本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
在 Amazon EMR 中使用物化视图
亚马逊 EMR 版本 7.12.0 及更高版本支持在 Glue 数据目录中创建和管理 Apache Iceberg 物化视图。 AWS 实体化视图是一种托管表,该表以 Apache Iceberg 格式存储 SQL 查询预先计算的结果,并随着基础源表的更改而增量更新。可以使用实体化视图来简化数据转换管道并提高复杂分析工作负载的查询性能。
当您在 Amazon EMR 上使用 Spark 创建物化视图时,视图定义和元数据存储在 Glue 数据 AWS 目录中。预先计算的结果以 Apache Iceberg 表的形式存储在您账户中的 Amazon S3 表存储桶或 Amazon S3 通用存储桶中。 AWS AWS Glue 数据目录使用托管计算基础架构自动监控源表并刷新物化视图。
主题
物化视图如何与 Amazon EMR 配合使用
物化视图通过 Apache Spark 的 Iceberg 支持与 Amazon EMR 集成。当您将 Spark 会话配置为使用 AWS Glue 数据目录时,您可以使用标准 SQL 语法创建实例化视图。当实体化视图提供更好的性能时,Spark 优化器可以自动重写查询进而使用这些视图,从而无需手动修改应用程序代码。
AWS Glue 数据目录处理物化视图维护的所有操作方面,包括:
-
使用 Apache Iceberg 的元数据层检测源表中的更改
-
使用托管的 Spark 计算计划和执行刷新操作
-
根据数据更改确定是执行完全刷新还是增量刷新
-
以 Apache Iceberg 格式存储预先计算的结果,便于多引擎访问
您可以使用与常规表相同的 Spark SQL 接口从 Amazon EMR 查询物化视图。也可以从其他服务访问预先计算的数据,包括 Amazon Athena 和 Amazon Redshift。
先决条件
要在 Amazon EMR 中使用物化视图,您需要:
-
一个 AWS 账户
-
运行 7.12.0 版或更高版本的 Amazon EMR 集群
-
在 Glue 数据目录中注册的 Apache Iceberg 格式 AWS 的源表
-
AWS 为源表和目标数据库配置的 Lake Formation 权限
-
向 AWS Lake Formation 注册的 S3 表存储桶或 S3 通用存储桶,用于存储物化视图数据
将 Spark 配置为使用实体化视图
要创建和管理物化视图,请使用所需的 Iceberg 扩展和目录设置配置 Spark 会话。配置会有所不同,具体取决于您的源表和实例化视图使用 S3 表存储桶还是 S3 通用存储桶。
为 S3 表进行配置
在将 S3 Tables 存储桶用于实例化视图时,请为源表和实例化视图配置单独的目录引用:
spark-sql \ --conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions \ --conf spark.sql.catalog.glue_catalog=org.apache.iceberg.spark.SparkCatalog \ --conf spark.sql.catalog.glue_catalog.type=glue \ --conf spark.sql.catalog.glue_catalog.warehouse=s3://amzn-s3-demo-bucket/warehouse \ --conf spark.sql.catalog.glue_catalog.glue.region=us-east-1 \ --conf spark.sql.catalog.glue_catalog.glue.id=111122223333 \ --conf spark.sql.catalog.glue_catalog.glue.account-id=111122223333 \ --conf spark.sql.catalog.glue_catalog.glue.lakeformation-enabled=true \ --conf spark.sql.catalog.s3t_catalog=org.apache.iceberg.spark.SparkCatalog \ --conf spark.sql.catalog.s3t_catalog.type=glue \ --conf spark.sql.catalog.s3t_catalog.glue.id=111122223333:s3tablescatalog/my-table-bucket \ --conf spark.sql.catalog.s3t_catalog.glue.account-id=111122223333 \ --conf spark.sql.catalog.s3t_catalog.glue.lakeformation-enabled=true \ --conf spark.sql.catalog.s3t_catalog.warehouse=s3://amzn-s3-demo-bucket/mv-warehouse \ --conf spark.sql.catalog.s3t_catalog.glue.region=us-east-1 \ --conf spark.sql.defaultCatalog=s3t_catalog \ // turn on automatic query rewrite (optional) --conf spark.sql.optimizer.answerQueriesWithMVs.enabled=true
为 S3 通用存储桶进行配置
使用 S3 通用存储桶时,请配置单一目录引用:
spark-sql \ --conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions \ --conf spark.sql.catalog.glue_catalog=org.apache.iceberg.spark.SparkCatalog \ --conf spark.sql.catalog.glue_catalog.type=glue \ --conf spark.sql.catalog.glue_catalog.warehouse=s3://amzn-s3-demo-bucket/warehouse \ --conf spark.sql.catalog.glue_catalog.glue.region=us-east-1 \ --conf spark.sql.catalog.glue_catalog.glue.id=111122223333 \ --conf spark.sql.catalog.s3t_catalog.glue.account-id=111122223333 \ --conf spark.sql.catalog.s3t_catalog.glue.lakeformation-enabled=true \ --conf spark.sql.defaultCatalog=glue_catalog \ // turn on automatic query rewrite (optional) --conf spark.sql.optimizer.answerQueriesWithMVs.enabled=true
启用增量刷新
要启用增量刷新优化,请将以下配置属性添加到 Spark 会话中:
spark-sql \ --conf spark.sql.optimizer.incrementalMVRefresh.enabled=true \
配置参数
以下配置参数控制实体化视图的行为:
-
spark.sql.extensions– 启用支持实体化视图所需的 Iceberg Spark 会话扩展。 -
spark.sql.optimizer.answerQueriesWithMVs.enabled– 启用自动查询重写,进而使用实体化视图 设置为 true 可激活此优化。 -
spark.sql.optimizer.incrementalMVRefresh.enabled– 启用增量刷新优化。设置为 true 可在刷新操作期间仅处理更改的数据。
创建实体化视图
您可以使用 CREATE MERATIALIZED VIEW SQL 语句创建实例化视图。视图定义将转换逻辑指定为引用一个或多个源表的 SQL 查询。
DLL
创建视图
{ CREATE OR REPLACE MATERIALIZED VIEW | CREATE MATERIALIZED VIEW [ IF NOT EXISTS ] } view_identifier [ view_clauses ] [ schedule_clauses ] AS [ select_statement ] view_clauses = { [ LOCATION location ] | [ PARTITIONED BY (col [, ...]) ] | [ COMMENT view_comment ] | [ SCHEDULE [ REFRESH ] schedule_clause ] } schedule_clause = { EVERY number { HOUR | HOURS | DAY | DAYS | WEEK | WEEKS } }
注意
视图子句必须出现在 select_statement 之前。
创建基本的物化视图
以下示例创建了一个实例化视图,该视图按客户汇总订单数据,在视图定义中使用具有三部分命名约定的完全限定表名:
CREATE MATERIALIZED VIEW customer_orders AS SELECT customer_name, COUNT(*) as order_count, SUM(amount) as total_amount FROM glue_catalog.sales.orders GROUP BY customer_name;
创建具有自动刷新功能的实体化视图
要配置自动刷新,请在使用视图定义中采用三部分命名规则的完全限定表名创建视图时指定刷新计划:
CREATE MATERIALIZED VIEW customer_orders SCHEDULE REFRESH EVERY 1 HOUR AS SELECT customer_name, COUNT(*) as order_count, SUM(amount) as total_amount FROM glue_catalog.sales.orders GROUP BY customer_name;
创建具有跨目录引用的实体化视图
当源表与实体化视图位于不同的目录中时,请在视图名称和视图定义中使用具有三部分命名约定的完全限定表名:
CREATE MATERIALIZED VIEW s3t_catalog.analytics.customer_summary AS SELECT customer_name, COUNT(*) as order_count, SUM(amount) as total_amount FROM glue_catalog.sales.orders GROUP BY customer_name;
查询实体化视图
创建实例化视图后,您可以使用标准 SQL SELECT 语句像查询任何其他表一样对其进行查询:
SELECT * FROM customer_orders;
自动查询重写
启用自动查询重写后,Spark 优化器会分析您的查询,并在实体化视图可以提高性能时自动使用这些视图。例如,如果执行以下查询:
SELECT customer_name, COUNT(*) as order_count, SUM(amount) as total_amount FROM orders GROUP BY customer_name;
只要实体化视图是最新的,Spark 优化器就会自动重写此查询,进而使用 customer_orders 实体化视图而不是处理基本订单表。
验证自动查询重写
要验证查询是否使用自动查询重写,请使用 EXPLAIN EXTENDED 命令:
EXPLAIN EXTENDED SELECT customer_name, COUNT(*) as order_count, SUM(amount) as total_amount FROM orders GROUP BY customer_name;
在执行计划中,在 BatchScan操作中查找物化视图名称。如果计划显示 g BatchScan lue_catalog.analytics.customer_orders 而不是 glue_catal BatchScan og.sales.orders,则查询已被自动重写为使用物化视图。
注意
创建实例化视图后,自动重写查询需要一段时间才能填充 Spark 元数据缓存。该过程通常在 30 秒内完成。
刷新实体化视图
可以使用两种方法刷新实体化视图:完全刷新或增量刷新。完全刷新会根据所有基表数据重新计算整个实体化视图,而增量刷新仅处理自上次刷新以来发生更改的数据。
手动完全刷新
要对实体化视图进行完全刷新,请执行以下操作:
REFRESH MATERIALIZED VIEW customer_orders FULL;
执行此命令后,查询实例化视图以验证更新的结果:
SELECT * FROM customer_orders;
手动增量刷新
要进行增量刷新,请确保在 Spark 会话配置中启用增量刷新,然后执行:
REFRESH MATERIALIZED VIEW customer_orders;
AWS Glue 数据目录根据视图定义和更改的数据量自动确定增量刷新是否适用。如果无法进行增量刷新,则操作将回退为完全刷新。
验证增量刷新执行情况
要确认增量刷新已成功执行,您可以通过运行以下命令来检查lastRefreshType表的属性:
SHOW TBLPROPERTIES <mvName>("lastRefreshType")
此外,这也可以通过修改 Spark 日志配置来启用调试日志记录来实现:
-
打开 Spark log4j 配置文件:
sudo vim /usr/lib/spark/conf/log4j2.properties -
添加以下记录器配置:
logger.spark.name = org.apache.spark.sql logger.spark.level = debug logger.inmemcache.name = org.apache.spark.sql.InMemMvMetadataCache logger.inmemcache.level = off -
执行刷新操作后,在 Spark 输出中搜索以下消息:
DEBUG RefreshMaterializedViewExec: Executed Incremental Refresh
管理实体化视图
Amazon EMR 提供用于管理物化视图生命周期的 SQL 命令。
描述实体化视图
要查看有关实体化视图的元数据,包括其定义、刷新状态和上次刷新时间戳,请执行以下操作:
DESCRIBE EXTENDED customer_orders;
更改实体化视图
要修改现有实体化视图的刷新计划,请执行以下操作:
ALTER MATERIALIZED VIEW customer_orders ADD SCHEDULE REFRESH EVERY 2 HOURS;
要移除自动刷新,请执行以下操作:
ALTER MATERIALIZED VIEW customer_orders DROP SCHEDULE;
删除实体化视图
要删除实体化视图,请执行以下操作:
DROP MATERIALIZED VIEW customer_orders;
此命令将实例化视图定义从 AWS Glue 数据目录中移除,并从 S3 存储桶中删除基础 Iceberg 表数据。
实体化视图的权限
要创建和管理物化视图,必须为创建视图的 IAM 角色(定义者角色)配置权限。亚马逊 EMR 支持两种权限模型:
-
仅限 IAM 策略 — 如果您使用 IAM 策略管理数据湖,则无需配置 AWS Lake Formation。
-
AWS 湖泊形成 — 如果您已经使用 AWS Lake Formation 来管理您的数据湖,则可以为物化视图配置 AWS Lake Formation 权限。
定义者角色所需的权限
定义者角色必须具有以下 Lake Formation 权限:
-
在源表上 – 不带行、列或单元格筛选条件的 SELECT 或 ALL 权限
-
在目标数据库上 – CREATE_TABLE 权限
-
关于 AWS Glue 数据目录 GetTable 和 CreateTable API 权限
创建实体化视图时,定义者角色的 ARN 存储在视图定义中。执行自动刷新操作时, AWS Glue 数据目录将扮演此角色。如果定义者角色失去对源表的访问权限,则在恢复权限之前,刷新操作将失败。
授予对实体化视图的访问权限
要授予其他用户查询物化视图的访问权限,请使用 AWS Lake Formation 授予对实体化视图表的 SELECT 权限。用户无需直接访问基础源表即可查询实体化视图。
有关配置 Lake Formation 权限的详细信息,请参阅 L AWS ake Formation 开发人员指南中的授予和撤消数据目录资源的权限。
监控实体化视图操作
AWS Glue 数据目录向亚马逊 CloudWatch发布物化视图刷新操作的指标和日志。您可以监控刷新状态、持续时间和通过 CloudWatch 指标处理的数据量。
查看刷新指标
要查看物化视图刷新指标,请执行以下操作:
-
打开控制 CloudWatch 台。
-
从导航窗格中选择指标。
-
选择 Glue 命名空间。
-
按实例化视图名称筛选指标。
设置警报
要在刷新操作失败或超过预期持续时间时接收通知,请针对物化视图指标创建 CloudWatch 警报。您还可以配置亚马逊 EventBridge 规则,以触发对刷新事件的自动响应。
示例:完整工作流程
以下示例演示了在 Amazon EMR 上创建和使用物化视图的完整工作流程。
-
使用 SSH 连接到 EMR 集群主节点。
-
使用示例数据创建基表:
spark-sql \ --conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions \ --conf spark.sql.catalog.glue_catalog=org.apache.iceberg.spark.SparkCatalog \ --conf spark.sql.catalog.glue_catalog.type=glue \ --conf spark.sql.catalog.glue_catalog.warehouse=s3://amzn-s3-demo-bucket/warehouse \ --conf spark.sql.catalog.glue_catalog.glue.region=us-east-1 \ --conf spark.sql.catalog.glue_catalog.glue.id=111122223333 \ --conf spark.sql.catalog.glue_catalog.glue.account-id=111122223333 \ --conf spark.sql.catalog.glue_catalog.glue.lakeformation-enabled=true \ --conf spark.sql.defaultCatalog=glue_catalog \ --conf spark.sql.optimizer.answerQueriesWithMVs.enabled=true CREATE DATABASE IF NOT EXISTS sales; USE sales; CREATE TABLE orders ( id INT, customer_name STRING, amount DECIMAL(10,2), order_date DATE ); INSERT INTO orders VALUES (1, 'John Doe', 150.00, DATE('2024-01-15')), (2, 'Jane Smith', 200.50, DATE('2024-01-16')), (3, 'Bob Johnson', 75.25, DATE('2024-01-17')); -
创建物化视图:
CREATE MATERIALIZED VIEW customer_summary AS SELECT customer_name, COUNT(*) as order_count, SUM(amount) as total_amount FROM glue_catalog.sales.orders GROUP BY customer_name; -
查询物化视图:
SELECT * FROM customer_summary; -
在基表中插入其他数据:
INSERT INTO orders VALUES (4, 'Jane Smith', 350.00, DATE('2024-01-18')), (5, 'Bob Johnson', 100.25, DATE('2024-01-19')); -
刷新实体化视图:
REFRESH MATERIALIZED VIEW customer_summary FULL; -
验证更新的结果:
SELECT * FROM customer_summary;
注意事项和限制
在 Amazon EMR 中使用物化视图时,请考虑以下几点:
-
物化视图需要亚马逊 EMR 版本 7.12.0 或更高版本。
-
源表必须是在 Gl AWS ue 数据目录中注册的 Apache Iceberg 表。Apache Hive、Apache Hudi 和 Linux Foundation Delta Lake 表在发布时不受支持。
-
源表必须与实体化视图位于同一个 AWS 区域和 AWS 账户中。
-
物化视图不能将 AWS Glue 数据目录视图、多方言视图或其他实例化视图作为源表引用。
-
视图定义者角色必须对所有未应用行、列或单元格筛选条件的源表具有完全读取权限(SELECT 或 ALL 权限)。
-
实体化视图最终与源表保持一致。在刷新窗口期间,查询可能会返回过时数据。执行手动刷新,立即保持一致性。
-
最小自动刷新间隔为一小时。
-
增量刷新支持有限的 SQL 操作子集。视图定义必须是单个 SELECT-FROM-WHERE-GROUP BY-HAVING 块,并且不能包含集合运算、子查询、SELECT 或聚合函数中的 DISTINCT 关键字、窗口函数或除 INNER JOIN 之外的联接。
-
增量刷新不支持用户定义的函数或某些内置函数。仅支持 Spark SQL 内置函数的子集。
-
查询自动重写仅考虑其定义属于受限 SQL 子集的实体化视图,类似于增量刷新限制。
-
完全刷新操作会覆盖整个表,并使以前的快照不可用。
-
CREATE MATERIALIZED VIEW 查询中不支持包含除字母数字字符和下划线之外的特殊字符的标识符。
-
以 __ivm 前缀开头的实例化视图列保留供系统使用。 AWS 保留在未来版本中修改或删除这些列的权利。
-
实体化视图定义中不支持 SORT BY、LIMIT、OFFSET、CLUSTER BY 和 ORDER BY 子句。
-
Cross-Region 并且不支持跨账户源表。
-
Non-deterministic 实例化视图定义中不支持 rand () 或 current_timestamp () 之类的函数。