索引列不必只是底层表中的一列,也可以是从该表的某列或多个列计算出的某个函数或标量表达式。此功能对于根据计算结果快速访问表非常有用。
例如,执行不区分大小写的比较的常见方法是使用 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
命令的语法通常要求用括号括住索引表达式。当表达式仅为函数调用时,可省略这些括号,如同第一个示例中所示的那样。
维护索引表达式相对昂贵,因为必须为每一行插入和非 HOT 更新计算派生表达式。但是,在索引搜索期间不会重新计算索引表达式,因为它们已经存储在索引中。在上面的两个示例中,系统将查询视为 WHERE indexedcolumn = 'constant'
,并且搜索速度等同于其他任何简单索引查询。因此,当检索速度比插入和更新速度更为重要时,表达式索引非常有用。