11.7. 表达式上的索引

索引并非一定要是一个底层表的字段,还可以是一个函数或者从一个或多个字段计算出来的标量表达式。 这个特性对于快速访问那些基于计算结果的表非常有用。

比如,做大小写无关比较的常用方法是使用lower函数:

SELECT * FROM test1 WHERE lower(col1) = 'value';

如果我们在lower(col1)函数的结果上定义索引

CREATE INDEX test1_lower_col1_idx ON test1 (lower(col1));

那么上述查询就可以使用该索引。如果我们把这个索引声明为UNIQUE, 那么它会禁止创建那种col1数值只是大小写有别或完全相同的数据行。 因此,在表达式上的索引可以用于强制那些无法定义为简单唯一约束的约束。

另外一个例子是,如果我们经常使用下面这样的查询:

SELECT * FROM people WHERE (first_name || ' ' || last_name) = 'John Smith';

那么我们就值得创建下面这样的索引:

CREATE INDEX people_names ON people ((first_name || ' ' || last_name));

CREATE INDEX命令的语法通常要求在索引表达式周围书写圆括弧, 就像我们在第二个例子里显示的那样。如果表达式只是一个函数调用, 那么可以省略,就像我们在第一个例子里显示的那样。

从维护角度来看,索引表达式相对费劲一些,因为在插入数据行或者更新数据行的时候, 都必须为每一行计算生成的表达式。不过,索引表达式不是在索引查找的时候进行计算的, 因为它们已经存储在索引里了。在上面的两个例子里,系统都把查询看做只是 WHERE indexedcolumn = 'constant',所以搜索的速度等效于任何其它简单的索引查询。 因此,表达式上的索引在检索速度比插入和更新速度更重要的场合下是有用的。