聚合索引
聚合索引的主要目的是提升查询性能,特别是在涉及聚合查询 (如MIN、MAX和SUM)的场景中。它通过预先计算并存储查询结果在单独的块中,从而无需扫描整个表,加快数据检索速度。在使用聚合索引时,请注意以下事项:
-
创建聚合索引时,限制其使用于标准的聚合函数(例如,AVG、SUM、MIN、MAX、COUNT和GROUP BY),同时注意GROUPING SETS、窗口函数、LIMIT和ORDER BY不被接受,否则会报错:
Currently create aggregating index just support simple query, like: SELECT ... FROM ... WHERE ... GROUP BY ...
。 -
创建聚合索引时定义的查询过滤范围应与实际查询的范围匹配或包含实际查询的范围。
-
要确认聚合索引是否对查询有效,请使用EXPLAIN命令分析查询。
-
如果不再需要聚合索引,请考虑删除它。请注意,删除聚合索引不会移除关联的存储块。要同时删除块,请使用VACUUM TABLE命令。要禁用聚合索引功能,请将
enable_aggregating_index_scan
设置为0。
刷新聚合索引
由于表在创建聚合索引后可能会进行数据插入和更新,因此聚合索引需要定期刷新。您有以下选项来刷新聚合索引:
-
自动刷新:如果聚合索引使用SYNC关键字创建,当表接收到可能影响查询结果的数据更新时,聚合索引将自动刷新。更多信息,请参见CREATE AGGREGATING INDEX。
-
手动刷新:如果聚合索引未使用SYNC关键字创建,聚合索引不会自动刷新。您可以使用REFRESH AGGREGATING INDEX命令手动刷新。在这种情况下,Databend建议在执行相关查询之前刷新聚合索引。
Databend中的自动刷新机制可能会影响大量数据加载的持续时间。这是因为Databend会延迟数据加载结果,直到自动刷新的聚合索引已更新以反映最新结果。Databend Cloud用户建议使用手动刷新机制。这是因为Databend Cloud会自动在后台更新聚合索引,即使对于未使用SYNC关键字创建的索引,也会响应表数据的变化进行更新。
管理聚合索引
Databend提供了多种命令来管理聚合索引。详情请参见聚合索引。
使用示例
此示例展示了聚合索引的利用方式,并说明了它们对查询执行计划的影响。
-- 准备数据
CREATE TABLE agg(a int, b int, c int);
INSERT INTO agg VALUES (1,1,4), (1,2,1), (1,2,4), (2,2,5);
-- 创建聚合索引
CREATE AGGREGATING INDEX my_agg_index AS SELECT MIN(a), MAX(c) FROM agg;
-- 刷新聚合索引
REFRESH AGGREGATING INDEX my_agg_index;
-- 验证聚合索引是否有效
EXPLAIN SELECT MIN(a), MAX(c) FROM agg;
explain |
----------------------------------------------------------------------------------------------------------------------+
AggregateFinal |
├── output columns: [MIN(a) (#8), MAX(c) (#9)] |
├── group by: [] |
├── aggregate functions: [min(a), max(c)] |
├── estimated rows: 1.00 |
└── AggregatePartial |
├── output columns: [MIN(a) (#8), MAX(c) (#9)] |
├── group by: [] |
├── aggregate functions: [min(a), max(c)] |
├── estimated rows: 1.00 |
└── TableScan |
├── table: default.default.agg |
├── output columns: [a (#5), c (#7)] |
├── read rows: 4 |
├── read bytes: 61 |
├── partitions total: 1 |
├── partitions scanned: 1 |
├── pruning stats: [segments: <range pruning: 1 to 1>, blocks: <range pruning: 1 to 1, bloom pruning: 0 to 0>]|
├── push downs: [filters: [], limit: NONE] |
├── aggregating index: [SELECT MIN(a), MAX(c) FROM default.agg] |
├── rewritten query: [selection: [index_col_0 (#0), index_col_1 (#1)]] |
└── estimated rows: 4.00 |
-- 删除聚合索引
DROP AGGREGATING INDEX my_agg_index;
EXPLAIN SELECT MIN(a), MAX(c) FROM agg;
explain |
----------------------------------------------------------------------------------------------------------------------+
AggregateFinal |
├── 输出列: [MIN(a) (#3), MAX(c) (#4)] |
├── 分组依据: [] |
├── 聚合函数: [min(a), max(c)] |
├── 估计行数: 1.00 |
└── AggregatePartial |
├── 输出列: [MIN(a) (#3), MAX(c) (#4)] |
├── 分组依据: [] |
├── 聚合函数: [min(a), max(c)] |
├── 估计行数: 1.00 |
└── TableScan |
├── 表: default.default.agg |
├── 输出列: [a (#0), c (#2)] |
├── 读取行数: 4 |
├── 读取字节数: 61 |
├── 分区总数: 1 |
├── 扫描分区数: 1 |
├── 剪枝统计: [segments: <range pruning: 1 to 1>, blocks: <range pruning: 1 to 1, bloom pruning: 0 to 0>]
|
├── 下推: [filters: [], limit: NONE] |
└── 估计行数: 4.00 |