このトピックでは、OSS 外部テーブルを作成し、カスタムストレージハンドラを使用してテーブルのデータを読み書きする方法について説明します。
適用範囲
OSS 外部テーブルはクラスタープロパティをサポートしていません。
単一ファイルのサイズは 2 GB を超えることはできません。ファイルが大きすぎる場合は、分割してください。
外部テーブルの作成
構文
CREATE EXTERNAL TABLE [IF NOT EXISTS] mc_oss_extable_name
(
col_name date_type,
...
)
[comment table_comment]
[partitioned BY (col_name data_type, ...)]
stored BY '<YOUR_DEFINED_STORAGEHANDLER>'
WITH serdeproperties (
['property_name'='property_value',...]
)
location 'oss_location'
USING 'jar_name';正確性の問題を回避するため、カスタムストレージハンドラはデフォルトではデータをシャーディングしません。ご利用のストレージハンドラがシャーディングを処理できることを確認した場合、次のコマンドを実行してデータシャーディング機能を有効にし、複数のマッパーを起動できます。
SET odps.sql.unstructured.data.single.file.split.enabled=true;共通パラメーター
共通パラメーターの詳細については、「基本的な構文パラメーター」をご参照ください。
排他的パラメーター
パラメーター | 必須 | 説明 |
your_defined_storagehandler | はい | MaxCompute のユーザー定義関数 (UDF) を使用して、カスタムリゾルバーを作成できます。詳細については、「UDF の開発」をご参照ください。 |
jar_name | はい | カスタムストレージハンドラのコードを含む JAR パッケージです。この JAR パッケージは、リソースとして MaxCompute プロジェクトに追加する必要があります。 リソースの追加方法の詳細については、「リソース操作」をご参照ください。 |
resource_name | いいえ | カスタム serde クラスを使用する場合、依存リソースを指定する必要があります。このリソースにはカスタム serde クラスが含まれます。 serde クラスを含む JAR パッケージは、リソースとして MaxCompute プロジェクトに追加する必要があります。 リソースの追加方法の詳細については、「リソース操作」をご参照ください。 |
データの書き込み
MaxCompute のデータ書き込み構文の詳細については、「OSS へのデータ書き込み」をご参照ください。
クエリと分析
SELECT 構文の詳細については、「OSS データの読み取り」をご参照ください。
クエリプランの最適化方法の詳細については、「クエリの最適化」をご参照ください。
例:カスタムストレージハンドラを使用した OSS 外部テーブルの作成
「付録:サンプルデータの準備」の SampleData/ ディレクトリ (カスタムストレージハンドラ) とのマッピングを確立します。手順は次のとおりです。
前提条件
OSS バケットとフォルダが利用可能であること。詳細については、「バケットの作成」および「フォルダの管理」をご参照ください。
MaxCompute は OSS でのフォルダの自動作成をサポートしています。SQL 文に外部テーブルとユーザー定義関数 (UDF) が含まれる場合、1 つの文でテーブルの読み書きと UDF の使用が可能です。フォルダは手動で作成することもできます。
MaxCompute は特定のリージョンにのみデプロイされます。リージョン間のデータ接続で潜在的な問題が発生するのを避けるため、ご利用の OSS バケットが MaxCompute プロジェクトと同じリージョンにあることを確認してください。
権限付与
OSS へのアクセス権限が必要です。Alibaba Cloud アカウント、Resource Access Management (RAM) ユーザー、または RAM ロールを使用して OSS 外部テーブルにアクセスできます。権限付与の詳細については、「OSS への STS モードでのアクセス権限付与」をご参照ください。
MaxCompute プロジェクトで CreateTable 権限が必要です。テーブル権限の詳細については、「MaxCompute の権限」をご参照ください。
MaxCompute Studio を使用して、次の 4 つの Java クラスを作成します:TextExtractor.java、TextOutputer.java、SplitReader.java、TextStorageHandler.java。Java プログラムの開発方法の詳細については、「UDF の開発」をご参照ください。
MaxCompute Studio のワンクリックパッケージング機能を使用して TextStorageHandler.java をパッケージ化し、MaxCompute リソースとしてアップロードします。
リソース名が
javatest-1.0-SNAPSHOT.jarであると仮定します。パッケージ化とアップロードの詳細については、「パッケージ化、アップロード、登録」をご参照ください。説明複数の依存関係が必要な場合は、それらを個別にパッケージ化し、MaxCompute リソースとしてアップロードしてください。
次の文を実行して、OSS 外部テーブルを作成します。
CREATE EXTERNAL TABLE ambulance_data_txt_external ( vehicleId INT, recordId INT, patientId INT, calls INT, locationLatitute DOUBLE, locationLongtitue DOUBLE, recordTime STRING, direction STRING ) stored BY 'com.aliyun.odps.udf.example.text.TextStorageHandler' WITH serdeproperties ( 'delimiter'='|', 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole' ) location 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/SampleData/' USING 'javatest-1.0-SNAPSHOT.jar'; -- 作成された外部テーブルの構造を表示するには、desc extended ambulance_data_txt_external; 文を実行します。説明delimiter パラメーターは、OSS オブジェクトの各行の列値を区切るために使用されるユーザー定義のデリミタです。有効な任意の文字列をデリミタとして使用できます。
OSS からデータを読み取ります。サンプル文:
SELECT recordId, patientId, direction FROM ambulance_data_txt_external 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 外部テーブルにデータを書き込みます。
INSERT INTO ambulance_data_txt_external VALUES (1,16,76,1,'46.81006','-92.08174','9/14/2014 0:10','SW'); -- 再度データをクエリして、データが書き込まれたかを確認します。OSS ディレクトリに新しいファイルが生成されたかを確認することもできます。 SELECT * FROM ambulance_data_txt_external WHERE recordId='16';
よくある質問
カスタム Extractor を使用して非構造化データから DATETIME データフィールドを読み取る際に、ODPS-0123131 エラーが報告されるのはなぜですか?
症状
カスタム Extractor を使用して非構造化データを読み取る際、データフィールドが `2019-11-11 06:43:36` のような DATETIME 型である場合に、次のエラーが返されます。
FAILED: ODPS-0123131:User defined function exception - Traceback: java.lang.IllegalArgumentException at java.sql.Date.valueOf(Date.java:143) at com.aliyun.odps.udf.example.text.TextExtractor.textLineToRecord(TextExtractor.java:194) at com.aliyun.odps.udf.example.text.TextExtractor.extract(TextExtractor.java:153) at com.aliyun.odps.udf.ExtractorHandler.extract(ExtractorHandler.java:120)原因
エラーは
Date.valueOf(parts)で発生します。java.sql.Date.valueOf()関数は、"yyyy-[m]m-[d]d"フォーマットの文字列パラメーターのみをサポートします。この関数は DATETIME フォーマットをサポートしていません。解決策
Joda-Time 依存関係を追加し、必要なクラスをコードにインポートします。
-- 依存関係。 <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>2.10</version> </dependency> -- インポート情報。 import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat;データを読み取る際に、
DateTimeFormat.forPattern()関数を使用して DATETIME 値を文字列に変換します。record.setDate(index, new Date(DateTime.parse(parts[i], DateTimeFormat.forPattern("yyyy-MM-dd HH:mi:ss")).getMillis()));
以下に例を示します。
MaxCompute クライアントを使用して、Extractor プロジェクトから生成された JAR パッケージをアップロードします。
add jar /Users/gary/big_data/odps/text_extractor/target/text_extractor-1.0-SNAPSHOT.jar/Users/gary/big_data/odps/text_extractor/target/text_extractor-1.0-SNAPSHOT.jarは、生成された JAR パッケージが保存されているローカルパスです。MaxCompute クライアントを使用して、サードパーティの Joda-Time JAR パッケージをアップロードします。
add jar /Users/gary/.m2/repository/joda-time/joda-time/2.10/joda-time-2.10.jar/Users/gary/.m2/repository/joda-time/joda-time/2.10/joda-time-2.10.jarは、サードパーティの Joda-Time JAR パッケージが保存されているローカルパスです。テストデータファイル (例:
video_play_log.txt) を OSS の指定されたディレクトリにアップロードします。ファイルには、次のサンプルデータを含めることができます。5c661071dba64d5080c91da085ff1073^music-click-fast_forward^26.12.XX.XX^2019-11-11 06:43:36外部テーブルからデータを読み取ります。
select * from <project_name>.video_play_log;次の結果が返されます。
+------+-------+---+----------------+ | uuid | action | ip | time | +------+-------+---+----------------+ | 5c661071dba64d5080c91da085ff1073 | music-click-fast_forward | 26.12.XX.XX | 2019-11-11 06:43:36 | +------+-------+---+----------------+