在大部分传统数据库中,索引能够极大地改善数据访问时间。不过,在一个Greenplum之类的分布式数据库中,索引应该被更保守地使用。Greenplum数据库会执行非常快的顺序扫描,索引则使用一种随机搜索的模式在磁盘上定位记录。Greenplum的数据分布在Segment上,因此每个Segment会扫描全体数据的一小部分来得到结果。通过表分区,要扫描的数据量可能会更少。因为商业智能(BI)查询负载通常会返回非常大的数据集,使用索引并不是很有效。
首先在不加索引时尝试用户的查询负载。索引更有可能为OLTP负载改进性能,在那种场景中查询会返回一个单一记录或者数据的一个小的子集。在被压缩过的追加优化表上,索引也可以提高返回一个目标行集合的查询的性能,因为优化器在适当的时候可以使用一种索引访问方法而不是全表扫描。对于压缩过的数据,使用一种索引访问方法意味着只有必要的行会被解压。
Greenplum数据库会自动为带有主键的表创建PRIMARY KEY约束。要在一个被分区的表上创建索引,就在用户创建的分区表上创建一个索引。该索引会被传播到Greenplum数据库所创建的所有子表上。不支持在Greenplum数据库为分区表创建的子表上创建索引。
注意一个UNIQUE CONSTRAINT(例如PRIMARY KEY CONSTRAINT)会隐式地创建一个UNIQUE INDEX,它必须包括分布键中所有的列以及任何分区键。UNIQUE CONSTRAINT会在整个表上被强制要求,包括所有的表分区(如果有)。
索引会增加一些数据库负担,它们使用存储空间并且在表被更新时需要被维护。要确保查询负载会用到用户创建的索引,并且检查用户增加的索引是否改进了查询性能(与表的顺序扫描相比)。要确定是否使用了索引,检查查询的EXPLAIN计划。
在创建索引时请考虑以下几点。
使用CLUSTER命令根据一个索引从物理上重新排序一个非常大的表可能会花费很长的时间。为了更快达到同样的结果,用户可以通过创建一个中间表并且按照想要的顺序重载数据来手工在磁盘上重排数据。例如:
CREATE TABLE new_table (LIKE old_table)
AS SELECT * FROM old_table ORDER BY myixcolumn;
DROP old_table;
ALTER TABLE new_table RENAME TO old_table;
CREATE INDEX myixcolumn_ix ON old_table;
VACUUM ANALYZE old_table;
Greenplum数据库数据库支持Postgres索引类型B-树和GiST,不支持Hash和GIN索引。每一种索引类型都使用一种不同的算法,它们最适合的查询类型也不同。B-树索引适合于最常见的情况并且是默认的索引类型。对于这些类型的描述请见PostgreSQL文档中的索引类型。
注意: 只有索引键的列与Greenplum分布键相同(或者是其超集)时,Greenplum数据库才允许唯一索引。在追加优化表上不支持唯一索引。在分区表上,唯一索引无法在一个分区表的所有子表分区之间被实施。唯一索引只能在一个分区内实施。
Greenplum数据库提供位图索引类型。位图索引最适合于拥有大量数据、很多临时查询以及少量数据修改(DML)事务的数据仓库应用和决策支持系统。
一个索引提供了指向表中包含一个给定键值的行的指针。常规索引存储了每个键存储了一个元组ID的列表,列表中的元组ID对应于具有那个键值的行。位图索引为每一个键值都存储一个位图。常规索引可能会比表中的数据大几倍,但位图索引提供了和常规索引相同的功能并且只需要被索引数据尺寸的一小部分。
位图中的每一个位对应于一个可能的元组ID。如果该位被设置,则具有相应元组ID的行包含该键值。一个映射函数负责将这个位的位置转换成一个元组ID。位图被压缩存储。如果可区分键值的数量很小,位图索引会小很多同时也会被压缩得更好,并且比常规索引节省可观的空间。一个位图索引的尺寸与该表中行数乘以被索引列中可区分值数量的结果成比例。
位图索引对于在WHERE子句中包含多个条件的查询最有效。满足某些但不是全部条件的行在访问表之前就会被过滤掉。这通常会极大地改善响应时间。
位图索引最适合用户只查询数据而不更新数据的数据仓库应用。对于拥有100至100,000个可区分值的列并且当被索引列常常与其他被索引列联合查询时,位图索引表现最好。低于100个可区分值的列通常无法从任何类型的索引受益,例如有两个可区分值的性别列(男和女)。而在具有超过100,000个可区分值的列上,位图索引的性能和空间效率会衰退。
位图索引能够提升ad hoc查询的查询性能。在将结果位图转换成元组ID之前,一个查询的WHERE子句中的AND以及OR条件可以通过在位图上直接执行相应的布尔操作快速地解决。如果结果行数很小,查询能够在不做全表扫描的情况下很快地被回答。
不要为唯一列或者具有高基数数据的列使用位图索引,例如顾客姓名或者电话号码。位图索引的性能增益和磁盘空间优势在具有100,000或者更多唯一值的列上开始减小,这与表中的行数无关。
位图索引不适合有大量并发事务修改数据的OLTP应用。
请保守地使用位图索引。测试并且比较使用索引和不使用索引的查询性能。只有被索引列的查询性能有提升时才增加索引。
CREATE INDEX命令在一个表上定义一个索引。例如,要在表employee的gender列上创建一个B-树索引:
CREATE INDEX gender_idx ON employee (gender);
要在表films中的列title上创建一个位图索引:
CREATE INDEX title_bmp_idx ON films USING bitmap (title);
Greenplum数据库的索引并不要求维护和调优。用户可以检查实际的查询负载使用了哪些索引。使用EXPLAIN命令可以检查一个查询的索引使用。
查询计划展示了数据库将用来回答一个查询的步骤或者计划节点以及每一个计划节点的时间估计。要检查索引的使用,请在用户的EXPLAIN输出中寻找以下查询计划节点类型:
用户必须做实验来确定要创建哪些索引。请考虑以下几点。
使用REINDEX命令可以重建一个表现不好的索引。 REINDEX使用存储在一个索引的基表中的数据重建该索引来替换该索引。
REINDEX my_table;
REINDEX my_index;
DROP INDEX命令移除一个索引。例如:
DROP INDEX title_idx;
在载入数据时,删除所有索引、载入数据然后重建索引会更快。
评论区(0)