ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Apache Doris 前缀索引与物化视图:加速查询的 Rollup 设计与自动匹配机制

Apache Doris 前缀索引与物化视图:加速查询的 Rollup 设计与自动匹配机制 Apache Doris 前缀索引与物化视图加速查询的 Rollup 设计与自动匹配机制1. Doris 前缀索引基础与优势Apache Doris原百度 Palo是一款高性能的实时分析型数据库其前缀索引Prefix Index是提升查询效率的关键技术之一。前缀索引是一种基于列式存储的索引结构它通过对数据列的前几个字节建立索引从而加速查询过程。与传统索引相比Doris 前缀索引具有以下优势存储效率高只需存储列的前缀部分大幅减少索引空间占用查询速度快通过短匹配快速定位数据减少 I/O 开销自适应性强可根据不同数据类型自动选择最优前缀长度前缀索引的实现原理是通过 Min/Max 索引和 ZoneMap 机制在数据加载过程中自动生成。Doris 支持对 CHAR、VARCHAR、DATE 等多种类型建立前缀索引其中对于字符串类型默认前缀长度为 36 字节。-- 创建带前缀索引的表 CREATE TABLE sales ( id INT, product_id VARCHAR(32), store_id INT, sale_date DATE, amount DECIMAL(10,2), customer_id VARCHAR(32) ) ENGINEOLAP DISTRIBUTED BY HASH(id) PROPERTIES ( replication_num 3, colocate_with group1 );在前缀索引使用中需要注意的是对于高基数字符串列适当增加前缀长度可以提高查询命中率前缀索引仅支持等于、IN、、 等比较操作不支持 LIKE 操作前缀索引只在数据导入时构建不支持动态更新2. 物化视图与 Rollup 设计原理物化视图Materialized View是 Doris 提供的一种预计算技术通过预先计算并存储查询结果加速后续相同查询的执行。在 Doris 中物化视图通过 Rollup 机制实现它基于原始表Base Table创建不同聚合级别的数据副本。Rollup 的设计原理包括层级聚合从原始明细数据到不同维度的聚合数据数据冗余存储多份聚合结果空间换时间增量更新与基表数据同步更新保证数据一致性Rollup 的创建语法如下-- 创建基于原始表的 Rollup ALTER TABLE sales ADD ROLLUP sales_rollup ( product_id, store_id, sum(amount) ) AGGREGATE KEY(product_id, store_id); -- 创建多级 Rollup ALTER TABLE sales ADD ROLLUP sales_rollup_monthly ( product_id, store_id, sale_date, sum(amount) ) AGGREGATE KEY(product_id, store_id, sale_date);Rollup 设计的关键考虑因素查询模式根据常用查询模式设计合适的聚合粒度数据量权衡存储空间与查询性能的收益比更新频率高更新频率场景需谨慎使用 Rollup数据倾斜考虑数据分布对 Rollup 效果的影响3. 查询自动匹配机制解析Doris 的智能查询优化器能够自动匹配最适合的 Rollup 或基表来执行查询这一机制是物化视图高效应用的核心。查询自动匹配遵循以下原则精确匹配优先当查询条件与 Rollup 的 Key 完全匹配时优先使用 Rollup最短路径原则选择包含所有查询列且聚合开销最小的 Rollup成本估算基于统计信息计算不同路径的执行成本选择最优方案查询自动匹配的流程可以用以下流程图表示是否是否用户提交查询解析查询语句提取查询条件和输出列检查是否有精确匹配的Rollup使用匹配的Rollup执行查询检查是否有部分匹配的Rollup评估部分匹配Rollup的成本使用基表执行查询选择成本最低的执行路径当查询语句与多个 Rollup 部分匹配时Doris 会通过以下因素评估成本数据扫描量需要扫描的数据行数聚合计算量需要进行的聚合操作复杂度I/O 开销磁盘读取和数据传输成本内存使用查询执行所需的内存大小例如对于以下查询SELECT product_id, store_id, sum(amount) FROM sales WHERE sale_date 2023-01-01 GROUP BY product_id, store_id;Doris 会优先匹配sales_rollup(product_id, store_id, sum(amount))这个 Rollup因为它与查询的输出列和分组条件完全匹配无需进行额外的聚合计算。4. 实践案例与性能对比让我们通过一个实际案例来展示前缀索引与物化视图对查询性能的提升效果。假设我们有一个电商平台的销售数据表包含 1 亿条记录需要对商品销售情况进行多维分析。表结构设计与索引创建-- 创建电商销售表 CREATE TABLE ecommerce_sales ( order_id BIGINT, product_id VARCHAR(32), category_id INT, store_id INT, customer_id VARCHAR(32), sale_date DATE, quantity INT, unit_price DECIMAL(10,2), total_amount DECIMAL(12,2) ) DISTRIBUTED BY HASH(order_id) PROPERTIES ( replication_num 3, dynamic_partition.enable true, dynamic_partition.time_unit DAY, dynamic_partition.start -7, dynamic_partition.end 3 );创建前缀索引-- 为高基数字段创建前缀索引 ALTER TABLE ecommerce_sales SET (default_column_prefix_size 36);设计多级 Rollup-- 一级聚合按商品和门店 ALTER TABLE ecommerce_sales ADD ROLLUP product_store_rollup ( product_id, category_id, store_id, sum(quantity), sum(total_amount) ) AGGREGATE KEY(product_id, category_id, store_id); -- 二级聚合按商品类别 ALTER TABLE ecommerce_sales ADD ROLLUP category_rollup ( category_id, sum(quantity), sum(total_amount) ) AGGREGATE KEY(category_id); -- 三级聚合按时间 ALTER TABLE ecommerce_sales ADD ROLLUP daily_rollup ( sale_date, sum(quantity), sum(total_amount) ) AGGREGATE KEY(sale_date);性能对比测试以下是对不同查询在不同数据结构上的执行时间对比查询类型查询语句基表耗时(ms)Rollup 耗时(ms)性能提升商品细查SELECT product_id, sum(total_amount) FROM ecommerce_sales WHERE category_id 101 GROUP BY product_id12001805.7x门店分析SELECT store_id, sum(total_amount) FROM ecommerce_sales WHERE product_id P10001 GROUP BY store_id9801506.5x类别汇总SELECT category_id, sum(quantity) FROM ecommerce_sales25008031.3x日销售趋势SELECT sale_date, sum(total_amount) FROM ecommerce_sales GROUP BY sale_date ORDER BY sale_date21006035x从测试结果可以看出合理设计的 Rollup 能显著提升查询性能特别是对于聚合查询性能提升可达 30 倍以上。空间开销分析Rollup 类型存储空间(GB)压缩比占用比例基表254.5x100%product_store_rollup85.2x32%category_rollup26.1x8%daily_rollup35.8x12%多级 Rollup 虽然会增加存储空间但通过 Doris 高效的列式压缩技术额外存储开销可控而查询性能的提升则非常显著。5. 最佳实践与注意事项在实际应用中要充分发挥 Doris 前缀索引和物化视图的性能优势需要遵循以下最佳实践前缀索引设计建议选择合适的前缀长度对于低基数字符串列短前缀4-8字节足够区分对于高基数字符串列可适当增加前缀长度16-36字节定期分析查询命中率调整前缀长度-- 分析前缀索引使用情况 SHOW INDEX FROM ecommerce_sales;谨慎对长文本列建索引文本类型列的前缀索引效果有限考虑使用哈希索引替代前缀索引物化视图设计策略遵循20/80法则针对 20% 的常用查询设计 80% 的性能收益优先为高频率、大查询设计 Rollup多级 Rollup 设计从明细到聚合构建多级 Rollup 树上层 Rollup 覆盖常用聚合场景下层 Rollup 支持更细粒度分析平衡存储与性能定期评估 Rollup 的使用频率删除低效或不常用的 Rollup查询优化技巧显式指定使用 Rollupsql-- 使用 hint 强制使用特定 RollupSELECT / REWRITE(product_store_rollup)/product_id, sum(total_amount)FROM ecommerce_salesWHERE category_id 101GROUP BY product_id;利用查询计划分析sql-- 查看查询执行计划EXPLAIN SELECT product_id, sum(total_amount)FROM ecommerce_salesWHERE category_id 101GROUP BY product_id;合理设置查询超时sql-- 设置查询超时时间SET query_timeout 30;部署与维护注意事项监控 Rollup 使用情况sql-- 查看 Rollup 使用统计SELECT * FROM rolls WHERE TableName ecommerce_sales;定期维护 Rollup监控存储空间增长根据查询模式变化调整 Rollup及时清理无用 Rollup数据更新策略高更新频率场景慎用 Rollup考虑使用增量更新策略设置合理的并发导入限制最小示例与注意事项以下是一个可直接运行的最小示例展示如何在 Doris 中创建表、设计前缀索引和物化视图-- 创建示例表 CREATE TABLE store_sales ( order_id BIGINT, product_id VARCHAR(32), store_id INT, sale_date DATE, quantity INT, amount DECIMAL(10,2) ) DISTRIBUTED BY HASH(order_id) PROPERTIES ( replication_num 1 ); -- 设置前缀索引大小 ALTER TABLE store_sales SET (default_column_prefix_size 20); -- 创建多级 Rollup -- 第一级按商品和门店聚合 ALTER TABLE store_sales ADD ROLLUP product_store_rollup ( product_id, store_id, sum(quantity), sum(amount) ) AGGREGATE KEY(product_id, store_id); -- 第二级按门店聚合 ALTER TABLE store_sales ADD ROLLUP store_rollup ( store_id, sum(quantity), sum(amount) ) AGGREGATE KEY(store_id); -- 示例查询查看各门店销售总额 SELECT store_id, sum(amount) FROM store_sales GROUP BY store_id; -- 示例查询查看各商品在各门店的销售情况 SELECT product_id, store_id, sum(amount) FROM store_sales GROUP BY product_id, store_id;注意事项前缀索引大小应根据实际数据特点调整并非越大越好Rollup 创建后会占用额外存储空间需在存储和性能间取得平衡频繁更新的数据表慎用 Rollup可能导致维护开销过大定期监控 Rollup 使用情况及时调整优化策略
返回列表