部分索引

部分索引允许指定要添加到索引的行和列的子集。

部分索引如何工作

当创建部分索引时,Hubble会在索引的布尔谓词表达式中的列和行评估为true,创建行值子集的排序副本,而不修改表本身中的值。

Hubble可以使用部分索引对部分索引隐含的任何行子集高效地执行查询。如果可能,基于成本的优化器会创建一个计划,将对部分索引隐含的行的表扫描限制为仅索引中的行。

部分索引可以通过多种方式提高集群性能:

  • 它们包含的行数少于完整索引,因此在集群上创建和存储它们的成本更低。

  • 对包含在部分索引中的行的读取查询仅扫描部分索引中的行。

  • 对具有部分索引的表的写入查询仅在插入的行满足部分索引谓词时才执行索引写入。这与对具有完整索引的表的写入查询形成对比,后者在插入的行修改索引列时会产生完整索引写入的开销。

以下有具体示例。

创建部分索引

要创建部分索引,请使用带有定义谓词WHERE表达式CREATE INDEX的标准子句的语句。

例如,要在表的列xy表上定义部分索引,过滤列中z大于1的行:

create index on test (x, y) where z > 1;

以下查询使用部分索引:

select x,y from test where z > 1;
select x,y from test where z = 2;

以下查询不使用部分索引:

select x,y from test;
select x,y from test where z = 0;

在定义谓词表达式时,请遵循:

  • 谓词表达式必须产生一个布尔值。
  • 谓词表达式只能引用被索引表中的列。
  • 谓词中使用的函数必须是不可变的。例如,now()函数在谓词中是不允许的。

唯一的部分索引

可以使用对行的子集强制唯一性CREATE UNIQUE INDEX ... WHERE ...语句。

要在列ab表上定义唯一的部分索引,过滤列中c等于的行'n':

create unique index on t (a, b) where c = 'n';

这会创建一个部分索引和对等于UNIQUE行子集的约束。

索引提示

查询可以强制使用特定的部分索引(也称为'索引提示'),就像使用完整索引一样。但是,与全索引不同,部分索引不能用于满足所有查询。

限制

  • Hubble目前不支持导入带有部分索引的表的语句。

  • Hubble目前不支持多个索引的INSERT ON CONFLICT DO UPDATE语句。

示例

创建一个部分索引,在行的子集上强制执行唯一性

create table cust_info (
                  id UUID not null DEFAULT gen_random_uuid(),
                  name string NULL,
                  addr string);
                  
insert into cust_info(id, addr, name) values (gen_random_uuid(), 'beijing', 'daxing');                  
insert into cust_info(id, addr, name) values (gen_random_uuid(), 'beijing', 'fangshan');                  
insert into cust_info(id, addr, name) values (gen_random_uuid(), 'beijing', 'chaoyang');                  
                  

要限制表中行的子集,以便该子集中特定列的所有值都是唯一的。

例如,地点的每个用户都必须有一个唯一的名字。

create unique index on cust_info(name) where addr='beijing';

这将创建一个部分索引和仅对行子集的UNIQUE约束

insert into cust_info(id, addr, name) values (gen_random_uuid(), 'beijing', 'chaoyang');
ERROR: duplicate key value violates unique constraint "cust_info_name_key"
SQLSTATE: 23505
DETAIL: Key (name)=('chaoyang') already exists.
CONSTRAINT: cust_info_name_key

因为唯一部分索引谓词仅暗示行where addr='beijing',所以UNIQUE约束不适用于表中的所有行。