æ¬èšäºã¯ 2025 幎 12 æ 9 æ¥ ã«å
¬éãããã Introducing Apache Iceberg materialized views in AWS Glue Data Catalog ãã翻蚳ãããã®ã§ãã æ°åäžã®ã客æ§ã AWS äžã§äººå·¥ç¥èœã𿩿¢°åŠç¿ (AI/ML) ããã³ã¢ããªãã£ã¯ã¹ã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããŠãããã¯ãšãªããã©ãŒãã³ã¹ãåäžãããããã«ãçããŒã¿ããåŠçæžã¿ããŒã¿ã»ãããæçµçãªåæããŒãã«ãŸã§ãè€æ°ã®ã¹ããŒãžãçµãŠããŒã¿ã倿ããŠããŸããããŒã¿ãšã³ãžãã¢ã¯ãããŒã¹ããŒãã«ã§å€æŽãããããŒã¿ã®æ€åºã倿ããžãã¯ã®äœæãšä¿å®ãäŸåé¢ä¿ãèæ
®ããã¯ãŒã¯ãããŒã®ã¹ã±ãžã¥ãŒãªã³ã°ãšãªãŒã±ã¹ãã¬ãŒã·ã§ã³ãã³ã³ãã¥ãŒãã£ã³ã°ã€ã³ãã©ã¹ãã©ã¯ãã£ã®ããããžã§ãã³ã°ãšç®¡çããã€ãã©ã€ã³ã®å¥å
šæ§ãç£èŠããªããã®é害ã®ãã©ãã«ã·ã¥ãŒãã£ã³ã°ãªã©ãè€éãªåé¡ã解決ããå¿
èŠããããŸãã äŸãã°ãE ã³ããŒã¹äŒæ¥ã§ã®åæãŠãŒã¹ã±ãŒã¹ã§ãããŒã¿ãšã³ãžãã¢ãã¯ãªãã¯ã¹ããªãŒã ãã°ãšæ³šæããŒã¿ãç¶ç¶çã«ããŒãžããå¿
èŠãããç¶æ³ãèããŠã¿ãŸããããå倿ã«ã¯ãå
ç¢ãªå€æŽæ€åºã¡ã«ããºã ã®æ§ç¯ãè€éãªçµåãšéèšã®äœæãè€æ°ã®ã¯ãŒã¯ãããŒã¹ãããã®èª¿æŽãã³ã³ãã¥ãŒãã£ã³ã°ãªãœãŒã¹ã®é©åãªã¹ã±ãŒãªã³ã°ãéçšã®ç£èŠãå¿
èŠã§ããããããã¹ãŠããããŒã¿å質ãšãã€ãã©ã€ã³ã®ä¿¡é Œæ§ããµããŒãããªããè¡ãå¿
èŠããããŸãããã®è€éãã«ã¯æ°ãæã®å°ä»»ãšã³ãžãã¢ãªã³ã°äœæ¥ãšç¶ç¶çãªã¡ã³ããã³ã¹ãå¿
èŠã§ãããããŒã¿ããæŽå¯ãåŸãããšããçµç¹ã«ãšã£ãŠãããŒã¿å€æã¯ã³ã¹ããšæéãããããã®ãšãªã£ãŠããŸãã ãããã®èª²é¡ã«å¯ŸåŠãããããAWS 㯠AWS Glue Data Catalog ã® Apache Iceberg ããŒãã«åãã®æ°ãããããªã¢ã©ã€ãºããã¥ãŒæ©èœãçºè¡šããŸããããã®æ°ãããããªã¢ã©ã€ãºããã¥ãŒæ©èœã¯ãããŒã¿ãã€ãã©ã€ã³ãç°¡çŽ åããããŒã¿ã¬ã€ã¯ã®ã¯ãšãªããã©ãŒãã³ã¹ãåäžãããŸãããããªã¢ã©ã€ãºããã¥ãŒã¯ãAWS Glue Data Catalog å
ã®ãããŒãžãããŒãã«ã§ãããã¯ãšãªã®äºåèšç®çµæã Iceberg 圢åŒã§ä¿åããåºç€ãšãªãããŒã¿ã»ããã®å€æŽãåæ ããããã«å¢åæŽæ°ãããŸããããã«ããã倿ãããããŒã¿ã»ãããçæããŠã¯ãšãªããã©ãŒãã³ã¹ãåäžãããããã®è€éãªããŒã¿ãã€ãã©ã€ã³ã®æ§ç¯ãšä¿å®ãäžèŠã«ãªããŸãã Amazon Athena ã Amazon EMR ã AWS Glue ã® Apache Spark ãšã³ãžã³ã¯ãæ°ãããããªã¢ã©ã€ãºããã¥ãŒããµããŒãããããã©ãŒãã³ã¹ãåäžãããªããã³ã³ãã¥ãŒãã£ã³ã°ã³ã¹ããåæžãããããªã¢ã©ã€ãºããã¥ãŒã䜿çšããããã«ã¯ãšãªãã€ã³ããªãžã§ã³ãã«æžãæããŸãã ãã®èšäºã§ã¯ãIceberg ãããªã¢ã©ã€ãºããã¥ãŒã®ä»çµã¿ãšäœ¿ãå§ãæ¹ã玹ä»ããŸãã Iceberg ãããªã¢ã©ã€ãºããã¥ãŒã®ä»çµã¿ Iceberg ãããªã¢ã©ã€ãºããã¥ãŒã¯ã䜿ãæ
£ãã SQL æ§æã«åºã¥ããã·ã³ãã«ãªãããŒãžããœãªã¥ãŒã·ã§ã³ãæäŸããŸããè€éãªãã€ãã©ã€ã³ãæ§ç¯ãã代ããã«ãSpark ããæšæºã® SQL ã¯ãšãªã䜿çšããŠãããªã¢ã©ã€ãºããã¥ãŒãäœæããã«ã¹ã¿ã ããŒã¿ãã€ãã©ã€ã³ãäœæããããšãªããéèšããã£ã«ã¿ãŒãçµåã§ããŒã¿ã倿ã§ããŸãã倿޿€åºãå¢åæŽæ°ããœãŒã¹ããŒãã«ã®ç£èŠã¯ AWS Glue Data Catalog ã§èªåçã«åŠçãããæ°ããããŒã¿ãå°çãããšãããªã¢ã©ã€ãºããã¥ãŒãæŽæ°ããããããæåã§ã®ãã€ãã©ã€ã³ãªãŒã±ã¹ãã¬ãŒã·ã§ã³ãäžèŠã«ãªããŸããããŒã¿å€æã¯ãã«ãããŒãžãã®ã³ã³ãã¥ãŒãã£ã³ã°ã€ã³ãã©ã¹ãã©ã¯ãã£ã§å®è¡ãããããããµãŒããŒã®ããããžã§ãã³ã°ãã¹ã±ãŒãªã³ã°ãã¡ã³ããã³ã¹ã®è² æ
ããªããªããŸãã çµæãšããŠåŸãããäºåèšç®ããŒã¿ã¯ãã客æ§ã®ã¢ã«ãŠã³ãå
ã® Amazon Simple Storage Service (Amazon S3) æ±çšãã±ããããŸã㯠Amazon S3 Tables ãã±ãã ã« Iceberg ããŒãã«ãšããŠä¿åããã倿ãããããŒã¿ã¯ Athenaã Amazon Redshift ãAWS æé©å Spark ã©ã³ã¿ã€ã ãªã©ãè€æ°ã®ã¯ãšãªãšã³ãžã³ããããã«ã¢ã¯ã»ã¹ã§ããŸããAthenaãAmazon EMRãAWS Glue ã® Spark ãšã³ãžã³ã¯ããããªã¢ã©ã€ãºããã¥ãŒãã€ã³ããªãžã§ã³ãã«äœ¿çšããèªåã¯ãšãªæžãæãæ©èœããµããŒãããŠãããããŒã¿åŠçãžã§ããã€ã³ã¿ã©ã¯ãã£ããªããŒãããã¯ã¯ãšãªã®ããã©ãŒãã³ã¹ãèªåçã«åäžãããŸãã 以äžã®ã»ã¯ã·ã§ã³ã§ã¯ããããªã¢ã©ã€ãºããã¥ãŒã®äœæãã¯ãšãªãæŽæ°ã®æé ã説æããŸãã åææ¡ä»¶ ãã®èšäºã«æ²¿ã£ãŠé²ããã«ã¯ã AWS ã¢ã«ãŠã³ã ãå¿
èŠã§ãã Amazon EMR ã§æé ãå®è¡ããã«ã¯ã以äžã®ã¹ããããå®äºããŠã¯ã©ã¹ã¿ãŒãèšå®ããŸãã Amazon EMR ã¯ã©ã¹ã¿ãŒ 7.12.0 以äžãèµ·åããŸãã Amazon EMR ã¯ã©ã¹ã¿ãŒã®ãã©ã€ããªããŒãã« SSH ãã°ã€ã³ãã以äžã®ã³ãã³ããå®è¡ããŠå¿
èŠãªèšå®ã§ Spark ã¢ããªã±ãŒã·ã§ã³ãèµ·åããŸãã 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=123456789012 \ --conf spark.sql.catalog.glue_catalog.glue.account-id=123456789012 \ --conf spark.sql.catalog.glue_catalog.client.region=us-east-1 \ --conf spark.sql.catalog.glue_catalog.glue.lakeformation-enabled=true \ --conf spark.sql.optimizer.answerQueriesWithMVs.enabled=true \ --conf spark.sql.defaultCatalog=glue_catalog AWS Glue for Spark ã§æé ãå®è¡ããã«ã¯ã以äžã®ã¹ããããå®äºããŠãžã§ããèšå®ããŸãã AWS Glue ããŒãžã§ã³ 5.1 以äžã®ãžã§ããäœæããŸãã ãžã§ããã©ã¡ãŒã¿ãèšå®ããŸãã ããŒ: --conf å€: spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions 以äžã®ã¹ã¯ãªããã§ãžã§ããèšå®ããŸãã from pyspark.sql import SparkSession spark = ( SparkSession.builder \ .config("spark.sql.extensions", "org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions") .config("spark.sql.catalog.glue_catalog", "org.apache.iceberg.spark.SparkCatalog") .config("spark.sql.catalog.glue_catalog.type", "glue") .config("spark.sql.catalog.glue_catalog.warehouse", "s3://amzn- -demo-bucket/warehouse") .config("spark.sql.catalog.glue_catalog.glue.region", "us-east-1") .config("spark.sql.catalog.glue_catalog.glue.id", "123456789012") .config("spark.sql.catalog.glue_catalog.glue.account-id", "123456789012") .config("spark.sql.catalog.glue_catalog.client.region", "us-east-1") .config("spark.sql.catalog.glue_catalog.glue.lakeformation-enabled", "true") .config("spark.sql.optimizer.answerQueriesWithMVs.enabled", "true") .config("spark.sql.defaultCatalog", "glue_catalog") .getOrCreate() ) 以äžã®ã¯ãšãªã Spark SQL ã§å®è¡ããŠããŒã¹ããŒãã«ãã»ããã¢ããããŸããAWS Glue ã§ã¯ã spark.sql("QUERY STATEMENT") ãéããŠå®è¡ã§ããŸãã CREATE DATABASE IF NOT EXIST iceberg_mv; USE iceberg_mv; CREATE TABLE IF NOT EXISTS base_tbl ( id INT, customer_name STRING, amount INT, order_date DATE); INSERT INTO base_tbl VALUES (1, 'John Doe', 150, DATE('2025-12-01')), (2, 'Jane Smith', 200, DATE('2025-12-02')), (3, 'Bob Johnson', 75, DATE('2025-12-03')); SELECT * FROM base_tbl; 以éã®ã»ã¯ã·ã§ã³ã§ã¯ããã®ããŒã¹ããŒãã«ã䜿çšããŠãããªã¢ã©ã€ãºããã¥ãŒãäœæããŸãã ãããªã¢ã©ã€ãºããã¥ãŒãæ±çš Amazon S3 ãã±ããã§ã¯ãªã Amazon S3 Tables ã«ä¿åããå Žåã¯ããã®èšäºã®æåŸã«ãã ä»é² 1 ã§èšå®ã®è©³çްãåç
§ããŠãã ããã ãããªã¢ã©ã€ãºããã¥ãŒã®äœæ ãããªã¢ã©ã€ãºããã¥ãŒãäœæããã«ã¯ã以äžã®ã³ãã³ããå®è¡ããŸãã CREATE MATERIALIZED VIEW mv AS SELECT customer_name, COUNT(*) as mv_order_count, SUM(amount) as mv_total_amount FROM glue_catalog.iceberg_mv.base_tbl GROUP BY customer_name; ãããªã¢ã©ã€ãºããã¥ãŒãäœæããåŸãSpark ã®ã€ã³ã¡ã¢ãªã¡ã¿ããŒã¿ãã£ãã·ã¥ãæ°ãããããªã¢ã©ã€ãºããã¥ãŒã®æ
å ±ãåæ ãããŸã§æéãããããŸãããã®ãã£ãã·ã¥æ§ç¯æéäžãããŒã¹ããŒãã«ã«å¯Ÿããã¯ãšãªã¯ãããªã¢ã©ã€ãºããã¥ãŒã䜿çšããã«éåžžã©ããå®è¡ãããŸãããã£ãã·ã¥ãå®å
šã«æ§ç¯ãããåŸ (éåžžã¯æ°åç§ä»¥å
)ãSpark ã¯ã¯ãšãªã«ãããªã¢ã©ã€ãºããã¥ãŒãé©çšã§ããããšãèªåçã«æ€åºããäºåèšç®ããããããªã¢ã©ã€ãºããã¥ãŒã䜿çšããããã«ã¯ãšãªãæžãæããŠãããã©ãŒãã³ã¹ãåäžãããŸãã ãã®åäœã確èªããã«ã¯ããããªã¢ã©ã€ãºããã¥ãŒãäœæããçŽåŸã«ä»¥äžã® EXPLAIN ã³ãã³ããå®è¡ããŸãã EXPLAIN EXTENDED SELECT customer_name, COUNT(*) as mv_order_count, SUM(amount) as mv_total_amount FROM base_tbl GROUP BY customer_name; 以äžã®åºåã¯ããã£ãã·ã¥æ§ç¯åã®åæçµæã瀺ããŠããŸãã == Parsed Logical Plan == 'Aggregate ['customer_name], ['customer_name, 'COUNT(1) AS mv_order_count#0, 'SUM('amount) AS mv_total_amount#1] +- 'UnresolvedRelation [base_tbl] , [], false == Analyzed Logical Plan == customer_name: string, mv_order_count: bigint, mv_total_amount: bigint Aggregate [customer_name#8], [customer_name#8, count(1) AS mv_order_count#0L, sum(amount#9) AS mv_total_amount#1L] +- SubqueryAlias glue_catalog.iceberg_mv.base_tbl +- RelationV2[id#7, customer_name#8, amount#9, order_date#10] glue_catalog.iceberg_mv.base_tbl glue_catalog.iceberg_mv.base_tbl == Optimized Logical Plan == Aggregate [customer_name#8], [customer_name#8, count(1) AS mv_order_count#0L, sum(amount#9) AS mv_total_amount#1L] +- RelationV2[customer_name#8, amount#9] glue_catalog.iceberg_mv.base_tbl == Physical Plan == AdaptiveSparkPlan isFinalPlan=false +- HashAggregate(keys=[customer_name#8], functions=[count(1), sum(amount#9)], output=[customer_name#8, mv_order_count#0L, mv_total_amount#1L], schema specialized) +- Exchange hashpartitioning(customer_name#8, 1000), ENSURE_REQUIREMENTS, [plan_id=19] +- HashAggregate(keys=[customer_name#8], functions=[partial_count(1), partial_sum(amount#9)], output=[customer_name#8, count#27L, sum#29L], schema specialized) +- BatchScan glue_catalog.iceberg_mv.base_tbl[customer_name#8, amount#9] glue_catalog.iceberg_mv.base_tbl (branch=null) [filters=, groupedBy=, pushedLimit=None] RuntimeFilters: [] ãã®åæå®è¡ãã©ã³ã§ã¯ãSpark 㯠base_tbl ãçŽæ¥ã¹ãã£ã³ ( BatchScan glue_catalog.iceberg_mv.base_tbl ) ããçããŒã¿ã«å¯ŸããŠéèš ( COUNT ãš SUM ) ãå®è¡ããŠããŸããããã¯ãããªã¢ã©ã€ãºããã¥ãŒã®ã¡ã¿ããŒã¿ãã£ãã·ã¥ãæ§ç¯ãããåã®åäœã§ãã ã¡ã¿ããŒã¿ãã£ãã·ã¥ã®æ§ç¯ã®ããã«çŽæ°åç§åŸ
ã£ãåŸãåã EXPLAIN ã³ãã³ããå床å®è¡ããŸãã以äžã®åºåã¯ããã£ãã·ã¥æ§ç¯åŸã®ã¯ãšãªæé©åãã©ã³ã®äž»ãªéãã瀺ããŠããŸãã == Optimized Logical Plan == Aggregate [customer_name#97], [customer_name#97, coalesce(sum(mv_order_count#98L), 0) AS mv_order_count#72L, sum(mv_total_amount#99L) AS mv_total_amount#73L] +- RelationV2[customer_name#97, mv_order_count#98L, mv_total_amount#99L] glue_catalog.iceberg_mv.mv == Physical Plan == AdaptiveSparkPlan isFinalPlan=false +- HashAggregate(keys=[customer_name#97], functions=[sum(mv_order_count#98L), sum(mv_total_amount#99L)], output=[customer_name#97, mv_order_count#72L, mv_total_amount#73L], schema specialized) +- Exchange hashpartitioning(customer_name#97, 1000), ENSURE_REQUIREMENTS, [plan_id=51] +- HashAggregate(keys=[customer_name#97], functions=[partial_sum(mv_order_count#98L), partial_sum(mv_total_amount#99L)], output=[customer_name#97, sum#113L, sum#115L], schema specialized) +- BatchScan glue_catalog.iceberg_mv.mv[customer_name#97, mv_order_count#98L, mv_total_amount#99L] glue_catalog.iceberg_mv.mv (branch=null) [filters=, groupedBy=, pushedLimit=None] RuntimeFilters: [] ãã£ãã·ã¥ãæ§ç¯ãããåŸãSpark ã¯ããŒã¹ããŒãã«ã§ã¯ãªããããªã¢ã©ã€ãºããã¥ãŒ ( BatchScan glue_catalog.iceberg_mv.mv ) ãã¹ãã£ã³ããããã«ãªããŸãããã¯ãšãªã¯ããããªã¢ã©ã€ãºããã¥ãŒå
ã®äºåèšç®ãããéèšããŒã¿ããèªã¿åãããã«èªåçã«æžãæããããŠããŸããåºåã§ã¯ãéèšé¢æ°ãçããŒã¿ãã COUNT ãš SUM ãåèšç®ããã®ã§ã¯ãªããäºåèšç®ãããå€ãåçŽã«åèš ( sum(mv_order_count) ãš sum(mv_total_amount) ) ããŠããããšãããããŸãã èªåæŽæ°ã¹ã±ãžã¥ãŒã«ä»ãã®ãããªã¢ã©ã€ãºããã¥ãŒã®äœæ ããã©ã«ãã§ã¯ãæ°ããäœæããããããªã¢ã©ã€ãºããã¥ãŒã«ã¯åæã¯ãšãªçµæãå«ãŸããŠããŸããåºç€ãšãªãããŒã¹ããŒãã«ã®ããŒã¿ã倿ŽãããŠãèªåçã«ã¯æŽæ°ãããŸããããããªã¢ã©ã€ãºããã¥ãŒãããŒã¹ããŒãã«ã®ããŒã¿ãšåæãããã«ã¯ãèªåæŽæ°ã¹ã±ãžã¥ãŒã«ãèšå®ã§ããŸããèªåæŽæ°ãæå¹ã«ããã«ã¯ããããªã¢ã©ã€ãºããã¥ãŒãäœæãããšãã« REFRESH EVERY å¥ã䜿çšããŸãããã®å¥ã¯æéééãšåäœãåãå
¥ããããããããªã¢ã©ã€ãºããã¥ãŒãæŽæ°ãããé »åºŠãæå®ã§ããŸãã 以äžã®äŸã§ã¯ã24 æéããšã«èªåæŽæ°ããããããªã¢ã©ã€ãºããã¥ãŒãäœæããŸãã CREATE MATERIALIZED VIEW mv REFRESH EVERY 24 HOURS AS SELECT customer_name, COUNT(*) as mv_order_count, SUM(amount) as mv_total_amount FROM glue_catalog.iceberg_mv.base_tbl GROUP BY customer_name; æŽæ°ééã¯ã SECONDS ã MINUTES ã HOURS ã DAYS ã®ããããã®æéåäœã䜿çšããŠèšå®ã§ããŸããããŒã¿ã®é®®åºŠèŠä»¶ãšã¯ãšãªãã¿ãŒã³ã«åºã¥ããŠé©åãªééãéžæããŠãã ããã ãããªã¢ã©ã€ãºããã¥ãŒã®æŽæ°ã¿ã€ãã³ã°ããã现ããå¶åŸ¡ãããå Žåããã¹ã±ãžã¥ãŒã«ãããééå€ã§æŽæ°ããå¿
èŠãããå Žåã¯ããã€ã§ãæåæŽæ°ãããªã¬ãŒã§ããŸãããã«æŽæ°ãšå¢åæŽæ°ãå«ãæåæŽæ°ãªãã·ã§ã³ã®è©³çŽ°ãªæé ã¯ããã®èšäºã®åŸåã§èª¬æããŸãã ãããªã¢ã©ã€ãºããã¥ãŒãžã®ã¯ãšãª Amazon EMR ã¯ã©ã¹ã¿ãŒã§ãããªã¢ã©ã€ãºããã¥ãŒãã¯ãšãªããŠéèšããŒã¿ãååŸããã«ã¯ãæšæºã® SELECT ã¹ããŒãã¡ã³ãã䜿çšã§ããŸãã SELECT * FROM mv; ãã®ã¯ãšãªã¯ããããªã¢ã©ã€ãºããã¥ãŒãããã¹ãŠã®è¡ãååŸããŸããåºåã«ã¯ãéèšãããé¡§å®¢ã®æ³šææ°ãšåèšéé¡ã衚瀺ãããŸããçµæã«ã¯ã3 人ã®é¡§å®¢ãšããããã®ã¡ããªã¯ã¹ã衚瀺ãããŸãã -- Result Jane Smith 1 200 Bob Johnson 1 75 John Doe 1 150 ããã«ãAthena SQL ããåããããªã¢ã©ã€ãºããã¥ãŒãã¯ãšãªã§ããŸãã以äžã®ã¹ã¯ãªãŒã³ã·ã§ããã¯ãAthena ã§å®è¡ãããåãã¯ãšãªãšçµæã®åºåã瀺ããŠããŸãã ãããªã¢ã©ã€ãºããã¥ãŒã®æŽæ° ãããªã¢ã©ã€ãºããã¥ãŒã¯ã ãã«æŽæ° ãŸã㯠å¢åæŽæ° ã® 2 ã€ã®æŽæ°ã¿ã€ãã䜿çšããŠæŽæ°ã§ããŸãããã«æŽæ°ã¯ããã¹ãŠã®ããŒã¹ããŒãã«ããŒã¿ãããããªã¢ã©ã€ãºããã¥ãŒå
šäœãåèšç®ããŸããå¢åæŽæ°ã¯ãååã®æŽæ°ä»¥éã®å€æŽã®ã¿ãåŠçããŸãããã«æŽæ°ã¯ãäžè²«æ§ãå¿
èŠãªå Žåã倧å¹
ãªããŒã¿å€æŽåŸã«æé©ã§ããå¢åæŽæ°ã¯ãå³ææŽæ°ãå¿
èŠãªå Žåã«é©ããŠããŸãã以äžã®äŸã§ã¯ãäž¡æ¹ã®æŽæ°ã¿ã€ãã瀺ããŸãã ãã«æŽæ° ã䜿çšããã«ã¯ã以äžã®ã¹ããããå®äºããŸãã æ°ããããŒã¿ã®å°çãã·ãã¥ã¬ãŒãããããã«ãããŒã¹ããŒãã«ã« 3 ã€ã®æ°ããã¬ã³ãŒããæ¿å
¥ããŸãã INSERT INTO base_tbl VALUES (4, 'Jane Smith', 350, DATE('2025-11-29')), (5, 'Bob Johnson', 100, DATE('2025-11-30')), (6, 'Kwaku Mensah', 40, DATE('2025-12-01')); ãããªã¢ã©ã€ãºããã¥ãŒãã¯ãšãªããŠããŸã å€ãéèšå€ã衚瀺ãããããšã確èªããŸãã SELECT * FROM mv; -- Result Jane Smith 1 200 Bob Johnson 1 75 John Doe 1 150 以äžã®ã³ãã³ãã䜿çšããŠãããªã¢ã©ã€ãºããã¥ãŒã®ãã«æŽæ°ãå®è¡ããŸãã REFRESH MATERIALIZED VIEW mv FULL; ãããªã¢ã©ã€ãºããã¥ãŒãå床ã¯ãšãªããŠãéèšå€ã«æ°ããã¬ã³ãŒããå«ãŸããŠããããšã確èªããŸãã SELECT * FROM mv; -- Result Jane Smith 2 550 // Updated Bob Johnson 2 175 // Updated John Doe 1 150 Kwaku Mensah 1 40 // Added å¢åæŽæ° ã䜿çšããã«ã¯ã以äžã®ã¹ããããå®äºããŸãã Spark èšå®ããããã£ãèšå®ããŠå¢åæŽæ°ãæå¹ã«ããŸãã SET spark.sql.optimizer.incrementalMVRefresh.enabled=true; ããŒã¹ããŒãã«ã« 2 ã€ã®è¿œå ã¬ã³ãŒããæ¿å
¥ããŸãã INSERT INTO base_tbl VALUES (7, 'Jane Smith', 120, DATE('2025-11-28')), (8, 'Kwaku Mensah', 90, DATE('2025-12-02')); FULL å¥ãªãã§ REFRESH ã³ãã³ãã䜿çšããŠå¢åæŽæ°ãå®è¡ããŸããå¢åæŽæ°ãæå¹ã«ãªã£ãŠãããã©ããã確èªããã«ã¯ããã®èšäºã®æåŸã«ãã ä»é² 2 ãåç
§ããŠãã ããã REFRESH MATERIALIZED VIEW mv; ãããªã¢ã©ã€ãºããã¥ãŒãã¯ãšãªããŠãå¢å倿Žãéèšçµæã«åæ ãããŠããããšã確èªããŸãã SELECT * FROM mv; --Result Jane Smith 3 670 3 3 // Updated Bob Johnson 2 175 2 2 John Doe 1 150 1 1 Kwaku Mensah 2 130 2 2 // Updated Spark SQL ã䜿çšãã以å€ã«ãã¹ã±ãžã¥ãŒã«ãããééå€ã§æŽæ°ãå¿
èŠãªå Žåã¯ãAWS Glue API ãéããŠæåæŽæ°ãããªã¬ãŒããããšãã§ããŸãã以äžã® AWS CLI ã³ãã³ããå®è¡ããŸãã $ aws glue start-materialized-view-refresh-task-run \ --catalog-id <ACCOUNT_ID> \ --database-name <DATABASE_NAME> \ --table-name <MV_TABLE_NAME> AWS Lake Formation ã³ã³ãœãŒã«ã«ã¯ãAPI ã§ããªã¬ãŒãããæŽæ°ã®æŽæ°å±¥æŽã衚瀺ãããŸãããããªã¢ã©ã€ãºããã¥ãŒãéããšãæŽæ°ã¿ã€ã ( INCREMENTAL ãŸã㯠FULL )ãéå§æå»ãšçµäºæå»ãã¹ããŒã¿ã¹ãªã©ã確èªã§ããŸãã Iceberg ãããªã¢ã©ã€ãºããã¥ãŒã䜿çšããŠå¹ççãªããŒã¿åŠçãšã¯ãšãªãè¡ãæ¹æ³ãåŠã³ãŸãããAmazon EMR äžã® Spark ã䜿çšããŠãããªã¢ã©ã€ãºããã¥ãŒãäœæããAmazon EMR ãš Athena ã®äž¡æ¹ããã¯ãšãªãå®è¡ãããã«æŽæ°ãšå¢åæŽæ°ã® 2 ã€ã®æŽæ°ã¡ã«ããºã ã䜿çšããŸãããIceberg ãããªã¢ã©ã€ãºããã¥ãŒã¯ãããŒã¿ãã€ãã©ã€ã³ãç°¡åã«å€æããã³æé©åããã®ã«åœ¹ç«ã¡ãŸãã èæ
®äºé
ãã®æ©èœãæé©ã«äœ¿çšããããã«èæ
®ãã¹ãéèŠãªç¹ããããŸãã ãããªã¢ã©ã€ãºããã¥ãŒã管çããããã®æ°ãã SQL ã³ãã³ãã¯ãAWS ã«ãã£ãŠæé©åããã Spark ã©ã³ã¿ã€ã ãšã³ãžã³ã§ã®ã¿åäœããŸãããããã¯ãAthenaãAmazon EMRãAWS Glue ã® Spark ããŒãžã§ã³ 3.5.6 以äžã§å©çšã§ããŸãããªãŒãã³ãœãŒã¹ã® Spark ã¯ãµããŒããããŠããŸããã ãããªã¢ã©ã€ãºããã¥ãŒã¯ãããŒã¹ããŒãã«ãšçµææŽåæ§ããããŸãããœãŒã¹ããŒãã«ã倿Žããããšããããªã¢ã©ã€ãºããã¥ãŒã¯ãäœææã«æŽæ°ã¹ã±ãžã¥ãŒã«ã§ãŠãŒã¶ãŒãå®çŸ©ããããã¯ã°ã©ãŠã³ãæŽæ°ããã»ã¹ãéããŠæŽæ°ãããŸããæŽæ°ãŠã£ã³ããŠäžããããªã¢ã©ã€ãºããã¥ãŒã«çŽæ¥ã¢ã¯ã»ã¹ããã¯ãšãªã¯å€ãããŒã¿ãåç
§ããå¯èœæ§ããããŸãããã ããææ°ã®ããŒã¿ã»ããã«ããã«ã¢ã¯ã»ã¹ããå¿
èŠãããã客æ§ã¯ãã·ã³ãã«ãª REFRESH MATERIALIZED VIEW SQL ã³ãã³ãã§æåæŽæ°ãå®è¡ã§ããŸãã ã¯ãªãŒã³ã¢ãã ä»åŸã®æéãçºçããªãããã«ããã®ãŠã©ãŒã¯ã¹ã«ãŒã§äœæãããªãœãŒã¹ãã¯ãªãŒã³ã¢ããããŸãã 以äžã®ã³ãã³ããå®è¡ããŠããããªã¢ã©ã€ãºããã¥ãŒãšããŒãã«ãåé€ããŸãã DROP TABLE mv PURGE; -- Or, DROP MATERIALIZED VIEW mv; DROP TABLE base_tbl PURGE; -- If necessary, delete the database by DROP DATABASE iceberg_mv; Amazon EMR ã®å Žåã¯ãAmazon EMR ã¯ã©ã¹ã¿ãŒãçµäºããŸãã AWS Glue ã®å Žåã¯ãAWS Glue ãžã§ããåé€ããŸãã ãŸãšã ãã®èšäºã§ã¯ãIceberg ãããªã¢ã©ã€ãºããã¥ãŒã AWS äžã§å¹ççãªããŒã¿ã¬ã€ã¯æäœãã©ã®ããã«ä¿é²ãããã瀺ããŸãããæ°ãããããªã¢ã©ã€ãºããã¥ãŒæ©èœã¯ãããŒã¿ãã€ãã©ã€ã³ãç°¡çŽ åããããŒã¹ããŒãã«ã®å€æŽã«å¿ããŠèªåçã«æŽæ°ãããäºåèšç®çµæãä¿åããããšã§ã¯ãšãªããã©ãŒãã³ã¹ãåäžãããŸãã䜿ãæ
£ãã SQL æ§æã䜿çšããŠãããªã¢ã©ã€ãºããã¥ãŒãäœæãããã«æŽæ°ãšå¢åæŽæ°ã®äž¡æ¹ã®ã¡ã«ããºã ã䜿çšããŠããŒã¿ã®äžè²«æ§ãç¶æã§ããŸãããã®ãœãªã¥ãŒã·ã§ã³ã¯ãAthenaãAmazon EMRãAWS Glue ãªã©ã® AWS ãµãŒãã¹ãšã®ã·ãŒã ã¬ã¹ãªçµ±åãæäŸããªãããè€éãªãã€ãã©ã€ã³ã®ã¡ã³ããã³ã¹ãäžèŠã«ããŸããèªåã¯ãšãªæžãæãæ©èœã¯ã該åœããå Žåã«ãããªã¢ã©ã€ãºããã¥ãŒãã€ã³ããªãžã§ã³ãã«æŽ»çšããããšã§ããã©ãŒãã³ã¹ãããã«æé©åããããŒã¿å€æã¯ãŒã¯ãããŒãåçåããŠã¯ãšãªããã©ãŒãã³ã¹ãåäžããããçµç¹ã«ãšã£ãŠåŒ·åãªããŒã«ãšãªã£ãŠããŸãã ä»é² 1: Apache Iceberg ãããªã¢ã©ã€ãºããã¥ãŒãä¿åããããã® Amazon S3 Tables ã䜿çšãã Spark èšå® ãã®èšäºã§åè¿°ããããã«ããããªã¢ã©ã€ãºããã¥ãŒã¯ã客æ§ã®ã¢ã«ãŠã³ãå
ã® Amazon S3 Tables ãã±ããã« Iceberg ããŒãã«ãšããŠä¿åãããŸããæ±çš Amazon S3 ãã±ããã§ã¯ãªã Amazon S3 Tables ããããªã¢ã©ã€ãºããã¥ãŒã®ä¿åå ŽæãšããŠäœ¿çšããå Žåã¯ãAmazon S3 Tables ã«ã¿ãã°ã§ Spark ãèšå®ããå¿
èŠããããŸãã åææ¡ä»¶ã»ã¯ã·ã§ã³ã§ç€ºããæšæºã® AWS Glue Data Catalog èšå®ãšã®éãã¯ã glue.id ãã©ã¡ãŒã¿ã®åœ¢åŒã§ããAmazon S3 Tables ã®å Žåã¯ãã¢ã«ãŠã³ã ID ã ãã§ãªãã <account-id>:s3tablescatalog/<s3-tables-bucket-name> ã®åœ¢åŒã䜿çšããŸãã spark-sql \ --conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions \ --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.warehouse="s3://amzn-s3-demo-bucket/warehouse" \ --conf spark.sql.catalog.s3t_catalog.glue.region="us-east-1" \ --conf spark.sql.catalog.s3t_catalog.glue.id="123456789012:s3tablescatalog/amzn-s3-demo-table-bucket" \ --conf spark.sql.catalog.s3t_catalog.glue.account-id=123456789012 \ --conf spark.sql.catalog.s3t_catalog.client.region="us-east-1" \ --conf spark.sql.catalog.s3t_catalog.glue.lakeformation-enabled=true \ --conf spark.sql.optimizer.answerQueriesWithMVs.enabled=true \ --conf spark.sql.defaultCatalog=s3t_catalog ãããã®èšå®ã§ Spark ãèšå®ããåŸããã®èšäºã§ç€ºããã®ãšåã SQL ã³ãã³ãã䜿çšããŠãããªã¢ã©ã€ãºããã¥ãŒãäœæããã³ç®¡çã§ãããããªã¢ã©ã€ãºããã¥ãŒã¯ Amazon S3 Tables ãã±ããã«ä¿åãããŸãã ä»é² 2: Spark SQL ã§ãããªã¢ã©ã€ãºããã¥ãŒã®æŽæ°ã確èªãã Spark SQL ã§ SHOW TBLPROPERTIES ãå®è¡ããŠãã©ã®æŽæ°æ¹æ³ã䜿çšããããã確èªããŸãã +-------------------------------+----------------------------------------------------------------------------------------------------------------------------------+ |key |value | +-------------------------------+----------------------------------------------------------------------------------------------------------------------------------+ |IMV_ansiEnabled |false | |IMV_catalogInfo |[{"catalogId":"123456789012","catalogName":"glue_catalog"}] | |IMV_mvCatalogID |123456789012 | |IMV_mvNamespace |iceberg_mv | |IMV_region |us-east-1 | |IMV_sparkVersion |3.5.6-amzn-1 | |current-snapshot-id |5750703934418352571 | |format |iceberg/parquet | |format-version |2 | |isMaterializedView |true | |lastRefreshType |INCREMENTAL | |subObjects |[{"Version":"4887707562550190856","DatabaseName":"iceberg_mv","Region":"us-east-1","CatalogId":"123456789012","Name":"base_tbl"}] | |tableVersionToken |*********(redacted) | |viewOriginalText |SELECT\ncustomer_name, \nCOUNT(*) as mv_order_count, \nSUM(amount) as mv_total_amount \nFROM base_tbl\nGROUP BY customer_name | |viewVersionId |5750703934418352571 | |viewVersionToken |*********(redacted) | |write.parquet.compression-codec|zstd | +-------------------------------+----------------------------------------------------------------------------------------------------------------------------------+ èè
ã«ã€ã㊠Tomohiro Tanaka AWS ã® Senior Cloud Support Engineer ã§ããAWS äžã®ããŒã¿ã¬ã€ã¯ã§ Apache Iceberg ã䜿çšããã客æ§ãæ¯æŽããããšã«æ
ç±ã泚ãã§ããŸããäœæã«ã¯ãååãšã®ã³ãŒããŒãã¬ã€ã¯ãèªå®
ã§ã®ã³ãŒããŒäœããæ¥œããã§ããŸãã Leon Lin AWS ã® Software Development Engineer ã§ãOpen Data Analytics Engines ããŒã ã§ Apache Iceberg ãš Apache Spark ã®éçºã«æ³šåããŠããŸãããªãŒãã³ãœãŒã¹ã® Apache Iceberg ãããžã§ã¯ããžã®ã¢ã¯ãã£ããªã³ã³ããªãã¥ãŒã¿ãŒã§ããããŸãã Noritaka Sekiyama AWS Analytics ãµãŒãã¹ã® Principal Big Data Architect ã§ããã客æ§ãæ¯æŽããããã®ãœãããŠã§ã¢ã¢ãŒãã£ãã¡ã¯ãã®æ§ç¯ãæ
åœããŠããŸããäœæã«ã¯ãããŒããã€ã¯ã§ã®ãµã€ã¯ãªã³ã°ã楜ããã§ããŸãã Mahesh Mishra AWS Analytics ããŒã ã® Principal Product Manager ã§ããAWS ã®å€ãã®å€§èŠæš¡ãªã客æ§ãšæ°èãã¯ãããžãŒã®ããŒãºã«ã€ããŠååãããã©ã³ã¶ã¯ã·ã§ãã«ããŒã¿ã¬ã€ã¯ã®åŒ·åãªãµããŒããå«ããAWS å
ã®ããã€ãã®ããŒã¿ããã³ã¢ããªãã£ã¯ã¹ã€ãã·ã¢ããããªãŒãããŠããŸãã Layth Yassin AWS Glue ããŒã ã® Software Development Engineer ã§ããå€§èŠæš¡ã§å°é£ãªåé¡ã«åãçµã¿ãåéã®éçãæŒãåºãã補åãæ§ç¯ããããšã«æ
ç±ã泚ãã§ããŸããä»äºä»¥å€ã§ã¯ããã¹ã±ããããŒã«ããã¬ã€ããã芳æŠããããå人ãå®¶æãšéããããšã楜ããã§ããŸãã ãã®èšäºã¯ Kiro ã翻蚳ãæ
åœããSolutions Architect ã® Sotaro Hikita ãã¬ãã¥ãŒããŸããã