11.6. 表达式上的索引

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

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

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

如果我们在 lower(col1) 操作的结果上定义索引, 那么这个查询就可以使用索引∶

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

如果我们要把这个索引声明为 UNIQUE,那么它会禁止创建那种 col1 数值只是大小写有区别的数据行, 以及 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',因此搜索的速度等效于任何其它简单的索引查询。 因此,表达式上的索引在检索速度比插入和更新速度更重要的场合下是有用的。