背景情報 Hadoop 3.0 を実行する場合、または E-MapReduce(EMR)で Spark、Hive、Presto などのサービスを使用する場合は、Object Storage Service (OSS) 内のデータを直接処理できます。MaxCompute や Data Lake Analytics (DLA) などの Alibaba Cloud サービスも OSS でサポートされています。
OSS が提供する GetObject オペレーションでは、ビッグデータプラットフォームが OSS オブジェクトをローカルコンピュータにダウンロードして分析およびフィルタリングする必要があります。その結果、多くのクエリシナリオで大量の帯域幅とクライアントリソースが浪費されます。
SelectObject オペレーションは、この問題に対処するために使用されます。SelectObject オペレーションを使用すると、OSS はビッグデータプラットフォームによって提供される条件と射影を使用してデータを事前にフィルタリングできます。その結果、有用なデータのみがビッグデータプラットフォームに返されます。これにより、クライアントは帯域幅リソースの消費を削減し、より少量のデータを処理して、CPU 使用率とメモリ使用量を最小限に抑えることができます。これにより、OSS ベースのデータウェアハウジングとデータ分析は、ビジネス要件により適したものになります。
請求ルール SelectObject オペレーションの呼び出し時にスキャンされるオブジェクトのサイズに基づいて課金されます。詳細については、「データ処理料金 」をご参照ください。
サポートされているオブジェクトタイプ このセクションでは、SelectObject オペレーションでサポートされているオブジェクトタイプについて説明します。
RFC 4180 に準拠する CSV オブジェクト(および TSV オブジェクトなどの CSV に類似したオブジェクト)。CSV オブジェクトでは、カスタムの行および列の区切り文字と引用符を指定できます。
UTF-8 エンコードされた JSON オブジェクト。SelectObject オペレーションは、DOCUMENT 形式と LINES 形式の JSON オブジェクトをサポートしています。
標準および低頻度アクセス(IA)オブジェクト。アーカイブ、コールドアーカイブ、およびディープコールドアーカイブオブジェクトは、SelectObject オペレーションがオブジェクトで呼び出される前にリストアする必要があります。
OSS によって完全に管理および暗号化されるか、Key Management Service (KMS) によって管理されるカスタマーマスターキー(CMK)を使用して暗号化されるオブジェクト。
サポートされているデータ型 デフォルトでは、OSS の CSV データは String 型です。CAST 関数を使用してデータ型を変換できます。
次の SQL 文の例は、1 番目と 2 番目の列のデータを Integer 型のデータに変換するために使用されます: Select * from OSSOBject where cast (_1 as int) > cast(_2 as int)
。
SelectObject オペレーションでは、WHERE 句を使用してデータ型を暗黙的に変換できます。たとえば、次の SQL 文は、1 番目と 2 番目の列のデータを Integer 型のデータに変換します:
Select _1 from ossobject where _1 + _2 > 100
CAST 関数を使用しない場合、JSON オブジェクトのデータの型は変更されません。標準の JSON オブジェクトは、Null、Bool、Int64、Double、String など、さまざまなデータ型をサポートできます。
SQL 文の例 CSV オブジェクトと JSON オブジェクトの SQL 文の例を示します。
CSV
シナリオ
SQL 文
最初の 10 行を返します。
select * from ossobject limit 10
1 番目と 3 番目の列の整数を返します。1 番目の列の整数値は、3 番目の列の整数値よりも大きくなります。
select _1, _3 from ossobject where cast(_1 as int) > cast(_3 as int)
1 番目の列のデータが X で始まるレコードの数を返します。LIKE の後に指定された漢字は UTF-8 エンコードである必要があります。
select count(*) from ossobject where _1 like 'X%'
2 番目の列の時間値が 2018-08-09 11:30:25 より後で、3 番目の列の値が 200 より大きいすべてのレコードを返します。
select * from ossobject where _2 > cast('2018-08-09 11:30:25' as timestamp) and _3 > 200
2 番目の列の浮動小数点数の平均値、合計、最大値、最小値を返します。
select AVG(cast(_6 as double)), SUM(cast(_6 as double)), MAX(cast(_6 as double)), MIN(cast(_6 as double)) from ossobject
1 番目と 3 番目の列のデータによって連結された文字列が Tom で始まり Anderson で終わるすべてのレコードを返します。
select * from ossobject where (_1 || _3) like 'Tom%Anderson'
1 番目の列の値が 3 で割り切れるすべてのレコードを返します。
select * from ossobject where (_1 % 3) = 0
1 番目の列の値が 1995 から 2012 の間のすべてのレコードを返します。
select * from ossobject where _1 between 1995 and 2012
5 番目の列の値が N、M、G、または L であるすべてのレコードを返します。
select * from ossobject where _5 in ('N', 'M', 'G', 'L')
2 番目と 3 番目の列の値の積が 100 と 5 番目の列の値の合計よりも大きいすべてのレコードを返します。
select * from ossobject where _2 * _3 > _5 + 100
JSON
JSON オブジェクトの例:
{
"contacts":[
{
"firstName": "John",
"lastName": "Smith",
"isAlive": true,
"age": 27,
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021-3100"
},
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "office",
"number": "646 555-4567"
},
{
"type": "mobile",
"number": "123 456-7890"
}
],
"children": [],
"spouse": null
}, …… # その他の類似ノードは省略されています。
]}
次の表に、JSON オブジェクトの SQL 文の例を示します。
シナリオ
SQL 文
age の値が 27 であるすべてのレコードを返します。
select * from ossobject.contacts[*] s where s.age = 27
すべての自宅の電話番号を返します。
select s.number from ossobject.contacts[*].phoneNumbers[*] s where s.type = "home"
spouse の値が null であるすべてのレコードを返します。
select * from ossobject s where s.spouse is null
children の値が 0 であるすべてのレコードを返します。
select * from ossobject s where s.children[0] is null
説明 上記の文は、他に使用できるメソッドがないため、空の配列を指定するために使用されます。
シナリオ ほとんどの場合、SelectObject は、マルチパートクエリ、JSON オブジェクトのクエリ、ログオブジェクトの分析に使用されます。
マルチパートクエリを使用してラージオブジェクトをクエリする
SelectObject オペレーションによって提供されるマルチパートクエリ機能は、GetObject オペレーションによって提供されるバイトベースのマルチパートダウンロード機能に似ています。データは、行または分割によってパーツに分割されます。
説明 分割によってデータを分割する方が効率的です。
CSV オブジェクトの列に改行が含まれていない場合は、バイトに基づいてオブジェクトをパーツに分割できます。このメソッドは、オブジェクトのメタを作成する必要がないため簡単です。JSON オブジェクトまたは列に改行が含まれる CSV オブジェクトをクエリする場合は、次の手順を実行します。
CreateSelectObjectMeta オペレーションを呼び出して、オブジェクトの分割の総数を取得します。スキャン時間を短縮するために、オブジェクトをクエリする前に SelectObject オペレーションを非同期的に呼び出すことをお勧めします。
クライアントのリソースに基づいて、適切な並行レベル(n)を選択します。分割の総数を並行レベル(n)で割って、各クエリに含まれる分割の数を取得します。
リクエスト本文のパラメータを設定して、マルチパートクエリを実行します。たとえば、split-range を 1 ~ 20 に設定できます。
結果を結合します。
JSON オブジェクトをクエリする
JSON オブジェクトをクエリする場合は、FROM 句で JSON パスの範囲を絞り込みます。
JSON オブジェクトの例:
{
"contacts":[
{
"firstName": "John",
"lastName": "Smith",
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021-3100"
},
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "office",
"number": "646 555-4567"
},
{
"type": "mobile",
"number": "123 456-7890"
}
]
}
]}
郵便番号が 10021 で始まるすべての番地をクエリするには、次の SQL 文を実行します: select s.address.streetAddress from ossobject.contacts[*] s where s.address.postalCode like '10021%'
または select s.streetAddress from ossobject.contacts[*].address s where s.postalCode like '10021%'
。
select s.streetAddress from ossobject.contacts[*].address s where s.postalCode like '10021%'
を実行する場合、JSON パスを含む SQL 文の方が正確であるため、パフォーマンスが向上します。
JSON オブジェクトの高精度浮動小数点数を処理する
JSON オブジェクトの高精度浮動小数点数を計算する場合は、ParseJsonNumberAsString パラメータを true に設定し、CAST 関数を使用して解析されたデータを Decimal 型に変換することをお勧めします。たとえば、属性 a の値が 123456789.123456789 の場合、select s.a from ossobject s where cast(s.a as decimal) > 123456789.12345
文を実行して、属性 a の精度を維持できます。
手順 OSS コンソールを使用する
重要 OSS コンソールでは、最大 128 MB のオブジェクトから最大 40 MB のデータを選択して取得できます。
OSS コンソール にログインします。
左側のナビゲーションウィンドウで、バケットリスト をクリックします。[バケット] ページで、目的のバケットを見つけてクリックします。
左側のナビゲーションツリーで、ファイル > オブジェクト を選択します。
ターゲットオブジェクトの右側にある [アクション] 列で、 を選択します。
[コンテンツの選択] パネルで、パラメータを設定します。次の表に、パラメータを示します。
パラメータ
説明
オブジェクトタイプ
有効な値: CSV および JSON。
区切り文字
このパラメータは、[オブジェクトタイプ] が [CSV] に設定されている場合にのみ使用できます。有効な値: , および [カスタム]。
タイトル行
このパラメータは、[オブジェクトタイプ] が [CSV] に設定されている場合にのみ使用できます。オブジェクトの最初の行に列タイトルが含まれているかどうかを指定します。
JSON 表示モード
このパラメータは、[オブジェクトタイプ] が [JSON] に設定されている場合にのみ使用できます。有効な値: JSON_LINES および JSON_DOCUMENT。
圧縮形式
オブジェクトを圧縮するかどうかを選択します。GZIP 圧縮のみがサポートされています。
[プレビュー] をクリックして、選択したデータをプレビューします。
重要 標準オブジェクトの選択したデータをプレビューすると、SelectObject オペレーションによって発生したデータスキャン料金が課金されます。IA、アーカイブ、コールドアーカイブ、またはディープコールドアーカイブオブジェクトの選択したデータをプレビューすると、SelectObject オペレーションによって発生したデータスキャン料金とデータ取得料金が課金されます。詳細については、「データ処理料金 」をご参照ください。
[次へ] をクリックします。SQL 文を入力して実行します。
たとえば、People という名前の CSV オブジェクトには、名前 、会社 、年齢 の列が含まれています。
50 歳以上で、名前が Lora で始まる人をクエリするには、次の SQL 文を実行します。この文では、_1、_2、_3 は列インデックスを指定します。_1 は最初の列のインデックスを指定します。_2 は 2 番目の列のインデックスを指定します。_3 は 3 番目の列のインデックスを指定します。
select * from ossobject where _1 like 'Lora*' and _3 > 50
オブジェクトの行数、最大年齢、最小年齢をクエリするには、次の SQL 文を実行します。
select count(*), max(cast(_3 as int)), min(cast(_3 as int)) from oss_object
実行結果を表示します。
[ダウンロード] をクリックして、選択したコンテンツをローカルコンピュータにダウンロードすることもできます。
OSS SDK を使用する オブジェクトのクエリには、OSS SDK for Java と OSS SDK for Python のみを使用できます。
Java import com.aliyun.oss.model.*;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
/**
* Select オブジェクトメタデータの作成と Select オブジェクトの例。
*
*/
public class SelectObjectSample {
// バケットが配置されているリージョンのエンドポイントを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、エンドポイントを https://oss-cn-hangzhou.aliyuncs.com に設定します。
private static String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// バケットの名前を指定します。例: examplebucket。
private static String bucketName = "examplebucket";
public static void main(String[] args) throws Exception {
// 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、リージョンを cn-hangzhou に設定します。
String region = "cn-hangzhou";
// OSSClient インスタンスを作成します。
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
// クエリするオブジェクトの完全なパスを指定し、SELECT 文を使用してオブジェクトのデータをクエリします。完全なパスにバケット名を含めないでください。
// CSV オブジェクトの完全なパスを指定します。
selectCsvSample("test.csv", ossClient);
// JSON オブジェクトの完全なパスを指定します。
selectJsonSample("test.json", ossClient);
ossClient.shutdown();
}
private static void selectCsvSample(String key, OSS ossClient) throws Exception {
// アップロードするオブジェクトのコンテンツを指定します。
String content = "name,school,company,age\r\n" +
"Lora Francis,School A,Staples Inc,27\r\n" +
"Eleanor Little,School B,\"Conectiv, Inc\",43\r\n" +
"Rosie Hughes,School C,Western Gas Resources Inc,44\r\n" +
"Lawrence Ross,School D,MetLife Inc.,24";
ossClient.putObject(bucketName, key, new ByteArrayInputStream(content.getBytes()));
SelectObjectMetadata selectObjectMetadata = ossClient.createSelectObjectMetadata(
new CreateSelectObjectMetadataRequest(bucketName, key)
.withInputSerialization(
new InputSerialization().withCsvInputFormat(
// コンテンツ内の異なるレコードを区切るために使用される区切り文字を指定します。例: \r\n。
new CSVFormat().withHeaderInfo(CSVFormat.Header.Use).withRecordDelimiter("\r\n"))));
System.out.println(selectObjectMetadata.getCsvObjectMetadata().getTotalLines());
System.out.println(selectObjectMetadata.getCsvObjectMetadata().getSplits());
SelectObjectRequest selectObjectRequest =
new SelectObjectRequest(bucketName, key)
.withInputSerialization(
new InputSerialization().withCsvInputFormat(
new CSVFormat().withHeaderInfo(CSVFormat.Header.Use).withRecordDelimiter("\r\n")))
.withOutputSerialization(new OutputSerialization().withCsvOutputFormat(new CSVFormat()));
// SELECT 文を使用して、4 番目の列の値が 40 より大きいすべてのレコードをクエリします。
selectObjectRequest.setExpression("select * from ossobject where _4 > 40");
OSSObject ossObject = ossClient.selectObject(selectObjectRequest);
// オブジェクトのコンテンツを読み取ります。
BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
while (true) {
String line = reader.readLine();
if (line == null) {
break;
}
System.out.println(line);
}
reader.close();
ossClient.deleteObject(bucketName, key);
}
private static void selectJsonSample(String key, OSS ossClient) throws Exception {
// アップロードするオブジェクトのコンテンツを指定します。
final String content = "{\n" +
"\t\"name\": \"Lora Francis\",\n" +
"\t\"age\": 27,\n" +
"\t\"company\": \"Staples Inc\"\n" +
"}\n" +
"{\n" +
"\t\"name\": \"Eleanor Little\",\n" +
"\t\"age\": 43,\n" +
"\t\"company\": \"Conectiv, Inc\"\n" +
"}\n" +
"{\n" +
"\t\"name\": \"Rosie Hughes\",\n" +
"\t\"age\": 44,\n" +
"\t\"company\": \"Western Gas Resources Inc\"\n" +
"}\n" +
"{\n" +
"\t\"name\": \"Lawrence Ross\",\n" +
"\t\"age\": 24,\n" +
"\t\"company\": \"MetLife Inc.\"\n" +
"}";
ossClient.putObject(bucketName, key, new ByteArrayInputStream(content.getBytes()));
SelectObjectRequest selectObjectRequest =
new SelectObjectRequest(bucketName, key)
.withInputSerialization(new InputSerialization()
.withCompressionType(CompressionType.NONE)
.withJsonInputFormat(new JsonFormat().withJsonType(JsonType.LINES)))
.withOutputSerialization(new OutputSerialization()
.withCrcEnabled(true)
.withJsonOutputFormat(new JsonFormat()))
.withExpression("select * from ossobject as s where s.age > 40"); // SELECT 文を使用してオブジェクト内のデータをクエリします。
OSSObject ossObject = ossClient.selectObject(selectObjectRequest);
// オブジェクトのコンテンツを読み取ります。
BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
while (true) {
String line = reader.readLine();
if (line == null) {
break;
}
System.out.println(line);
}
reader.close();
ossClient.deleteObject(bucketName, key);
}
}
Python import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
def select_call_back(consumed_bytes, total_bytes = None):
print('Consumed Bytes:' + str(consumed_bytes) + '\n')
# 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
# バケットが配置されているリージョンのエンドポイントを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、エンドポイントを https://oss-cn-hangzhou.aliyuncs.com に設定します。
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
# エンドポイントにマップするリージョンの ID を指定します。例: cn-hangzhou。署名アルゴリズム V4 を使用する場合は、このパラメータが必要です。
region = "cn-hangzhou"
# バケットの名前を指定します。
bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region)
key ='python_select.csv'
content ='Tom Hanks,USA,45\r\n'*1024
filename ='python_select.csv'
# CSV ファイルをアップロードします。
bucket.put_object(key, content)
# SelectObject オペレーションのパラメータを設定します。
csv_meta_params = {'RecordDelimiter': '\r\n'}
select_csv_params = {'CsvHeaderInfo': 'None',
'RecordDelimiter': '\r\n',
'LineRange': (500, 1000)}
csv_header = bucket.create_select_object_meta(key, csv_meta_params)
print(csv_header.rows)
print(csv_header.splits)
result = bucket.select_object(key, "select * from ossobject where _3 > 44", select_call_back, select_csv_params)
select_content = result.read()
print(select_content)
result = bucket.select_object_to_file(key, filename,
"select * from ossobject where _3 > 44", select_call_back, select_csv_params)
bucket.delete_object(key)
###JSON DOCUMENT
key = 'python_select.json'
content = "{\"contacts\":[{\"key1\":1,\"key2\":\"hello world1\"},{\"key1\":2,\"key2\":\"hello world2\"}]}"
filename = 'python_select.json'
# JSON DOCUMENT オブジェクトをアップロードします。
bucket.put_object(key, content)
select_json_params = {'Json_Type': 'DOCUMENT'}
result = bucket.select_object(key, "select s.key2 from ossobject.contacts[*] s where s.key1 = 1", None, select_json_params)
select_content = result.read()
print(select_content)
result = bucket.select_object_to_file(key, filename,
"select s.key2 from ossobject.contacts[*] s where s.key1 = 1", None, select_json_params)
bucket.delete_object(key)
###JSON LINES
key = 'python_select_lines.json'
content = "{\"key1\":1,\"key2\":\"hello world1\"}\n{\"key1\":2,\"key2\":\"hello world2\"}"
filename = 'python_select.json'
# JSON LINES オブジェクトをアップロードします。
bucket.put_object(key, content)
select_json_params = {'Json_Type': 'LINES'}
json_header = bucket.create_select_object_meta(key,select_json_params)
print(json_header.rows)
print(json_header.splits)
result = bucket.select_object(key, "select s.key2 from ossobject s where s.key1 = 1", None, select_json_params)
select_content = result.read()
print(select_content)
result = bucket.select_object_to_file(key, filename,
"select s.key2 from ossobject s where s.key1 = 1", None, select_json_params)
bucket.delete_object(key)
Go OSS API を使用する 高度なカスタマイズが必要な場合は、RESTful API を直接呼び出すことができます。API を直接呼び出すには、コードに署名計算を含める必要があります。詳細については、「SelectObject 」をご参照ください。