本文主要是介绍dremio虚拟数据湖反射说明,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
虚拟数据湖反射说明
1、基础概念
反射是从 现有表 或 视图派生的源数据或查询的优化具体化,类似于 “物化视图”。派生出 反射的表 或 视图是反射的锚点(基点或支柱点)
Dremio 的查询优化器可以通过使用一个 或 多个反射来部分或全部满足该查询,而不是处理基础数据源中的原始数据,从而加速对表或视图的查询。查询不需要直接引用反射。相反,Dremio 会动态重写查询,选择最小的 查询计算成本 ,以使用满足查询的反射。
当 Dremio 收到查询时,它首先确定所有 反射是否至少有一个表与查询引用的表和视图相同。如果有多个反射,Dremio 会对其进行评估,以确定它们是否满足查询。然后,如果其中 有 反射确实满足查询,Dremio 将生成使用它们的查询计划。
然后,Dremio 将计划的成本 与 直接针对表 执行查询的成本进行比较,并选择成本较低的计划。
最后,Dremio 执行选定的查询计划。通常,使用一个或多个反射的计划 比 对原始数据运行的计划成本更低。
例如 :
假设 从数据源创建了三个名为 customers , orders 、 和 的 items 表。有三个表进行单个查询的要求,创建了一个名为 order_detail “联接它们”的视图:
视图 order_detail 脚本 :
SELECT *
FROM order
INNER JOIN customer
ON order.cust_id = customer.cust_id
INNER JOIN item
on order.item_id = item.item_id)
而 现在 我们 想在 基于 视图 order_detail 上 进行数据分析,并创建了一个名为 customer_summary_US 的视图
视图 customer_summary_US 脚本 :
select cust_name,city,count(item_id),sum(item_price)
from order_detail
where cust_country = 'US'
group by cust_name
order by sum(item_price) DESC
由于此查询是计算密集型的,需要一些时间来运行,并且是经常运行的查询,因此可以 根据最佳做法从 视图 customer_summary_US 创建反射。
当业务分析师从其 BI 客户端应用程序运行查询时,Dremio 的查询计划器会针对反射 而不是 视图 customer_summary_US 运行查询,即使查询引用的 视图这个视图 。这样 查询运行速度要快得多,因为运行它的 Dremio 引擎不必通过表和视图下降到 数据源中的原始数据。
如图所示:
2、反射的类型
反射主要有两种类型:1、行反射 / 聚合反射
2、外部的反射
- 行 反射
此类型的反射由创建它的基础表或视图的所有行 和 一个或多个字段组成。最基本的原始反射等同于对应表或视图的 SELECT * FROM 。您可以通过对数据进行垂直分区(选择字段的子集)、水平对数据进行分区(通过将一个或多个列定义为分区键,并选择性地对它们应用分区转换)以及对一个或多个字段上的数据进行排序来自定义行反射
行反射的记录数 与其 锚点相同,但通常只是锚点大小的一小部分。在许多情况下,用户只查询列的一小部分,因此,在原始反射中仅包含这些列是有必要 的。
使用行反射的好处
1:加速对未优化数据或慢速存储的查询
根据源的不同,基础表或视图对于扫描密集型工作负载来说可能不是最佳的。此外,数据格式对于扫描(例如 JSON、CSV)可能效率低下,并且源可能只能通过慢速网络连接访问。如果源数据以非列格式存储,则使用原始反射可以显著提高查询性能。
- 加速 “大海捞针式” 查询
行反射以针对扫描进行优化的形式保留行级数据。您可以对特定字段上的数据进行排序 和 分区,以允许 Dremio 的查询优化器利用数据的物理组织方式来提高查询性能。
3、在生产数据源 上使用更少的资源
应用于查询中数据的转换的计算成本可能很高,尤其是对于精心设计的 CASE 语句和函数。查询可以使用存储转换结果的行反射,而不是使用系统资源来计算昂贵的转换。通过使用此类预先计算的结果,查询可以实现亚秒级响应时间。
4、加速对表或视图中 列 子集的查询
当一个表或视图包含数百个字段时,针对它的查询通常不包括每个字段。如果对字段子集创建反射,则 Dremio 的查询优化器会使用最少的字段来满足对表或视图的查询,从而需要扫描的数据要少得多。
5、加速对表或视图中 行 子集的查询
将数据过滤为子集 能计算 成本很高。此外,生成的子集可能明显小于总表或视图,这意味着扫描的数据远远多于必要的数据。当您选择 要对反射进行分区的字段时,Dremio 会维护数据的物理分区。Dremio 的查询优化器会在适当的时候修剪分区以优化查询执行。
6、加速执行 复杂关联 的查询
在表和/或视图之间联接数据可能会占用大量 CPU 和内存,尤其是当所涉及的表和视图大于内存,或者表和视图位于不同的位置时。使用原始反射预 联 接来自一个或多个源的数据可以显著提高性能。
7、加速对大型表或视图进行排序的查询
对未排序的大型表或视图进行排序可能会占用大量内存,尤其是当所涉及的表或视图大于内存时。您可以创建已对数据进行排序的原始反射。
- 聚合 反射
这种反射加速了涉及聚合的 BI 样式查询(GROUP BY 查询) 它们还可以配置为处理数据源字段的子集。
聚合反射是锚点的摘要,因此应具有较少的记录。聚合反射中的记录总数可以计算为每个维度列中唯一值数的乘积。当维度列中的唯一值数较少时,聚合量会相对较小,而当唯一值较多时,聚合量会较大。
虽然可以定义具有与其锚点相同数量记录的聚合反射(通过选择与表或视图具有相同基数的维度),但这会破坏聚合反射的目的,并且等效于在该表或视图上使用 行反射。
使用聚合反射的好处
1、使用聚合反射来存储表或视图中维度组合的预计算聚合。这样做可以提高数据使用者发出的查询中 GROUP BY 语句以及 SQL 聚合函数(如 SUM 和 AVG)的效率。
2、通过预聚合数据和预计算度量(总和、计数、最小值、最大值等),可以在查询运行时完全绕过这些昂贵的(CPU、RAM(内存))操作
- 外部 反射
解释 :派生表 :with as 出的临时 表 或者 select 出的 子查询 表
您可以通过针对连接数据源中的表具体化运行查询来加速查询。选择源数据,然后创建派生表,例如聚合。接下来,在 Dremio 中,定义与派生表匹配的视图。最后,将视图映射到派生表。映射是外部反射。
Dremio 用户可以查询视图,查询规划器在为这些查询设计最佳计划时可以考虑使用外部反射。
详情 请转到 :创建和编辑反射 |Dremio 文档 --- Creating and Editing Reflections | Dremio Documentation
3、反射的延展性
星型模型 和 雪花模型
当通过连接在数据集上实现反射时,Dremio 会保留统计数据并检测每个连接的关系(例如 1对1、1-多)。如果联接是非展开的,则 Dremio 可以利用此属性来加速更大的查询集。非展开联接是左表中每行最多参与一次结果的联接。
1-1
如果用户在数据集上创建了一个反射,该反射将事实数据表与三维表连接起来,则该反射满足上述条件,Dremio 可以加速包含这些连接的任何子集的查询(例如,仅与其中一个维度表连接的事实表),而无需定义多个反射。行反射和聚合反射都可以支持星片加速。
1-多
雪花模型:
星型模型:
4、创建行反射和聚合反射的最佳实践
1、为昂贵的查询模式设计反射
1:查看查询历史记录(作业 job),以确定提交的最昂贵和 最频繁的查询。
2:在配置文件中查找这些查询。由执行成本高昂的扫描、联接和聚合的多个查询引用的表和视图是反射的良好候选项。
3:检查引用同一表或视图的选定查询的 SQL 以查找可帮助您定义对该表或视图的反射以满足尽可能多的查询的模式。
2、避免“越多越好”的方法
创建比 数据 所需 还多 的反射的可能会导致损失 您的环境最佳资源,无论是在系统资源方面,还是在使用这些资源所花费的时间和精力方面。
3、建立何时创建反射的标准
仅当数据使用者遇到查询响应缓慢或报表不符合既定 SLA 时,才创建它们。
SLA 的定义:服务等级协议(英语:service-level agreement,缩写SLA),是服务提供商与客户之间定义的正式承诺。SLA的概念,对互 联网公司来说就是服务可用性的一个保证。
4、在他们完成最多工作的地方创建反射,而不会重复其他反射的工作
在创建表和视图时,应按层创建它们:
1:底层或第一层由您的表 组成
2:第二层是视图,每个表对应一个视图
用于为下一层中的视图进行轻量级数据准备。在这里,管理员可以创建视图,以执行有限的强制转换、类型转换和字段重命名,以及编辑敏感信息以及其他准备操作。管理员还可以通过子设置其他图层中的用户无法访问的行和字段来增加安全性。数据已被轻微清理,并仅限于具有业务知识的人群,这些知识使他们能够使用这些视图来构建数据使用者可以使用的高阶视图。然后,管理员将对这些视图的访问权限授予在下一层中创建视图的用户,而无法查看表中的原始数据。
3:数据转换层
在第三层中,用户创建执行联接和其他昂贵操作的视图。此层是对数据进行密集工作的地方。然后,这些用户从他们的视图创建反射(行、聚合或两者)。
4:可视化层
用户可以为仪表板、报表和可视化工具创建轻量级视图。它们还可以根据需要创建聚合反射。
5、建立一个例程,用于检查查询计划器使用反射的频率
通过以下下sql 可查看反射 历程
SELECT * FROM sys.reflections;SELECT * FROM sys.reflection_dependencies;SELECT * FROM sys.materializations;
6、水平分区具有多行的反射
如果在数据反射中选择要分区的字段,则 Dremio 会将记录物理分组到文件系统上的公共目录中。
例如,如果按“国家/地区”字段进行分区,其中值是国家/地区名称(如 US、UK、DE 和 CA)的两个字母缩写,则 Dremio 会将每个国家/地区的数据存储在名为 US、UK、DE、CA 等的单独目录中。此优化允许 Dremio 根据查询扫描目录的子集,这是一种称为分区修剪的优化。
如果用户查询 Country 值为 US 或 UK 的记录,则 Dremio 可以应用分区修剪以仅扫描 US 和 UK 目录,从而显著减少为查询扫描的数据量。
在为数据反射选择分区字段时,请注意以下问题:
1:该字段是否在许多查询中使用?
2:字段中的唯一值是否相对较少(低基数)?
要对数据进行分区,Dremio 必须首先对所有记录进行排序,这会消耗资源。因此,仅对可用于优化查询的字段对数据进行分区。此外,字段的唯一值数应相对较小,以便 Dremio 仅创建相对较少的分区。如果字段中的所有值都是唯一的,则分区的成本将大于收益。
通常,Dremio 建议反射的分区总数小于 10,000
由于反射是作为 Apache Iceberg 表创建的,因此您可以使用分区转换来指定要应用于分区列以生成分区值的转换。例如,如果选择对时间戳列进行分区,则可以设置分区转换,以生成这些时间戳中的年、月、日或小时分区值。下表列出了可供选择的分区转换。
注意:
1:如果某列被列为分区列,则该列不能同时作为同一反射的排序列列出。
2:在聚合反射中,指定为分区列或用于转换的每个列也必须作为维度列列出。
3:在行反射中,指定为分区列或用于转换的每个列也必须列为显示列
值 | 分区转换的类型 | 描述 |
IDENTITY | identity(<column_name>) | 为每个值创建一个分区。这是默认转换。如果未为 name 属性命名的列指定任何转换,则执行 IDENTITY 转换。该列可以使用任何受支持的数据类型 |
YEAR | year(<column_name>) | 按年份划分。该列必须使用 DATE 或 TIMESTAMP 数据类型 |
MONTH | month(<column_name>) | 按月划分。该列必须使用 DATE 或 TIMESTAMP 数据类型。 |
DAY | day(<column_name>) | 等效于 dateint 的分区。该列必须使用 DATE 或 TIMESTAMP 数据类型。 |
HOUR | hour(<column_name>) | 等效的 dateint 和 hour 的分区。该列必须使用 TIMESTAMP 数据类型。 |
BUCKET | bucket(<integer>, <column_name>) | 将数据分区为整数指定的分区数。例如,如果指定了整数值 N,则数据将分区为 N 个分区,或者(0 到 (N-1))个分区。存储单个行的分区是通过对列值进行哈希处理然后计算 <hash_value> mod N 来确定的。如果结果为 0,则该行位于分区 0 中;如果结果为 1,则该行位于分区 1 中;等等。 该列可以使用 DECIMAL、INT、BIGINT、VARCHAR、VARBINARY、DATE 或 TIMESTAMP 数据类型。 |
TRUNCATE | truncate(<integer>,<column_name>) | 如果指定的列使用整数或长数据类型,则按以下方式截断列值: 对于任何 truncate(L, col) ,将列值截断为小于列值的 L 的最大倍数。例如,假设指定的转换是 truncate(10, intColumn) 。值 1 被截断为 0,该行将放置在分区 0 中。值 247 被截断为 240,该行被放置在分区 240 中。如果转换为 truncate(3, intColumn) ,则值 13 将截断为 12,并将该行放在分区 12 中。值 255 不会被截断,因为它可以被 3 整除,并且该行位于分区 255 中。 该列可以使用 DECIMAL、INT、BIGINT、VARCHAR 或 VARBINARY 数据类型。 注意:截断转换不会更改列值。它使用列值来计算要在其中放置行的正确分区。 |
7、分区反射,允许基于分区的增量刷新
反射中数据的增量刷新比完全刷新快得多。基于分区的增量刷新基于 元数据,用于识别已修改的分区并将刷新范围限制为仅这些分区。
对于基于分区的增量刷新,必须对 基表 及 其反射进行分区,并且它们使用的分区转换必须兼容。上表列出了在基表上转换的分区和反射上的分区转换是兼容的:
注意:
1:如果基表和反射都使用截断分区转换,请遵循以下有关截断长度的规则:
2:如果分区列使用 String 数据类型,则用于反射的截断长度必须小于或等于用于基表的截断长度。
3:如果分区列使用 Integer 数据类型,则反射 (A) 上的截断长度除以基表 (B) 上的截断长度的余数必须等于 0: A MOD B = 0
4:如果分区列使用任何其他数据类型,则截断长度必须相同。
5:如果基表使用 Bucket 分区转换,则无法进行基于分区的增量刷新。
8、对超大型基表中时间戳数据的聚合反射进行分区
假设您要在具有数十亿行的基表上定义聚合反射。基表包含一个使用 TIMESTAMP 数据类型或将时间戳作为字符串包含的列,并且基表在该列上进行分区
在聚合反射中,您计划聚合基表中的时间戳数据。但是,要获得基于分区的增量刷新的好处,您需要以与基表上的分区兼容的方式对反射进行分区。您可以通过以下两种方式之一使分区兼容:
1:通过在基表上定义视图,然后在该视图上定义聚合反射
2:通过使用高级反射编辑器在基表上定义聚合反射
1:定义视图上的聚合反射
如果基表中的时间戳列使用 TIMESTAMP 数据类型,请使用此表中的函数之一在视图中定义相应的列。您可以对视图列上的聚合反射进行分区,并使用与函数对应的分区转换。
视图定义中的函数 | 对应的分区转换 |
DATE_TRUNC('HOUR', <base_table_column>) | HOUR(<view_col>) |
DATE_TRUNC('DAY', <base_table_column>) | DAY(<view_col>) |
DATE_TRUNC('MONTH', <base_table_column>) | MONTH(<view_col>) |
DATE_TRUNC('YEAR', <base_table_column>) | YEAR(<view_col>) |
CAST <base_table_column> as DATE | DAY(<view_col>) |
TO_DATE(<base_table_column>) | DAY(<view_col>) |
如果基表中的时间戳列使用 STRING 数据类型,请使用此表中的函数之一在视图中定义相应的列。您可以对视图列上的聚合反射进行分区,并使用与函数对应的分区转换。
视图定义中的函数 | 对应的分区转换 |
LEFT(<base_table_column>, X) | TRUNCATE(<view_col>, X) |
SUBSTR(<base_table_column>, 0, X) | TRUNCATE(<view_col>, X) |
SUBSTRING(<base_table_column>, 0, X) | TRUNCATE(<view_col>, X) |
2: 在基表上定义聚合反射
在高级视图中创建或编辑聚合反射时,如创建和编辑反射中所述,请执行以下步骤:
1: 将基表的时间戳列设置为维度。
2: 单击绿色圆圈旁边的向下箭头。
3: 选择“日期”作为日期粒度。
9、对高基数字段的反射进行 排序
sort 选项可用于优化使用筛选器或范围查询,尤其是在具有高基数的字段上。如果启用了排序,则在查询执行期间,Dremio 会根据排序字段上的筛选器跳过大型记录块。
如果反射跨越多个节点并由多个分区组成,则 Dremio 会在查询执行期间对数据进行排序。
在单个数据反射中对多个字段进行排序通常不会显著提高读取性能,并会增加维护任务的成本。
对于需要对多个字段进行排序的工作负载,请考虑创建多个反射,每个反射都在单个字段上进行排序。
10、基于多个查询的联接的联接创建反射
表和/或视图之间的关联往往很昂贵。您可以通过仅在构建和刷新反射时执行联接来降低联接的成本。
作为管理员,您可以识别一组使用类似联接的查询。然后,您可以创建一个常规查询,该查询使用基于相似联接的联接,但不包括组中查询的任何其他谓词。此泛型查询可以用作 行反射和/或聚合反射 的基础。
例如 :请考虑以下三个查询,它们在视图 A、B 和 C 上使用类似的联接:
select a.col1
,b.col1
,c.col1
from a
join b
on (a.col4 = b.col4)
join c
on (c.col5 = a.col5)
where a.size = 'm'
and a.col3 > '2001-01-01'
and b.col3 in ('red', 'blue', 'green')
select a.col1
,a.col2
,c.col1
,count(b1)
from a
join b
on (a.col4 = b.col4)
join c
on (c.col5 = a.col5)
where a.size = 'm'
and b.col2 < 10
and c.col2 > 2
group by a.col1
,a.col2
,c.col1
select a.col1
,b.col2
from a
join b
on (a.col4 = b.col4)
join c
on (c.col5 = a.col5)
where c.col1 = 123
因此 :您可以编写并运行此通用查询,以创建原始反射以加速所有三个原始查询
select a.col1
,a.col2
,a.col3
,b.col1
,b.col2
,b.col3
,c.col1
,c.col2
from a
join b
on (a.col4 = b.col4)
join c
on (c.col5 = a.col5)
这篇关于dremio虚拟数据湖反射说明的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!