

# CTAS および INSERT INTO を使用して 100 パーティションの制限を回避する
<a name="ctas-insert-into"></a>

Athena では、`CREATE TABLE AS SELECT` ([CTAS](ctas.md)) クエリごとのパーティション数は 100 個に制限されています。同様に、[INSERT INTO](https://docs.aws.amazon.com/athena/latest/ug/insert-into.html) ステートメントを使用すると、宛先テーブルに最大 100 個のパーティションを追加できます。

この制限を超えると、HIVE\$1TOO\$1MANY\$1OPEN\$1PARTITIONS: Exceeded limit of 100 open writers for partitions/buckets (HIVE\$1TOO\$1MANY\$1OPEN\$1PARTITIONS: パーティション/バケットのオープンライターの制限である 100 を超えました) エラーメッセージが表示されることがあります。これらの制限を回避するには、CTAS ステートメントと、それぞれ最大 100 個のパーティションを作成または挿入する一連の `INSERT INTO` ステートメントを使用できます。

このトピックの例では、Amazon S3 バケットの場所 s3://amzn-s3-demo-bucket/ にデータが格納されている、`tpch100` という名前のデータベースを使用します。

**CTAS および INSERT INTO を使用して 100 個を超えるパーティションのテーブルを作成するには**

1. `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/'
   ```

1. 次のような `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
   */
   ```

1. 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');
   ```

1. `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
   */
   ```

1. `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');
   ```

1. `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
   */
   ```

1. 各々が読み取りと追加を 100 パーティション以上実行しない `INSERT INTO` ステートメントを引き続き使用します。必要なパーティション数に達するまで続行します。
**重要**  
`WHERE` 条件を設定するときは、クエリが重複しないようにしてください。そうしなければ、一部のパーティションに重複するデータが発生する可能性があります。