Dremio查询加速技术全解析
1. 引言:Dremio的查询加速
在 Dremio 中,查询可以通过反射(Reflections)和结果缓存进行加速。
1.1.反射
反射是一种预先计算并优化的源数据或查询结果的副本,旨在提升查询性能。它派生自现有表或视图(称为其锚点)。反射可以是:
自主:由 Dremio 自动创建和管理。
手册:由用户创建和管理。
Dremio的查询优化器利用Reflections来加速查询,避免了扫描原始数据的需求。Dremio会自动重写查询以使用Reflections,当它们能提供所需结果时,无需用户直接引用这些Reflections。

当Dremio接收到查询时,它首先判断是否有任何Reflection与查询引用的表和视图至少有一个共同表。如果存在这样的Reflection,Dremio会评估它们以确定是否满足查询需求。随后,若有Reflection确实满足查询,Dremio会生成使用这些Reflection的查询计划。
Dremio随后将该计划的成本与直接对表执行查询的成本进行比较,并选择成本较低的计划。最后,Dremio执行选定的查询计划。通常情况下,使用一个或多个Reflection的计划比针对原始数据运行的计划成本更低。
1.1.1.反射类型
针对特定工作负载,有多种类型的Reflections可供选择:
- 原始反射:在保留与锚点相同记录数的同时允许列子集。它通过物化复杂视图、将非高性能源数据转换为针对大规模分析优化的Iceberg表格式,并利用分区和排序实现更快访问,从而提升查询性能。通过以优化格式预计算和存储数据,原始反射能显著降低查询延迟并提升整体效率。
 - 聚合反射:通过预计算选定维度和度量上的结果(如求和、计数、平均值、分组查询),加速涉及聚合操作的商业智能风格查询。通过预计算高开销运算,这类反射能在运行时显著提升查询性能。特别适用于需要对大型数据集频繁执行聚合分析的分析型工作负载。
 - 外部反射:引用外部数据源中的预计算表,而非在Dremio内部物化反射,从而消除刷新开销和存储成本。您可以通过在Dremio中定义与预计算表匹配的视图,并将该视图映射到外部数据源来使用外部反射。预计算表中的数据不会由Dremio刷新。查询该视图时,Dremio的查询规划器会利用外部反射生成最优执行计划,在无需额外占用Dremio存储空间的情况下提升查询性能。
 - 星花反射:通过利用事实表和维度表之间的预计算关系优化多表连接。当连接不重复行时,即使反射仅包含部分表连接,Dremio仍可使用反射加速查询,从而减少针对不同表组合创建多个反射的需求。
 
1.1.2.反射类型功能与数据格式兼容性矩阵
下表概述了主要Reflections功能在支持的数据格式中的可用性,包括版本特定增强功能,例如自主Reflections、实时Reflections和智能增量刷新。
|   数据格式  |    自主反思  |    自动原始数据+聚合推荐  |    手动反射  |    实时反射 (25.1+)  |    自动原始推荐(25.0+)  |    智能增量刷新 (24.3+)  |  
|   Iceberg  |    Yes  |    Yes  |    Yes  |    Yes  |    Yes  |    Yes  |  
|   UniForm  |    Yes  |    Yes  |    Yes  |    Yes  |    Yes  |    Yes  |  
|   Parquet  |    Yes  |    Yes  |    Yes  |    No  |    Yes  |    Yes  |  
|   Delta  |    No  |    No  |    Yes  |    No  |    No  |    No  |  
|   联合来源  |    No  |    No  |    Yes  |    No  |    No  |    No  |  
1.2.1.结果缓存
结果缓存通过复用先前执行的相同确定性查询的结果来提高查询性能,前提是基础数据集保持不变且先前执行由同一用户执行。结果缓存功能开箱即用,无需配置,可自动缓存和复用结果。无论查询是否使用结果缓存,其返回结果始终保持一致。
结果缓存与客户端无关,这意味着在Dremio控制台中执行的查询即使后续通过JDBC、ODBC、REST或Arrow Flight等其他客户端重新运行,也会产生缓存命中。要使查询使用缓存,其查询计划必须与原始缓存版本保持完全一致。对模式或数据集的任何更改都会生成新的查询计划,从而使缓存失效。
结果缓存还支持无缝协调器扩展,使新添加的协调器能够立即从先前缓存的结果中受益。
1.2.2.结果缓存支持的案例
查询结果在以下情况下会被缓存:
- 该SQL语句是一个SELECT语句。
 - 该查询从Iceberg、Parquet数据集读取,或从基于其他Dremio支持的数据源和格式(如关系数据库、CSV、JSON或TEXT)定义的原始Reflection读取。
 - 该查询不包含动态函数,例如QUERY_USER、IS_MEMBER、RAND、CURRENT_DATE或NOW。
 - 该查询未引用SYS或INFORMATION_SCHEMA表,也未使用外部查询。
 - 结果集大小,以 Arrow 格式存储时,小于或等于 20 MB。
 - 查询未在 Dremio 控制台中作为预览执行。
 
1.2.3.查看查询是否使用了结果缓存
在“作业”页面查看作业列表,以确定数据消费者的查询是否通过结果缓存得到了加速。
要确定查询是否通过结果缓存加速:
- 找到运行该查询的作业,并查找其旁边的闪电图标。该图标表示该查询已通过 Reflections 或结果缓存进行了加速处理。
 - 点击代表运行查询的作业所在行,即可查看作业摘要。右侧窗格中显示的摘要提供了查询是否通过结果缓存或Reflections加速的详细信息。
 

缓存结果存储在分布式存储中,配置于dremio.conf文件中。执行器将缓存条目以Arrow数据文件形式写入,并在处理导致缓存命中的SELECT查询时读取这些文件。协调器负责管理过期缓存文件的删除。
运行在某个Dremio协调器上的后台任务负责处理缓存过期。该任务每小时执行一次,将过去24小时内未被访问的缓存条目标记为过期,随后将其与关联的缓存文件一并删除。
注意事项与限制:通过Dremio控制台或REST客户端执行的SQL查询若访问缓存,会将缓存的查询结果重写入作业结果存储区以实现分页功能。该行为将在未来版本中增强。
2. 前端界面架构与组件设计
2.1 整体架构
用户界面层 (DAC/UI)
├── 反射管理界面 (Reflections.jsx)
├── 性能监控面板 (AccelerationController.jsx)
├── 配置表单 (AccelerationForm.jsx)
└── 实时监控组件 (AccelerationGridController.jsx) 
