CTAS および INSERT INTO を使用して 100 パーティションの制限を回避する
Athena では、CREATE TABLE AS SELECT (CTAS) クエリごとのパーティション数は 100 個に制限されています。同様に、INSERT INTO ステートメントを使用すると、宛先テーブルに最大 100 個のパーティションを追加できます。
この制限を超えると、HIVE_TOO_MANY_OPEN_PARTITIONS: Exceeded limit of 100 open writers for partitions/buckets (HIVE_TOO_MANY_OPEN_PARTITIONS: パーティション/バケットのオープンライターの制限である 100 を超えました) エラーメッセージが表示されることがあります。これらの制限を回避するには、CTAS ステートメントと、それぞれ最大 100 個のパーティションを作成または挿入する一連の INSERT INTO ステートメントを使用できます。
このトピックの例では、Amazon S3 バケットの場所 s3://amzn-s3-demo-bucket/ にデータが格納されている、tpch100 という名前のデータベースを使用します。
CTAS および INSERT INTO を使用して 100 個を超えるパーティションのテーブルを作成するには
-
CREATE EXTERNAL TABLEステートメントを使用して、目的のフィールドでパーティション化されたテーブルを作成します。次の例のステートメントは、列
l_shipdateでデータを分割します。テーブルには 2525 個のパーティションがあります。CREATE EXTERNAL TABLE `tpch100.lineitem_parq_partitioned`( `l_orderkey` int, `l_partkey` int, `l_suppkey` int, `l_linenumber` int, `l_quantity` double, `l_extendedprice` double, `l_discount` double, `l_tax` double, `l_returnflag` string, `l_linestatus` string, `l_commitdate` string, `l_receiptdate` string, `l_shipinstruct` string, `l_comment` string) PARTITIONED BY ( `l_shipdate` string) ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' STORED AS INPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat' LOCATION 's3://amzn-s3-demo-bucket/lineitem/' -
次のような
SHOW PARTITIONSコマンドを実行して、パーティションをリストします。<table_name>SHOW PARTITIONS lineitem_parq_partitioned次に、結果の一部を示します。
/* l_shipdate=1992-01-02 l_shipdate=1992-01-03 l_shipdate=1992-01-04 l_shipdate=1992-01-05 l_shipdate=1992-01-06 ... l_shipdate=1998-11-24 l_shipdate=1998-11-25 l_shipdate=1998-11-26 l_shipdate=1998-11-27 l_shipdate=1998-11-28 l_shipdate=1998-11-29 l_shipdate=1998-11-30 l_shipdate=1998-12-01 */ -
CTAS クエリを実行して、パーティション分割されたテーブルを作成します。
次の例では、
my_lineitem_parq_partitionedというテーブルを作成し、WHERE句を使用して、DATEを1992-02-01より前の日付に制限します。サンプルデータセットは 1992 年 1 月から始まるため、1992 年 1 月のパーティションのみが作成されます。CREATE table my_lineitem_parq_partitioned WITH (partitioned_by = ARRAY['l_shipdate']) AS SELECT l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_commitdate, l_receiptdate, l_shipinstruct, l_comment, l_shipdate FROM tpch100.lineitem_parq_partitioned WHERE cast(l_shipdate as timestamp) < DATE ('1992-02-01'); -
SHOW PARTITIONSコマンドを実行して、必要なパーティションがテーブルに含まれていることを確認します。SHOW PARTITIONS my_lineitem_parq_partitioned;この例のパーティションは 1992 年 1 月のものです。
/* l_shipdate=1992-01-02 l_shipdate=1992-01-03 l_shipdate=1992-01-04 l_shipdate=1992-01-05 l_shipdate=1992-01-06 l_shipdate=1992-01-07 l_shipdate=1992-01-08 l_shipdate=1992-01-09 l_shipdate=1992-01-10 l_shipdate=1992-01-11 l_shipdate=1992-01-12 l_shipdate=1992-01-13 l_shipdate=1992-01-14 l_shipdate=1992-01-15 l_shipdate=1992-01-16 l_shipdate=1992-01-17 l_shipdate=1992-01-18 l_shipdate=1992-01-19 l_shipdate=1992-01-20 l_shipdate=1992-01-21 l_shipdate=1992-01-22 l_shipdate=1992-01-23 l_shipdate=1992-01-24 l_shipdate=1992-01-25 l_shipdate=1992-01-26 l_shipdate=1992-01-27 l_shipdate=1992-01-28 l_shipdate=1992-01-29 l_shipdate=1992-01-30 l_shipdate=1992-01-31 */ -
INSERT INTOステートメントを使用して、テーブルにパーティションを追加します。次の例では、1992 年 2 月の日付のパーティションを追加します。
INSERT INTO my_lineitem_parq_partitioned SELECT l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_commitdate, l_receiptdate, l_shipinstruct, l_comment, l_shipdate FROM tpch100.lineitem_parq_partitioned WHERE cast(l_shipdate as timestamp) >= DATE ('1992-02-01') AND cast(l_shipdate as timestamp) < DATE ('1992-03-01'); -
SHOW PARTITIONSをもう一度実行します。SHOW PARTITIONS my_lineitem_parq_partitioned;サンプルテーブルには、1992 年 1 月と 2 月のパーティションがあります。
/* l_shipdate=1992-01-02 l_shipdate=1992-01-03 l_shipdate=1992-01-04 l_shipdate=1992-01-05 l_shipdate=1992-01-06 ... l_shipdate=1992-02-20 l_shipdate=1992-02-21 l_shipdate=1992-02-22 l_shipdate=1992-02-23 l_shipdate=1992-02-24 l_shipdate=1992-02-25 l_shipdate=1992-02-26 l_shipdate=1992-02-27 l_shipdate=1992-02-28 l_shipdate=1992-02-29 */ -
各々が読み取りと追加を 100 パーティション以上実行しない
INSERT INTOステートメントを引き続き使用します。必要なパーティション数に達するまで続行します。重要
WHERE条件を設定するときは、クエリが重複しないようにしてください。そうしなければ、一部のパーティションに重複するデータが発生する可能性があります。