Object Storage Service (OSS) に保存されている CSV および TSV データの外部テーブルを作成、読み取り、書き込みする方法について説明します。
注意事項
OSS 外部テーブルはクラスタープロパティをサポートしていません。
単一ファイルのサイズは 2 GB を超えることはできません。2 GB を超えるファイルは分割する必要があります。
MaxCompute と OSS は同じリージョンにある必要があります。
サポートされているデータ型
MaxCompute のデータ型の詳細については、「データ型バージョン 1.0」および「データ型バージョン 2.0」をご参照ください。
スマート解析の詳細については、「スマート解析による柔軟な型互換性」をご参照ください。
型 | com.aliyun.odps.CsvStorageHandler/ TsvStorageHandler (組み込み) | org.apache.hadoop.hive.serde2.OpenCSVSerde (オープンソース) |
TINYINT | ||
SMALLINT | ||
INT | ||
BIGINT | ||
BINARY | ||
FLOAT | ||
DOUBLE | ||
DECIMAL(precision,scale) | ||
VARCHAR(n) | ||
CHAR(n) | ||
STRING | ||
DATE | ||
DATETIME | ||
TIMESTAMP | ||
TIMESTAMP_NTZ | ||
BOOLEAN | ||
ARRAY | ||
MAP | ||
STRUCT | ||
JSON |
サポートされている圧縮形式
圧縮された OSS ファイルの読み取りまたは書き込みを行う場合、CREATE TABLE 文に with serdeproperties 属性を含める必要があります。詳細については、「with serdeproperties 属性パラメーター」をご参照ください。
圧縮形式 | com.aliyun.odps.CsvStorageHandler/ TsvStorageHandler (組み込み) | org.apache.hadoop.hive.serde2.OpenCSVSerde (オープンソース) |
GZIP | ||
SNAPPY | ||
LZO | ||
ZSTD |
サポートされているスキーマ進化
操作 | サポート | 説明 |
列の追加 |
| |
列の削除 | この操作は、スキーマとデータの不一致を引き起こす可能性があるため、推奨されません。 | |
列の順序変更 | この操作は、スキーマとデータの不一致を引き起こす可能性があるため、推奨されません。 | |
列のデータ型変更 | サポートされているデータ型変換のリストについては、「列のデータ型変更」をご参照ください。 | |
列名の変更 | ||
列コメントの変更 | コメントは、最大長 1,024 バイトの有効な文字列である必要があります。それ以外の場合、エラーが発生します。 | |
列の NULL 値許容属性の変更 | この操作はサポートされていません。列はデフォルトで NULL 値を許容します。 |
パラメーター設定
CSV または TSV 外部テーブルのスキーマは、位置によってファイル列にマッピングされます。OSS ファイルの列数が外部テーブルのスキーマの列数と一致しない場合、odps.sql.text.schema.mismatch.mode パラメーターを使用して、不一致な行の処理方法を指定できます。
odps.sql.text.schema.mismatch.modeが truncate に設定されている場合、列の変更は次の効果をもたらします:新しいスキーマに準拠するデータは期待どおりに読み取られます。
古いスキーマを使用する既存データは、新しいスキーマに基づいて読み取られます。
たとえば、テーブルに列を追加した場合、その列の既存データはテーブルを読み取る際に NULL として表示されます。
odps.sql.text.schema.mismatch.modeが ignore に設定されている場合、列の変更は次の効果をもたらします:新しいスキーマに準拠するデータは期待どおりに読み取られます。
古いスキーマを使用する既存データは、新しいスキーマに基づいて読み取られます。
たとえば、テーブルに列を追加した場合、新しい列が欠落している既存データの行全体が、テーブルを読み取る際に破棄されます。
odps.sql.text.schema.mismatch.modeが error に設定されている場合、列の変更は次の効果をもたらします:新しいスキーマに準拠するデータは期待どおりに読み取られます。
古いスキーマを使用する既存データは、新しいスキーマに基づいて読み取られます。
たとえば、テーブルに列を追加した場合、新しい列が欠落している既存データを読み取ろうとするとエラーが発生します。
権限の説明
OSS 外部テーブルにアクセスする際、Alibaba Cloud アカウント (root ユーザー)、RAM ユーザー、または RAM ロールのいずれを使用するかにかかわらず、データは
odps.properties.rolearnパラメーターで指定されたロールを介してアクセスされます。したがって、RAM ロールを作成し、ターゲットの OSS バケットにアクセスするための権限を付与し、そのロールの ARN をodps.properties.rolearnパラメーターで設定する必要があります。詳細については、「パラメーター」をご参照ください。ビジネス要件に基づいて、同一アカウントまたはクロスアカウントのアクセスを権限付与できます。よりきめ細かなアクセス制御を行うために、カスタム権限付与ポリシーを使用することを推奨します。詳細については、「外部データソースの権限付与」をご参照ください。
外部テーブルの作成
構文
組み込みテキストパーサー
CSV 形式
CREATE EXTERNAL TABLE [IF NOT EXISTS] <mc_oss_extable_name>
(
<col_name> <data_type>,
...
)
[COMMENT <table_comment>]
[PARTITIONED BY (<col_name> <data_type>, ...)]
STORED BY 'com.aliyun.odps.CsvStorageHandler'
[WITH serdeproperties (
['<property_name>'='<property_value>',...]
)]
LOCATION '<oss_location>'
[tblproperties ('<tbproperty_name>'='<tbproperty_value>',...)];TSV 形式
CREATE EXTERNAL TABLE [IF NOT EXISTS] <mc_oss_extable_name>
(
<col_name> <data_type>,
...
)
[COMMENT <table_comment>]
[PARTITIONED BY (<col_name> <data_type>, ...)]
STORED BY 'com.aliyun.odps.TsvStorageHandler'
[WITH serdeproperties (
['<property_name>'='<property_value>',...]
)]
LOCATION '<oss_location>'
[tblproperties ('<tbproperty_name>'='<tbproperty_value>',...)];組み込みオープンソースパーサー
CREATE EXTERNAL TABLE [IF NOT EXISTS] <mc_oss_extable_name>
(
<col_name> <data_type>,
...
)
[COMMENT <table_comment>]
[PARTITIONED BY (<col_name> <data_type>, ...)]
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
[WITH serdeproperties (
['<property_name>'='<property_value>',...]
)]
STORED AS TEXTFILE
LOCATION '<oss_location>'
[tblproperties ('<tbproperty_name>'='<tbproperty_value>',...)];共通パラメーター
共通パラメーターの詳細については、「基本構文パラメーター」をご参照ください。
形式固有のパラメーター
WITH SERDEPROPERTIES パラメーター
適用可能なパーサー | パラメーター | ユースケース | 説明 | 値 | デフォルト |
組み込みテキストデータパーサー (CsvStorageHandler/TsvStorageHandler) | odps.text.option.gzip.input.enabled | GZIP 形式で圧縮された CSV または TSV ファイルを読み取る場合に、このプロパティを使用します。 | CSV および TSV 圧縮プロパティ。MaxCompute が GZIP 圧縮ファイルを読み取るには、このプロパティを |
| False |
odps.text.option.gzip.output.enabled | GZIP 圧縮形式でデータを OSS に書き込む場合に、このプロパティを使用します。 | CSV および TSV 圧縮プロパティ。OSS に書き込む際にデータを圧縮するには、このプロパティを |
| False | |
odps.text.option.header.lines.count | OSS 内の CSV または TSV ファイルの最初の N 行をスキップする場合に、このプロパティを使用します。 | データ読み取り時にファイルの先頭からスキップするヘッダー行の数を指定します。 | 非負整数 | 0 | |
odps.text.option.null.indicator | データ内の NULL 値を表すカスタム文字列を定義する場合に、このプロパティを使用します。 | MaxCompute は指定された文字列を たとえば、ファイル内の | 文字列 | 空の文字列 | |
odps.text.option.ignore.empty.lines | CSV または TSV ファイル内の空行の処理方法を定義する場合に、このプロパティを使用します。 |
|
| True | |
odps.text.option.encoding | データファイルがデフォルトの UTF-8 エンコーディングを使用していない場合に、このプロパティを使用します。 | ここで指定するエンコーディングは、ファイルの実際のエンコーディングと一致する必要があります。不一致の場合、読み取りに失敗します。 |
| UTF-8 | |
odps.text.option.delimiter | CSV または TSV ファイルの列区切り文字を指定する場合に、このプロパティを使用します。 | データの不整合を防ぐために、指定したデリミタがデータファイル内の列を正しく区切っていることを確認してください。 | 単一文字 | コンマ (,) | |
odps.text.option.use.quote | CSV または TSV ファイルのフィールドに改行 (CRLF)、二重引用符、または列区切り文字が含まれる場合に、このプロパティを使用します。 | CSV ファイルのフィールドに改行、二重引用符 (エスケープするために |
| False | |
odps.sql.text.option.flush.header | テーブルヘッダーを OSS の各ファイルブロックの最初の行として書き込む場合に、このプロパティを使用します。 | このプロパティは CSV ファイルにのみ適用されます。 |
| False | |
odps.sql.text.schema.mismatch.mode | データファイルの行の列数が外部テーブルのスキーマと異なる場合に、このプロパティを使用します。 | テーブルスキーマと列数が一致しない行の処理方法を指定します。 注:この機能は、 |
| error | |
odps.text.option.zstd.input.enabled | ZSTD 形式で圧縮された CSV または TSV ファイルを読み取る場合に、このプロパティを使用します。 | CSV および TSV 圧縮プロパティ。MaxCompute が ZSTD 圧縮ファイルを読み取るには、このプロパティを True に設定します。それ以外の場合、読み取り操作は失敗します。 |
| False | |
odps.text.option.zstd.output.enabled | ZSTD 圧縮形式でデータを OSS に書き込む場合に、このプロパティを使用します。 | CSV および TSV 圧縮プロパティ。OSS に書き込む際にデータを ZSTD 形式で圧縮するには、このプロパティを True に設定します。それ以外の場合、データは非圧縮で書き込まれます。 |
| False | |
odps.text.option.snappy.input.enabled | SNAPPY で圧縮された CSV または TSV ファイルを読み取る必要がある場合に、このプロパティを追加します。 (SnappyRawCodec)。 | CSV および TSV 圧縮プロパティ。MaxCompute は、このパラメーターが True に設定されている場合にのみ圧縮ファイルを読み取ることができます。それ以外の場合、読み取り操作は失敗します。 |
| False | |
odps.text.option.snappy.output.enabled | データを書き込む必要がある場合に、このプロパティを追加します。 SNAPPY (SnappyRawCodec) で圧縮された OSS。 | CSV および TSV 圧縮プロパティ。このパラメーターが True に設定されている場合、MaxCompute はデータを SNAPPY 圧縮で OSS に書き込みます。それ以外の場合、データは非圧縮で書き込まれます。 |
| False | |
組み込みオープンソースデータパーサー (OpenCSVSerde) | separatorChar | TEXTFILE として保存されている CSV データの列区切り文字を指定する場合に、このプロパティを使用します。 | 列区切り文字を指定します。 | 単一文字 | コンマ (,) |
quoteChar | CSV データのフィールドにデリミタや改行などの特殊文字が含まれる場合に、このプロパティを使用します。 | フィールドを引用符で囲むために使用する文字を指定します。 | 単一文字 | なし | |
escapeChar | TEXTFILE として保存されている CSV データのエスケープ文字を指定する場合に、このプロパティを使用します。 | フィールド内の特殊文字をエスケープするために使用する文字を指定します。 | 単一文字 | なし |
tblproperties パラメーター
適用可能なパーサー | パラメーター | ユースケース | 説明 | 値 | デフォルト |
組み込みオープンソースデータパーサー (OpenCSVSerde) | skip.header.line.count | TEXTFILE として保存されている CSV ファイルの最初の N 行をスキップする場合に、このプロパティを使用します。 | データ読み取り時にファイルの先頭からスキップするヘッダー行の数を指定します。 | 非負整数 | なし |
skip.footer.line.count | TEXTFILE として保存されている CSV ファイルの最後の N 行をスキップする場合に、このプロパティを使用します。 | データ読み取り時にファイルの末尾からスキップするフッター行の数を指定します。 | 非負整数 | なし | |
mcfed.mapreduce.output.fileoutputformat.compress | TEXTFILE データを圧縮して OSS に書き込む場合に、このプロパティを使用します。 | TEXTFILE 圧縮プロパティ。 |
| False | |
mcfed.mapreduce.output.fileoutputformat.compress.codec | 圧縮された TEXTFILE データを OSS に書き込む際に圧縮コーデックを指定する場合に、このプロパティを使用します。 ファイル名に .bz2、.deflate、.snappy、.gz、または .zstd のサフィックスが含まれる圧縮された CSV/TSV ファイルを読み取る場合、追加の構成は不要です。 | TEXTFILE 圧縮プロパティ。TEXTFILE データファイルの圧縮方法を設定します。 |
| なし | |
odps.text.option.bad.row.skipping | OSS に保存されている CSV ファイル内のダーティデータをスキップする場合に、このプロパティを使用します。 | MaxCompute がダーティデータと見なされる行をスキップするか、エラーを報告するかを制御します。 |
| なし |
ホワイトリストとブラックリスト
MaxCompute の OSS 外部テーブルは、ホワイトリストとブラックリストによるフィルタリングをサポートしています。tblproperties でホワイトリストとブラックリストのパラメーターを設定することで、ディレクトリから読み取るファイルをフィルタリングできます。詳細については、「ホワイトリストとブラックリスト」をご参照ください。
データの書き込み
MaxCompute での書き込み構文の詳細については、「書き込み構文」をご参照ください。
クエリと分析
SELECT 構文の詳細については、「クエリ構文」をご参照ください。
クエリプランの最適化の詳細については、「クエリの最適化」をご参照ください。
詳細については、「BadRowSkipping」をご参照ください。
BadRowSkipping
BadRowSkipping 機能を使用すると、クエリの失敗原因となる CSV データ内の不正な行をスキップできます。この設定はエラー処理を制御し、基になるデータ形式の解析方法には影響しません。
パラメーター
テーブルレベルのパラメーター:
odps.text.option.bad.row.skippingrigid:スキップを強制します。この設定は、セッションレベルまたはプロジェクトレベルの構成でオーバーライドできません。flexible:スキップを有効にします。この設定は柔軟であり、セッションレベルまたはプロジェクトレベルの構成でオーバーライドできます。
session/projectレベルのパラメーターodps.sql.unstructured.text.bad.row.skippingパラメーターは、flexibleのテーブルレベルパラメーターをオーバーライドできますが、rigidのパラメーターはオーバーライドできません。on:機能を有効にします。テーブルに機能が構成されていない場合、デフォルトで有効になります。off:機能を無効にします。テーブルが flexible として構成されている場合、機能は無効になります。それ以外の場合、テーブルパラメーターの設定が使用されます。<null> または無効な入力:テーブルレベルの構成が使用されます。
odps.sql.unstructured.text.bad.row.skipping.debug.num:Logview の標準出力に出力するエラー結果の数を指定します。最大値は 1000 です。
値が <=0 の場合、この機能は無効になります。
値が無効な場合、この機能は無効になります。
セッションレベルのパラメーターとテーブルプロパティの相互作用
tbl プロパティ
セッションフラグ
結果
rigid
on
On、強制的に On
off
<null>、無効な値、またはパラメーターが構成されていない
flexible
on
On
off
Off、セッションによって無効化
<null>、無効な値、またはパラメーターが構成されていない
On
構成されていない
on
On、セッションによって有効化
off
Off
<null>、無効な値、またはパラメーターが構成されていない
例
データの準備
不正な行を含むテストデータファイル csv_bad_row_skipping.csv を、OSS のディレクトリ (例:
oss-mc-test/badrow/) にアップロードします。CSV 外部テーブルの作成
以下の例は、テーブルレベルとセッションレベルのパラメーターの異なる組み合わせに基づく 3 つのシナリオを示しています。
テーブルパラメーター:
odps.text.option.bad.row.skipping = flexible | rigid | <not set>セッションフラグ:
odps.sql.unstructured.text.bad.row.skipping = on | off | <not set>
パラメーター未設定
-- テーブルレベルのパラメーターは設定されていません。セッションレベルのフラグでオーバーライドされない限り、不正な行でクエリは失敗します。 CREATE EXTERNAL TABLE test_csv_bad_data_skipping_flag ( a INT, b INT ) STORED BY 'com.aliyun.odps.CsvStorageHandler' WITH serdeproperties ( 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole' ) location '<oss://<your-bucket-name>/<your-file-path>/>';柔軟なスキップ
-- テーブルは不正な行をスキップするように構成されていますが、これはセッションレベルのフラグで無効にできます。 CREATE EXTERNAL TABLE test_csv_bad_data_skipping_flexible ( a INT, b INT ) STORED BY 'com.aliyun.odps.CsvStorageHandler' WITH serdeproperties ( 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole' ) location '<oss://<your-bucket-name>/<your-file-path>/>' tblproperties ( 'odps.text.option.bad.row.skipping' = 'flexible' -- 柔軟なスキップを有効にします。これはセッションレベルで無効にできます。 );厳格なスキップ
-- テーブルは不正な行を強制的にスキップするように構成されています。これはセッションレベルで無効にできません。 CREATE EXTERNAL TABLE test_csv_bad_data_skipping_rigid ( a INT, b INT ) STORED BY 'com.aliyun.odps.CsvStorageHandler' WITH serdeproperties ( 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole' ) location '<oss://<your-bucket-name>/<your-file-path>/>' tblproperties ( 'odps.text.option.bad.row.skipping' = 'rigid' -- スキップを強制的にオンにします。 );クエリ結果の検証
パラメーター未設定
-- 次のコマンドはスキップを有効にしますが、この例の次のコマンドによってすぐにオーバーライドされます。 SET odps.sql.unstructured.text.bad.row.skipping=on; -- このコマンドはスキップを無効にし、以下の SELECT クエリの有効な設定となり、クエリは失敗します。 SET odps.sql.unstructured.text.bad.row.skipping=off; -- スキップが有効な場合にスキップされた行の詳細を出力するためにこのコマンドを使用できます。クエリが失敗するため、ここでは効果がありません。 SET odps.sql.unstructured.text.bad.row.skipping.debug.num=10; SELECT * FROM test_csv_bad_data_skipping_flag;クエリは次のエラーで失敗します:FAILED: ODPS-0123131:User defined function exception
柔軟なスキップ
-- 次のコマンドはスキップを有効にしますが、この例の次のコマンドによってすぐにオーバーライドされます。 SET odps.sql.unstructured.text.bad.row.skipping=on; -- このコマンドはスキップを無効にし、テーブルの 'flexible' 設定をオーバーライドします。これは以下の SELECT クエリの有効な設定となり、クエリは失敗します。 SET odps.sql.unstructured.text.bad.row.skipping=off; -- セッションレベルで最大 10 件の不正な行の詳細を出力します。最大値は 1,000 です。0 以下の値は出力を無効にします。 SET odps.sql.unstructured.text.bad.row.skipping.debug.num=10; SELECT * FROM test_csv_bad_data_skipping_flexible;クエリは次のエラーで失敗します:FAILED: ODPS-0123131:User defined function exception
厳格なスキップ
-- 'rigid' 設定がすでにスキップを強制しているため、このコマンドは冗長です。 SET odps.sql.unstructured.text.bad.row.skipping=on; -- このコマンドはスキップを無効にしようとしますが、'rigid' テーブル設定はオーバーライドできないため、無視されます。 SET odps.sql.unstructured.text.bad.row.skipping=off; -- このコマンドは、'rigid' 設定によってスキップされた最大 10 件の不正な行の詳細を出力します。 SET odps.sql.unstructured.text.bad.row.skipping.debug.num=10; SELECT * FROM test_csv_bad_data_skipping_rigid;次の結果が返されます:
+------------+------------+ | a | b | +------------+------------+ | 1 | 26 | | 5 | 37 | +------------+------------+
スマート解析による柔軟な型互換性
OSS の CSV 形式の外部テーブルに対して、MaxCompute SQL はデータ型 2.0 を使用して読み取りおよび書き込み操作を実行します。以前は厳密な形式の値のみがサポートされていました。この機能は、CSV ファイルからさまざまな値の形式を読み取るための柔軟な型互換性を提供します。具体的な解析ルールは以下のとおりです。
型 | 文字列としての入力 | 文字列としての出力 | 説明 |
BOOLEAN |
説明 解析中に入力に対して |
| 入力文字列がサポートされている値のいずれでもない場合、解析は失敗します。 |
TINYINT |
説明
|
| 8 ビット整数。値が |
SMALLINT | 16 ビット整数。値が | ||
INT | 32 ビット整数。値が | ||
BIGINT | 64 ビット整数。値が 説明 値 | ||
FLOAT |
説明
|
| 特殊な値 (大文字と小文字を区別しない) には、NaN、Inf、-Inf、Infinity、-Infinity が含まれます。値が範囲外の場合、エラーが発生します。精度が制限を超える場合、値は四捨五入されます。 |
DOUBLE |
説明
|
| 特殊な値 (大文字と小文字を区別しない) には、NaN、Inf、-Inf、Infinity、-Infinity が含まれます。値が範囲外の場合、エラーが発生します。精度が制限を超える場合、値は四捨五入されます。 |
DECIMAL (precision, scale) 例:DECIMAL(15,2) |
説明
|
| 整数部分が エラーが報告されます。小数部分がスケールを超える場合、値は四捨五入され、切り捨てられます。 |
CHAR(n) 例:CHAR(7) |
|
| 最大長は 255 です。入力文字列が n より短い場合、末尾にスペースが埋め込まれますが、これらのスペースは比較時に無視されます。入力文字列が n より長い場合、切り捨てられます。 |
VARCHAR(n) 例:VARCHAR(7) |
|
| 最大長は 65,535 です。入力文字列が n より長い場合、切り捨てられます。 |
STRING |
|
| 最大長は 8 MB です。 |
DATE |
説明
|
|
|
TIMESTAMP_NTZ 説明 OpenCsvSerde は、Hive データ形式と互換性がないため、この型をサポートしていません。 |
|
|
|
DATETIME |
| システムタイムゾーンが Asia/Shanghai の場合:
|
|
TIMESTAMP |
| (システムタイムゾーンが Asia/Shanghai の場合)
|
|
一般ルール
どのデータ型でも、CSV データファイル内の空の文字列は、テーブルに読み込まれる際に NULL として解析されます。
サポートされていないデータ型
複雑な型 (STRUCT, ARRAY, MAP):サポートされていません。これらの型の値には、コンマ (
,) などの文字が含まれることが多く、一般的な CSV デリミタと競合して解析に失敗する可能性があります。BINARY および INTERVAL:現在サポートされていません。これらの型のサポートが必要な場合は、MaxCompute のテクニカルサポートにお問い合わせください。
数値型 (INT, DOUBLE など)
INT、SMALLINT、TINYINT、BIGINT、FLOAT、DOUBLE、DECIMAL などの数値データ型に対して、MaxCompute は広範なデフォルトの解析機能を提供します。
基本的な数値文字列のみを解析する必要がある場合は、
tblpropertiesでodps.text.option.smart.parse.levelプロパティをnaiveに設定できます。naive モードでは、パーサーは "123" や "123.456" のような単純な形式のみをサポートします。他の文字列形式を解析するとエラーが発生します。
日付と時刻の型 (DATE, TIMESTAMP など)
java.time.format.DateTimeFormatterクラスは、DATE、DATETIME、TIMESTAMP、TIMESTAMP_NTZの 4 つすべての日付と時刻の型を処理します。デフォルト形式:MaxCompute にはいくつかの組み込み解析形式があります。
カスタム形式:
tblpropertiesでodps.text.option.<date|datetime|timestamp|timestamp_ntz>.io.formatプロパティを設定することで、複数の解析形式と 1 つの出力形式を定義できます。ハッシュ記号 (
#) を使用して、複数の解析パターンを区切ります。カスタム形式は組み込み形式よりも優先されます。最初のカスタムパターンが出力に使用されます。
例:DATE 型のカスタム形式文字列を
pattern1#pattern2#pattern3と定義した場合、MaxCompute はpattern1、pattern2、またはpattern3に一致する文字列を解析できます。ただし、ファイルにデータを書き込む場合、出力は常にpattern1で指定された形式を使用します。詳細については、「DateTimeFormatter」をご参照ください。
'z' タイムゾーンパターンに関する重要な注意
特に中国のユーザーは、あいまいさがあるため、カスタム形式で 'z' (タイムゾーン名) を使用しないでください。
代わりに、タイムゾーンパターンには 'x' (ゾーンオフセット) または 'VV' (タイムゾーン ID) を使用してください。
例:'CST' は通常、中国では中国標準時 (UTC+08:00) を意味します。しかし、
java.time.format.DateTimeFormatterが 'CST' を解析すると、米国中部標準時 (UTC-6) と解釈され、予期しない入力または出力結果を引き起こす可能性があります。
CSV ファイルの分割ロジック
組み込み CSV/TSV パーサー (OpenCSVSerde)
組み込み CSV/TSV パーサー (OpenCSVSerde) は、CSV ファイルの各データ行が \r\n などの文字で区切られ、列に \r\n が含まれていないことを要求します。並列分割とデータ整合性のロジックは次のとおりです:
まず、ファイルは分割サイズによって分割され、一部の行は途中で切断される可能性があります。
後続のワーカーが分割を消費する際、最初の分割を除くすべての分割は、先頭の部分的または完全な行を積極的にスキップします。
各ワーカーは、次の分割の範囲内であっても、末尾の部分的または完全な行を積極的に消費する必要があります。
このパーサーは並列分割をサポートしますが、引用符のエスケープはサポートしていません。
オープンソース CSV パーサー (CsvStorageHandler / TsvStorageHandler)
オープンソース CSV パーサー (CsvStorageHandler / TsvStorageHandler) は、CSV/TSV ファイルを読み取る際に引用符のエスケープを考慮し、\r\n をサポートします。ネストされた引用符や \r\n などの特殊文字が引用符内に現れるシナリオを処理できます。
たとえば、データ "a\ra","b\nb","cc""cc" では、\r\n と二重引用符が正しく解析および出力され、複数行にまたがる値をサポートします。ただし、実際の改行位置はデータ解析を通じてのみ決定できるため、ファイルを単純に \r\n で分割することはできません。その結果、単一ファイルの並列消費はサポートされていません。
データ列に \r\n が含まれず、\r\n が行区切り文字としてのみ使用されていることを確認した場合、odps.sql.unstructured.data.single.file.split.enabled を設定することで並列分割を有効にできます。この場合、大きなファイルは分割サイズによって複数の分割に分割され、組み込みの Text Extractor が自動的に改行境界に整列してデータ整合性を確保します。
結論:
データに行区切り文字として扱えない \r\n が含まれている場合、組み込み CSV/TSV パーサーのみを使用できます。
逆に、単一の大きなファイルを並列で分割する必要がある場合は、オープンソース CSV Serde パーサーのみを使用できます。
例
前提条件
OSS バケットとフォルダが利用可能であること。詳細については、「バケットの作成」および「フォルダの管理」をご参照ください。
MaxCompute は OSS でのフォルダの自動作成をサポートしています。SQL ステートメントに外部テーブルとユーザー定義関数 (UDF) が含まれる場合、単一のステートメントを使用してテーブルの読み取りと書き込み、および UDF の使用ができます。フォルダを手動で作成することもできます。
MaxCompute は特定のリージョンにのみデプロイされています。クロスリージョンデータ接続に関する潜在的な問題を避けるため、ご利用の OSS バケットが MaxCompute プロジェクトと同じリージョンにあることを確認してください。
権限付与
OSS にアクセスする権限が必要です。Alibaba Cloud アカウント (root ユーザー)、Resource Access Management (RAM) ユーザー、または RAM ロールを使用して OSS 外部テーブルにアクセスできます。権限付与の詳細については、「OSS の STS モードでのアクセス権限付与」をご参照ください。
MaxCompute プロジェクトで CreateTable 権限が必要です。テーブル権限の詳細については、「MaxCompute の権限」をご参照ください。
組み込みテキストパーサーを使用した OSS 外部テーブルの作成
例 1:非パーティションテーブル
外部テーブルをサンプルデータの
Demo1/ディレクトリにマッピングします。次のコマンドを使用して OSS 外部テーブルを作成します。CREATE EXTERNAL TABLE IF NOT EXISTS mc_oss_csv_external1 ( vehicleId INT, recordId INT, patientId INT, calls INT, locationLatitute DOUBLE, locationLongtitue DOUBLE, recordTime STRING, direction STRING ) STORED BY 'com.aliyun.odps.CsvStorageHandler' WITH serdeproperties ( 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole' ) LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/Demo1/'; -- `desc extended mc_oss_csv_external1;` コマンドを実行して、作成された OSS 外部テーブルのスキーマを表示できます。この例では、
aliyunodpsdefaultroleRAM ロールを使用しています。別の RAM ロールを使用する場合は、aliyunodpsdefaultroleを対象の RAM ロールの名前に置き換え、OSS にアクセスするために必要な権限を付与してください。非パーティション外部テーブルをクエリします。
SELECT * FROM mc_oss_csv_external1;コマンドは次の結果を返します:
+------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | vehicleid | recordid | patientid | calls | locationlatitute | locationlongtitue | recordtime | direction | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | 1 | 1 | 51 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | S | | 1 | 2 | 13 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | NE | | 1 | 3 | 48 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | NE | | 1 | 4 | 30 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | W | | 1 | 5 | 47 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | S | | 1 | 6 | 9 | 1 | 46.81006 | -92.08174 | 9/15/2014 0:00 | S | | 1 | 7 | 53 | 1 | 46.81006 | -92.08174 | 9/15/2014 0:00 | N | | 1 | 8 | 63 | 1 | 46.81006 | -92.08174 | 9/15/2014 0:00 | SW | | 1 | 9 | 4 | 1 | 46.81006 | -92.08174 | 9/15/2014 0:00 | NE | | 1 | 10 | 31 | 1 | 46.81006 | -92.08174 | 9/15/2014 0:00 | N | +------------+------------+------------+------------+------------------+-------------------+------------+----------------+非パーティション外部テーブルにデータを書き込み、データが正常に書き込まれたことを確認します。
INSERT INTO mc_oss_csv_external1 VALUES(1,12,76,1,46.81006,-92.08174,'9/14/2014 0:10','SW'); SELECT * FROM mc_oss_csv_external1 WHERE recordId=12;コマンドは次の結果を返します:
+------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | vehicleid | recordid | patientid | calls | locationlatitute | locationlongtitue | recordtime | direction | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | 1 | 12 | 76 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:10 | SW | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+OSS の
Demo1/ディレクトリに新しいファイルが表示されることを確認します。データが書き込まれた後、対応する OSS パスで生成された結果ファイル
20250606054845430gpwnhakujm16_M1_1_0_0-0_TableSink1-0-.csv(0.046 KB) と、元のデータファイルvehicle.csv(0.45 KB) を表示できます。
例 2:パーティションテーブル
外部テーブルをサンプルデータの
Demo2/ディレクトリにマッピングします。次のサンプルコマンドは、パーティション化された OSS 外部テーブルを作成します。CREATE EXTERNAL TABLE IF NOT EXISTS mc_oss_csv_external2 ( vehicleId INT, recordId INT, patientId INT, calls INT, locationLatitute DOUBLE, locationLongtitue DOUBLE, recordTime STRING ) PARTITIONED BY ( direction STRING ) STORED BY 'com.aliyun.odps.CsvStorageHandler' WITH serdeproperties ( 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole' ) LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/Demo2/'; -- `DESC EXTENDED mc_oss_csv_external2;` コマンドを実行して、作成された外部テーブルのスキーマを表示できます。この例では、
aliyunodpsdefaultroleRAM ロールを使用しています。別の RAM ロールを使用する場合は、aliyunodpsdefaultroleを対象の RAM ロールの名前に置き換え、OSS にアクセスするために必要な権限を付与してください。パーティションデータをインポートします。パーティション化された OSS 外部テーブルを作成する場合、パーティションデータもインポートする必要があります。詳細については、「OSS 外部テーブル」をご参照ください。
MSCK REPAIR TABLE mc_oss_csv_external2 ADD PARTITIONS; -- これは次のステートメントと同等です。 ALTER TABLE mc_oss_csv_external2 ADD PARTITION (direction = 'N') PARTITION (direction = 'NE') PARTITION (direction = 'S') PARTITION (direction = 'SW') PARTITION (direction = 'W');パーティション外部テーブルをクエリします。
SELECT * FROM mc_oss_csv_external2 WHERE direction='NE';コマンドは次の結果を返します:
+------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | vehicleid | recordid | patientid | calls | locationlatitute | locationlongtitue | recordtime | direction | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | 1 | 2 | 13 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | NE | | 1 | 3 | 48 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | NE | | 1 | 9 | 4 | 1 | 46.81006 | -92.08174 | 9/15/2014 0:00 | NE | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+パーティション外部テーブルにデータを書き込み、データが正常に書き込まれたことを確認します。
INSERT INTO mc_oss_csv_external2 PARTITION(direction='NE') VALUES(1,12,76,1,46.81006,-92.08174,'9/14/2014 0:10'); SELECT * FROM mc_oss_csv_external2 WHERE direction='NE' AND recordId=12;コマンドは次の結果を返します:
+------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | vehicleid | recordid | patientid | calls | locationlatitute | locationlongtitue | recordtime | direction | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | 1 | 12 | 76 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:10 | NE | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+OSS の
Demo2/direction=NEディレクトリに新しいファイルが生成されることを確認します。自動生成されたパーティションデータファイル
20250606062610590gocsdsoujm16_M1_1_0_0-0_TableSink1-0-.csvが OSS ファイルリストに表示され、データが対応する OSS のパーティションパスに正常に書き込まれたことを示します。
例 3:圧縮データ
この例では、GZIP 圧縮された CSV 外部テーブルを作成し、読み取りおよび書き込み操作を実行する方法を示します。
内部テーブルを作成し、後の書き込みテストのためにテストデータを挿入します。
CREATE TABLE vehicle_test( vehicleid INT, recordid INT, patientid INT, calls INT, locationlatitute DOUBLE, locationlongtitue DOUBLE, recordtime STRING, direction STRING ); INSERT INTO vehicle_test VALUES (1,1,51,1,46.81006,-92.08174,'9/14/2014 0:00','S');GZIP 圧縮された CSV 外部テーブルを作成し、サンプルデータの
Demo3/ディレクトリ (圧縮データを含む) にマッピングします。次のサンプルコマンドは、OSS 外部テーブルを作成します。CREATE EXTERNAL TABLE IF NOT EXISTS mc_oss_csv_external3 ( vehicleId INT, recordId INT, patientId INT, calls INT, locationLatitute DOUBLE, locationLongtitue DOUBLE, recordTime STRING, direction STRING ) PARTITIONED BY (dt STRING) STORED BY 'com.aliyun.odps.CsvStorageHandler' WITH serdeproperties ( 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole', 'odps.text.option.gzip.input.enabled'='true', 'odps.text.option.gzip.output.enabled'='true' ) LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/Demo3/'; -- パーティションデータをインポートします。 MSCK REPAIR TABLE mc_oss_csv_external3 ADD PARTITIONS; -- `DESC EXTENDED mc_oss_csv_external3;` コマンドを実行して、作成された外部テーブルのスキーマを表示できます。この例では、
aliyunodpsdefaultroleRAM ロールを使用しています。別の RAM ロールを使用する場合は、aliyunodpsdefaultroleを対象の RAM ロールの名前に置き換え、OSS にアクセスするために必要な権限を付与してください。MaxCompute クライアントを使用して OSS からデータを読み取ります:
説明OSS の圧縮データがオープンソースのデータ形式である場合、SQL ステートメントの前に
set odps.sql.hive.compatible=true;コマンドを追加し、それらを一緒に実行する必要があります。--現在のセッションでのみ全表スキャンを有効にします。 SET odps.sql.allow.fullscan=true; SELECT recordId, patientId, direction FROM mc_oss_csv_external3 WHERE patientId > 25;コマンドは次の結果を返します:
+------------+------------+------------+ | recordid | patientid | direction | +------------+------------+------------+ | 1 | 51 | S | | 3 | 48 | NE | | 4 | 30 | W | | 5 | 47 | S | | 7 | 53 | N | | 8 | 63 | SW | | 10 | 31 | N | +------------+------------+------------+内部テーブルからデータを読み取り、OSS 外部テーブルに書き込みます。
MaxCompute クライアントから外部テーブルに対して
INSERT OVERWRITEまたはINSERT INTOコマンドを実行して、OSS にデータを書き込むことができます。INSERT INTO TABLE mc_oss_csv_external3 PARTITION (dt='20250418') SELECT * FROM vehicle_test;コマンドが正常に実行された後、OSS ディレクトリでエクスポートされたファイルを表示できます。
ヘッダー行を持つ外部テーブルの作成
サンプルデータから oss-mc-test バケットに Demo11 ディレクトリを作成し、次のステートメントを実行します:
--外部テーブルを作成します。
CREATE EXTERNAL TABLE mf_oss_wtt
(
id BIGINT,
name STRING,
tran_amt DOUBLE
)
STORED BY 'com.aliyun.odps.CsvStorageHandler'
WITH serdeproperties (
'odps.text.option.header.lines.count' = '1',
'odps.sql.text.option.flush.header' = 'true',
'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole'
)
LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/Demo11/';
--データを挿入します。
INSERT OVERWRITE TABLE mf_oss_wtt VALUES (1, 'val1', 1.1),(2, 'value2', 1.3);
--データをクエリします。
--テーブルを作成する際、すべての列を STRING として定義できます。そうしないと、ヘッダーが読み取られるときにエラーが発生します。
--または、テーブル定義に 'odps.text.option.header.lines.count' = '1' パラメーターを追加してヘッダーをスキップします。
SELECT * FROM mf_oss_wtt;この例では、aliyunodpsdefaultrole RAM ロールを使用しています。別の RAM ロールを使用する場合は、aliyunodpsdefaultrole を対象の RAM ロールの名前に置き換え、OSS にアクセスするために必要な権限を付与してください。
コマンドは次の結果を返します:
+----------+--------+------------+
| id | name | tran_amt |
+----------+--------+------------+
| 1 | val1 | 1.1 |
| 2 | value2 | 1.3 |
+----------+--------+------------+列が不一致な外部テーブルの作成
サンプルデータから
oss-mc-testバケットにdemoディレクトリを作成し、test.csvファイルをアップロードします。test.csvファイルには次の内容が含まれています:1,kyle1,this is desc1 2,kyle2,this is desc2,this is two 3,kyle3,this is desc3,this is three, I have 4 columns外部テーブルを作成します。
列数が一致しない行の処理方法を
TRUNCATEに設定します。-- テーブルを削除します。 DROP TABLE test_mismatch; -- 外部テーブルを作成します。 CREATE EXTERNAL TABLE IF NOT EXISTS test_mismatch ( id string, name string, dect string, col4 string ) STORED BY 'com.aliyun.odps.CsvStorageHandler' WITH serdeproperties ( 'odps.sql.text.schema.mismatch.mode' = 'truncate', 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole') LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/demo/';列数が一致しない行の処理方法を
IGNOREとして指定します。-- テーブルを削除します。 DROP TABLE test_mismatch01; -- 外部テーブルを作成します。 CREATE EXTERNAL TABLE IF NOT EXISTS test_mismatch01 ( id STRING, name STRING, dect STRING, col4 STRING ) STORED BY 'com.aliyun.odps.CsvStorageHandler' WITH serdeproperties ('odps.sql.text.schema.mismatch.mode' = 'ignore') LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/demo/';テーブル内のデータをクエリします。
test_mismatchテーブルをクエリします。SELECT * FROM test_mismatch; --返された結果 +----+-------+---------------+---------------+ | id | name | dect | col4 | +----+-------+---------------+---------------+ | 1 | kyle1 | this is desc1 | NULL | | 2 | kyle2 | this is desc2 | this is two | | 3 | kyle3 | this is desc3 | this is three | +----+-------+---------------+---------------+test_mismatch01テーブルをクエリします。SELECT * FROM test_mismatch01; --返された結果 +----+-------+----------------+-------------+ | id | name | dect | col4 | +----+-------+----------------+-------------+ | 2 | kyle2 | this is desc2 | this is two +----+-------+----------------+-------------+
オープンソースパーサーを使用した外部テーブルの作成
この例では、組み込みのオープンソースパーサーを使用して OSS 外部テーブルを作成し、ヘッダー行とフッター行を無視してコンマ区切りファイルを読み取る方法を示します。
サンプルデータから
oss-mc-testバケットにdemo-testディレクトリを作成し、test.csv ファイルをアップロードします。テストファイルには次のデータが含まれています:
1,1,51,1,46.81006,-92.08174,9/14/2014 0:00,S 1,2,13,1,46.81006,-92.08174,9/14/2014 0:00,NE 1,3,48,1,46.81006,-92.08174,9/14/2014 0:00,NE 1,4,30,1,46.81006,-92.08174,9/14/2014 0:00,W 1,5,47,1,46.81006,-92.08174,9/14/2014 0:00,S 1,6,9,1,46.81006,-92.08174,9/15/2014 0:00,S 1,7,53,1,46.81006,-92.08174,9/15/2014 0:00,N 1,8,63,1,46.81006,-92.08174,9/15/2014 0:00,SW 1,9,4,1,46.81006,-92.08174,9/15/2014 0:00,NE 1,10,31,1,46.81006,-92.08174,9/15/2014 0:00,N外部テーブルを作成し、区切り文字としてコンマを指定し、ヘッダー行とフッター行を無視するパラメーターを設定します。
CREATE EXTERNAL TABLE ext_csv_test08 ( vehicleId INT, recordId INT, patientId INT, calls INT, locationLatitute DOUBLE, locationLongtitue DOUBLE, recordTime STRING, direction STRING ) ROW FORMAT serde 'org.apache.hadoop.hive.serde2.OpenCSVSerde' WITH serdeproperties ( "separatorChar" = ",", 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole' ) stored AS textfile location 'oss://oss-cn-hangzhou-internal.aliyuncs.com/***/' -- ヘッダー行とフッター行を無視するパラメーターを設定します。 TBLPROPERTIES ( "skip.header.line.COUNT"="1", "skip.footer.line.COUNT"="1" ) ;外部テーブルからデータを読み取ります。
SELECT * FROM ext_csv_test08; -- ヘッダー行とフッター行が無視されるため、結果には 8 行のデータが含まれます。 +------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | vehicleid | recordid | patientid | calls | locationlatitute | locationlongtitue | recordtime | direction | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | 1 | 2 | 13 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | NE | | 1 | 3 | 48 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | NE | | 1 | 4 | 30 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | W | | 1 | 5 | 47 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | S | | 1 | 6 | 9 | 1 | 46.81006 | -92.08174 | 9/15/2014 0:00 | S | | 1 | 7 | 53 | 1 | 46.81006 | -92.08174 | 9/15/2014 0:00 | N | | 1 | 8 | 63 | 1 | 46.81006 | -92.08174 | 9/15/2014 0:00 | SW | | 1 | 9 | 4 | 1 | 46.81006 | -92.08174 | 9/15/2014 0:00 | NE | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+
カスタム時刻型を持つ CSV 外部テーブルの作成
CSV のカスタム時刻型の解析および出力形式の詳細については、「スマート解析による柔軟な型互換性」をご参照ください。
DATE、DATETIME、TIMESTAMP、TIMESTAMP_NTZなど、さまざまな時刻データ型を使用する CSV 外部テーブルを作成します。CREATE EXTERNAL TABLE test_csv ( col_date DATE, col_datetime DATETIME, col_timestamp TIMESTAMP, col_timestamp_ntz TIMESTAMP_NTZ ) STORED BY 'com.aliyun.odps.CsvStorageHandler' LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/demo/' WITH serdeproperties ( 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole' ) TBLPROPERTIES ( 'odps.text.option.date.io.format' = 'MM/dd/yyyy', 'odps.text.option.datetime.io.format' = 'yyyy-MM-dd-HH-mm-ss x', 'odps.text.option.timestamp.io.format' = 'yyyy-MM-dd HH-mm-ss VV', 'odps.text.option.timestamp_ntz.io.format' = 'yyyy-MM-dd HH:mm:ss.SS' ); INSERT OVERWRITE test_csv VALUES(DATE'2025-02-21', DATETIME'2025-02-21 08:30:00', TIMESTAMP'2025-02-21 12:30:00', TIMESTAMP_NTZ'2025-02-21 16:30:00.123456789');データが挿入された後、CSV ファイルの内容は次のようになります:
02/21/2025,2025-02-21-08-30-00 +08,2025-02-21 12-30-00 Asia/Shanghai,2025-02-21 16:30:00.12データを再度クエリして結果を表示します。
SELECT * FROM test_csv;コマンドは次の結果を返します:
+------------+---------------------+---------------------+------------------------+ | col_date | col_datetime | col_timestamp | col_timestamp_ntz | +------------+---------------------+---------------------+------------------------+ | 2025-02-21 | 2025-02-21 08:30:00 | 2025-02-21 12:30:00 | 2025-02-21 16:30:00.12 | +------------+---------------------+---------------------+------------------------+
よくある質問
列数の不一致エラー
症状
このエラーは、CSV または TSV ファイルの行の列数が、外部テーブル DDL で定義された列数と一致しない場合に発生します。MaxCompute は
FAILED: ODPS-0123131:User defined function exception - Traceback:java.lang.RuntimeException: SCHEMA MISMATCH:xxxのようなエラーを報告します。解決策
セッションレベルで
odps.sql.text.schema.mismatch.modeパラメーターを設定することで、MaxCompute が不一致をどのように処理するかを制御できます:SET odps.sql.text.schema.mismatch.mode=error:列数の不一致が発生した場合にクエリを失敗させます。これはデフォルトの動作です。SET odps.sql.text.schema.mismatch.mode=truncate:行の列数が外部テーブル DDL で定義されたものより多い場合、余分な列は破棄されます。行の列数が少ない場合、欠落している列は NULL で埋められます。