OSS(Object Storage Service)に格納された CSV および TSV データに対して、外部テーブルの作成、読み取り、および書き込み方法について説明します。
注意事項
OSS 外部テーブルでは、クラスター属性はサポートされていません。
単一ファイルのサイズは 2 GB を超えてはなりません。2 GB を超えるファイルは分割する必要があります。
MaxCompute と OSS は、同一リージョン内に配置する必要があります。
サポートされるデータ型
MaxCompute のデータ型の詳細については、「データ型バージョン 1.0」および「データ型バージョン 2.0」をご参照ください。
SmartParse の詳細については、「Smart Parse の柔軟な型互換性」をご参照ください。
型 | 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 ファイルから読み取る場合、または圧縮済み OSS ファイルに書き込む場合、CREATE TABLE ステートメントに with serdeproperties 属性を含める必要があります。詳細については、「with serdeproperties 属性パラメーター」をご参照ください。
圧縮形式 | com.aliyun.odps.CsvStorageHandler/ TsvStorageHandler (組み込み) | org.apache.hadoop.hive.serde2.OpenCSVSerde (オープンソース) |
GZIP | ||
SNAPPY | ||
LZO |
サポートされるスキーマ進化
操作 | サポート対象 | 説明 |
列の追加 |
| |
列の削除 | この操作は推奨されません。スキーマとデータの不一致が発生する可能性があります。 | |
列の順序変更 | この操作は推奨されません。スキーマとデータの不一致が発生する可能性があります。 | |
列のデータ型の変更 | サポートされるデータ型変換の一覧については、「列のデータ型の変更」をご参照ください。 | |
列名の変更 | ||
列コメントの変更 | コメントは、最大長 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 に設定した場合、列の変更には以下の効果があります:新しいスキーマに準拠するデータは、期待通りに読み取られます。
既存のデータ(古いスキーマを使用)は、新しいスキーマに基づいて読み取られます。
たとえば、テーブルに列を追加した場合、新しい列がない履歴データを読み取ろうとするとエラーが発生します。
外部テーブルの作成
構文
組み込みテキストパーサー
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 | このプロパティを使用して、OSS に GZIP 圧縮形式でデータを書き込みます。 | 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 ファイルの列区切り文字を指定します。 | 指定した区切り文字がデータファイル内の列を正しく分離することを確認してください。そうでないと、データの配置がずれる可能性があります。 | 1 文字 | カンマ (,) | |
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 | |
組み込みオープンソースデータパーサー(OpenCSVSerde) | separatorChar | TEXTFILE として格納された CSV データの列区切り文字を指定するために、このプロパティを使用します。 | 列区切り文字を指定します。 | 1 文字 | カンマ (,) |
quoteChar | CSV データのフィールドに区切り文字や改行などの特殊文字が含まれている場合に、このプロパティを使用します。 | フィールドを囲むために使用する文字を指定します。 | 1 文字 | なし | |
escapeChar | TEXTFILE として格納された CSV データのエスケープ文字を指定するために、このプロパティを使用します。 | フィールド内の特殊文字をエスケープするために使用する文字を指定します。 | 1 文字 | なし |
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 に書き込む際の圧縮コーデックを指定します。 | TEXTFILE 圧縮プロパティ。 TEXTFILE 出力用の圧縮コーデックを指定します。 注: MaxCompute は、 |
| なし | |
io.compression.codecs | OSS データファイルが Raw-Snappy 形式で圧縮されている場合に、このプロパティを使用します。 | MaxCompute が Raw-Snappy 圧縮データを読み取れるようにします。この設定がないと、読み取り操作は失敗します。 | com.aliyun.odps.io.compress.SnappyRawCodec | なし | |
odps.text.option.bad.row.skipping | OSS に格納された CSV ファイルのダーティデータをスキップするために、このプロパティを使用します。 | MaxCompute がダーティデータと見なされる行をスキップするか、エラーを報告するかを制御します。 |
| なし |
データの書き込み
MaxCompute における書き込み構文の詳細については、「書き込み構文」をご参照ください。
クエリおよび分析
SELECT 構文の詳細については、「クエリ構文」をご参照ください。
クエリプランの最適化の詳細については、「クエリの最適化」をご参照ください。
詳細については、「BadRowSkipping」をご参照ください。
BadRowSkipping
BadRowSkipping 機能により、クエリの失敗を引き起こす可能性のある CSV データ内の不良行をスキップできます。この設定はエラー処理を制御するものであり、基盤となるデータ形式の解析には影響しません。
パラメーター
テーブルレベルのパラメーター:
odps.text.option.bad.row.skippingrigid:スキップを強制します。この設定は、セッションレベルまたはプロジェクトレベルの構成で上書きできません。flexible:スキップを有効にします。この設定は **柔軟** であり、セッションレベルまたはプロジェクトレベルの構成で上書きできます。
セッション/プロジェクトレベルのパラメーターodps.sql.unstructured.text.bad.row.skippingパラメーターは、flexibleのテーブルレベルのパラメーターを上書きできますが、rigidの場合は上書きできません。on:機能を有効化します。テーブルで機能が構成されていない場合、デフォルトで有効になります。off:機能を無効化します。テーブルが flexible として構成されている場合、機能は無効になります。それ以外の場合は、テーブルパラメーターの設定が使用されます。<null> または無効な入力:テーブルレベルの構成が使用されます。
odps.sql.unstructured.text.bad.row.skipping.debug.num:Logview で stdout に出力するエラー結果の数を指定します。最大値は 1000 です。
値が <=0 の場合、この機能は無効になります。
値が無効な場合、この機能は無効になります。
セッションレベルのパラメーターとテーブルプロパティーの相互作用
テーブルプロパティー
セッションフラグ
結果
rigid
on
オン、強制的にオン
off
<null>、無効な値、またはパラメーターが未設定
flexible
on
オン
off
オフ、セッションにより無効化
<null>、無効な値、またはパラメーターが未設定
オン
未設定
on
オン、セッションにより有効化
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 | +------------+------------+
Smart Parse の柔軟な型互換性
OSS の CSV 形式外部テーブルでは、MaxCompute SQL が読み取りおよび書き込み操作にデータ型バージョン 2.0 を使用します。以前は、厳密な形式の値のみがサポートされていました。この機能により、CSV ファイルから幅広い形式の値を読み取る柔軟な型互換性が提供されます。具体的な解析ルールを以下に示します。
型 | 文字列としての入力 | 文字列としての出力 | 説明 |
BOOLEAN |
説明 解析時に、入力に対して |
| 入力文字列がサポートされる値のいずれでもない場合、解析は失敗します。 |
TINYINT |
説明
|
| 8 ビット整数。値が |
SMALLINT | 16 ビット整数。値が | ||
INT | 32 ビット整数。値が | ||
BIGINT | 64 ビット整数。値が 説明 SQL エンジンの制限により、値 | ||
FLOAT |
説明
|
| 特殊値(大文字小文字を区別しない)には、NaN、Inf、-Inf、Infinity、-Infinity があります。値が範囲外の場合、エラーが発生します。精度が上限を超える場合、値は四捨五入されます。 |
DOUBLE |
説明
|
| 特殊値(大文字小文字を区別しない)には、NaN、Inf、-Inf、Infinity、-Infinity があります。値が範囲外の場合、エラーが発生します。精度が上限を超える場合、値は四捨五入されます。 |
DECIMAL (precision, scale) 例:DECIMAL(15,2) |
説明
|
| 整数部の桁数が エラーが報告されます。小数部の桁数が scale を超える場合、値は四捨五入および切り捨てられます。 |
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 は広範なデフォルト解析機能を提供します。
基本的な数値文字列のみを解析する必要がある場合、
odps.text.option.smart.parse.levelプロパティをnaiveに設定できます。tblproperties内で naive モードを設定すると、パーサーは "123" や "123.456" のような単純なフォーマットのみをサポートします。他の文字列フォーマットを解析しようとするとエラーが発生します。
日付および時刻型(DATE、TIMESTAMP など)
java.time.format.DateTimeFormatterクラスが、DATE、DATETIME、TIMESTAMP、TIMESTAMP_NTZの 4 つの日付および時刻型すべてを処理します。デフォルトフォーマット:MaxCompute にはいくつかの組み込み解析フォーマットがあります。
カスタムフォーマット:
odps.text.option.<date|datetime|timestamp|timestamp_ntz>.io.formatプロパティをtblpropertiesで設定することで、複数の解析フォーマットと 1 つの出力フォーマットを定義できます。ハッシュ記号(
#)を使用して、複数の解析パターンを区切ります。カスタムフォーマットは、組み込みフォーマットよりも優先されます。最初のカスタムパターンが出力に使用されます。
例:DATE 型のカスタムフォーマット文字列を
pattern1#pattern2#pattern3として定義した場合、MaxCompute はpattern1、pattern2、またはpattern3に一致する文字列を解析できます。ただし、ファイルへの書き込み時には、常にpattern1で指定されたフォーマットが出力に使用されます。詳細については、「DateTimeFormatter」をご参照ください。
'z' タイムゾーンパターンに関する重要な注意事項
中国のユーザー向けに特に、カスタムフォーマットで 'z'(タイムゾーン名)を使用しないしないでください。あいまいさがあるため、特に中国のユーザーはカスタムフォーマットで 'z'(タイムゾーン名)を使用しないでください。
代わりに、タイムゾーンパターンには 'x'(ゾーンオフセット)または 'VV'(タイムゾーン ID)を使用してください。
例:中国では 'CST' は通常、中国標準時(UTC+8)を意味します。しかし、
java.time.format.DateTimeFormatterが 'CST' を解析すると、米国中部標準時(UTC-6)として解釈され、予期しない入出力結果を引き起こす可能性があります。
例
前提条件
組み込みテキストパーサーを使用した 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/ディレクトリに新しいファイルが表示されることを確認します。
例 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ディレクトリに新しいファイルが生成されることを確認します。
例 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'
)
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') 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" = "," ) 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 のカスタム時刻型の解析および出力フォーマットの詳細については、「Smart Parse の柔軟な型互換性」をご参照ください。
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/' 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 で埋められます。