全部产品
Search
文档中心

Object Storage Service:Kueri objek

更新时间:Mar 20, 2026

SelectObject memungkinkan Anda menjalankan kueri SQL langsung pada objek di Object Storage Service (OSS) dan hanya mengambil data yang sesuai—tanpa perlu mengunduh seluruh objek terlebih dahulu. Fitur ini mengurangi konsumsi bandwidth serta menurunkan penggunaan CPU dan memori di sisi klien, sehingga analitik data berbasis OSS menjadi lebih efisien.

Cara kerja

Saat menggunakan GetObject, aplikasi Anda mengunduh seluruh objek sebelum melakukan penyaringan. SelectObject memindahkan proses penyaringan ke dalam OSS itu sendiri: Anda mengirimkan kondisi dan proyeksi SQL, lalu OSS hanya mengembalikan baris-baris yang sesuai.

Alur kueri:

  1. Kirim permintaan SelectObject dengan pernyataan SQL SELECT ... FROM ... WHERE dan format output.

  2. OSS memindai objek dan menerapkan kondisi serta proyeksi Anda di sisi server.

  3. OSS mengalirkan hanya catatan-catatan yang cocok kembali ke klien Anda.

  4. Untuk objek besar, panggil CreateSelectObjectMeta terlebih dahulu untuk mendapatkan jumlah total split, lalu jalankan kueri paralel menggunakan split-range.

Jenis objek yang didukung

TypeDetails
CSV (termasuk TSV dan format serupa)Harus sesuai dengan RFC 4180. Mendukung pemisah baris dan kolom kustom serta karakter quote.
JSON (UTF-8 encoded)Dua format: JSON DOCUMENT (satu objek JSON) dan JSON LINES (satu objek JSON per baris, dipisahkan oleh \n atau \r\n; tidak perlu konfigurasi delimiter).
Objek Standard dan Infrequent Access (IA)Dapat dikueri secara langsung. Objek Archive, Cold Archive, dan Deep Cold Archive harus dipulihkan terlebih dahulu sebelum dikueri.
Objek terenkripsiObjek yang dienkripsi menggunakan enkripsi yang dikelola OSS atau oleh customer master keys (CMKs) yang dikelola Key Management Service (KMS).

Batasan

LimitDetails
Jenis bucket tidak didukungBucket tanpa atribut zona (no-header-region) tidak mendukung SelectObject.
Batas data di KonsolKonsol OSS mendukung pemilihan hingga 40 MB data dari objek berukuran maksimal 128 MB.
Dukungan SDKHanya OSS SDK for Java dan OSS SDK for Python yang mendukung SelectObject.
KompresiHanya kompresi GZIP yang didukung saat mengkueri objek terkompresi.
Sensitivitas huruf pada LIKEPencocokan kabur berbasis LIKE bersifat case-sensitive.

Penagihan

Biaya SelectObject didasarkan pada jumlah data yang dipindai:

  • Objek Standar: biaya pemindaian data.

  • Objek IA, Archive, Cold Archive, dan Deep Cold Archive: biaya pemindaian data ditambah biaya pengambilan data.

Untuk detail harga, lihat Biaya pemrosesan data.

Sintaks SQL yang didukung

CategorySupported
StatementSELECT ... FROM ossobject [WHERE ...]
Data typesstring, int (64-bit), double (64-bit), decimal (128-bit), timestamp, bool
Logical operatorsAND, OR, NOT
Arithmetic operators+, -, *, /, %
Comparison operators>, =, <, >=, <=, !=
String operatorsLIKE, || (concatenation)
Aggregate functionsCOUNT, MAX, MIN, AVG, SUM
Type conversionCAST function

Tipe data dalam CSV vs. JSON

Data CSV secara default bertipe string. Gunakan CAST untuk mengonversi:

SELECT s.a FROM ossobject s WHERE CAST(s.a AS decimal) > 123456789.12345

Objek JSON mempertahankan tipe aslinya (Null, Bool, Int64, Double, String). Untuk bilangan titik mengambang presisi tinggi, atur ParseJsonNumberAsString ke true lalu cast ke decimal:

SELECT s.a FROM ossobject s WHERE CAST(s.a AS decimal) > 123456789.12345

Contoh SQL

Kueri CSV

Indeks kolom dimulai dari _1. Jika CSV memiliki baris header, Anda dapat mereferensikan kolom berdasarkan nama.

GoalSQL statement
Mengembalikan 10 baris pertamaSELECT * FROM ossobject LIMIT 10
Mengembalikan baris di mana kolom 1 (int) > kolom 3 (int)SELECT _1, _3 FROM ossobject WHERE CAST(_1 AS int) > CAST(_3 AS int)
Menghitung baris di mana kolom 1 diawali dengan XSELECT COUNT(*) FROM ossobject WHERE _1 LIKE 'X%'
Mengembalikan baris di mana kolom 2 setelah timestamp tertentu dan kolom 3 > 200SELECT * FROM ossobject WHERE _2 > CAST('2018-08-09 11:30:25' AS timestamp) AND _3 > 200
Fungsi agregat pada kolom 6 (double)SELECT AVG(CAST(_6 AS double)), SUM(CAST(_6 AS double)), MAX(CAST(_6 AS double)), MIN(CAST(_6 AS double)) FROM ossobject
Kolom yang digabungkan dan cocok dengan pola tertentuSELECT * FROM ossobject WHERE (_1 || _3) LIKE 'Tom%Anderson'
Baris di mana kolom 1 habis dibagi 3SELECT * FROM ossobject WHERE (_1 % 3) = 0
Baris di mana kolom 1 berada di antara 1995 dan 2012SELECT * FROM ossobject WHERE _1 BETWEEN 1995 AND 2012
Baris di mana kolom 5 adalah salah satu dari N, M, G, LSELECT * FROM ossobject WHERE _5 IN ('N', 'M', 'G', 'L')
Baris di mana (kolom2 x kolom3) > (kolom5 + 100)SELECT * FROM ossobject WHERE _2 * _3 > _5 + 100

Kueri JSON

Gunakan notasi titik dan wildcard array untuk menavigasi struktur bersarang. Mempersempit path di klausa FROM meningkatkan performa.

Diberikan objek contoh berikut:

{
  "contacts": [
    {
      "firstName": "John",
      "lastName": "Smith",
      "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
    }
  ]
}
GoalSQL statement
Kontak dengan usia = 27SELECT * FROM ossobject.contacts[*] s WHERE s.age = 27
Semua nomor telepon rumahSELECT s.number FROM ossobject.contacts[*].phoneNumbers[*] s WHERE s.type = 'home'
Kontak dengan spouse bernilai nullSELECT * FROM ossobject s WHERE s.spouse IS NULL
Kontak dengan array children kosongSELECT * FROM ossobject s WHERE s.children[0] IS NULL
Alamat jalan dengan kode pos yang diawali 10021SELECT s.streetAddress FROM ossobject.contacts[*].address s WHERE s.postalCode LIKE '10021%'
Catatan

Mempersempit path FROM (misalnya, ossobject.contacts[*].address) lebih efisien daripada menggunakan path luas lalu akses melalui notasi titik (misalnya, ossobject.contacts[*] lalu s.address.streetAddress).

Kueri objek menggunakan Konsol OSS

Penting

Konsol mendukung pemilihan hingga 40 MB data dari objek berukuran maksimal 128 MB.

  1. Masuk ke Konsol OSS.

  2. Pada panel navigasi kiri, klik Buckets. Temukan dan klik bucket target.

  3. Pada pohon navigasi kiri, pilih Object Management > Objects.

  4. Pada kolom Actions untuk objek target, pilih more > Select Content.

  5. Pada panel Select Content, konfigurasikan parameter berikut:

    ParameterDescription
    Object TypeCSV atau JSON
    DelimiterHanya untuk CSV. , atau Custom
    Title RowHanya untuk CSV. Apakah baris pertama berisi header kolom
    JSON Display ModeHanya untuk JSON. JSON_LINES atau JSON_DOCUMENT
    Compression FormatHanya GZIP
  6. Klik Preview untuk melihat pratinjau data yang dipilih.

    Penting

    Pratinjau objek Standard dikenai biaya pemindaian data. Pratinjau objek IA, Archive, Cold Archive, atau Deep Cold Archive dikenai biaya pemindaian data ditambah biaya pengambilan data. Untuk detailnya, lihat Biaya pemrosesan data.

  7. Klik Next, lalu masukkan dan jalankan pernyataan SQL. Contoh: Objek CSV bernama People memiliki tiga kolom: Name, Company, dan Age. Indeks kolomnya adalah _1 (Name), _2 (Company), dan _3 (Age).

    • Kueri orang berusia di atas 50 yang namanya diawali Lora:

      SELECT * FROM ossobject WHERE _1 LIKE 'Lora*' AND _3 > 50
    • Ambil jumlah baris, usia maksimum, dan usia minimum:

      SELECT COUNT(*), MAX(CAST(_3 AS int)), MIN(CAST(_3 AS int)) FROM oss_object
  8. Lihat hasilnya. Klik Download untuk menyimpan output ke mesin lokal Anda.

Kueri objek menggunakan OSS SDK

Hanya OSS SDK for Java dan OSS SDK for Python yang mendukung SelectObject.

Contoh Java

SDK Java menggunakan createSelectObjectMetadata untuk membuat metadata split dan selectObject untuk menjalankan kueri. Kredensial dimuat dari variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET.

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;

public class SelectObjectSample {
    // Ganti dengan endpoint wilayah bucket Anda.
    // Contoh: https://oss-cn-hangzhou.aliyuncs.com
    private static String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
    private static String bucketName = "examplebucket";

    public static void main(String[] args) throws Exception {
        // Muat kredensial dari variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET.
        EnvironmentVariableCredentialsProvider credentialsProvider =
            CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        String region = "cn-hangzhou";

        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
            .endpoint(endpoint)
            .credentialsProvider(credentialsProvider)
            .clientConfiguration(clientBuilderConfiguration)
            .region(region)
            .build();

        // Kueri objek CSV.
        selectCsvSample("test.csv", ossClient);
        // Kueri objek JSON LINES.
        selectJsonSample("test.json", ossClient);

        ossClient.shutdown();
    }

    private static void selectCsvSample(String key, OSS ossClient) throws Exception {
        // Unggah data CSV contoh dengan baris header.
        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()));

        // Buat metadata split untuk objek (disarankan sebelum kueri multipart).
        SelectObjectMetadata selectObjectMetadata = ossClient.createSelectObjectMetadata(
            new CreateSelectObjectMetadataRequest(bucketName, key)
                .withInputSerialization(
                    new InputSerialization().withCsvInputFormat(
                        new CSVFormat()
                            .withHeaderInfo(CSVFormat.Header.Use)
                            .withRecordDelimiter("\r\n"))));
        System.out.println("Total lines: " + selectObjectMetadata.getCsvObjectMetadata().getTotalLines());
        System.out.println("Total splits: " + selectObjectMetadata.getCsvObjectMetadata().getSplits());

        // Kueri baris di mana kolom ke-4 (usia) lebih besar dari 40.
        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()));
        selectObjectRequest.setExpression("SELECT * FROM ossobject WHERE _4 > 40");

        OSSObject ossObject = ossClient.selectObject(selectObjectRequest);
        BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
        reader.close();
        ossClient.deleteObject(bucketName, key);
    }

    private static void selectJsonSample(String key, OSS ossClient) throws Exception {
        // Unggah data JSON LINES contoh (satu objek JSON per baris).
        final String content = "{\"name\":\"Lora Francis\",\"age\":27,\"company\":\"Staples Inc\"}\n" +
                "{\"name\":\"Eleanor Little\",\"age\":43,\"company\":\"Conectiv, Inc\"}\n" +
                "{\"name\":\"Rosie Hughes\",\"age\":44,\"company\":\"Western Gas Resources Inc\"}\n" +
                "{\"name\":\"Lawrence Ross\",\"age\":24,\"company\":\"MetLife Inc.\"}";
        ossClient.putObject(bucketName, key, new ByteArrayInputStream(content.getBytes()));

        // Kueri catatan di mana usia > 40.
        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");

        OSSObject ossObject = ossClient.selectObject(selectObjectRequest);
        BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
        reader.close();
        ossClient.deleteObject(bucketName, key);
    }
}

Contoh Python

SDK Python menyediakan create_select_object_meta, select_object, dan select_object_to_file. Kredensial dimuat dari variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET.

import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider

def select_callback(consumed_bytes, total_bytes=None):
    print(f"Consumed bytes: {consumed_bytes}")

# Muat kredensial dari variabel lingkungan.
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())

endpoint = "https://oss-cn-hangzhou.aliyuncs.com"  # Ganti dengan endpoint bucket Anda.
region = "cn-hangzhou"                              # Ganti dengan wilayah bucket Anda.
bucket = oss2.Bucket(auth, endpoint, "examplebucket", region=region)

# --- Kueri CSV ---

key = "python_select.csv"
content = "Tom Hanks,USA,45\r\n" * 1024
bucket.put_object(key, content)

# Buat metadata split.
csv_meta_params = {"RecordDelimiter": "\r\n"}
csv_header = bucket.create_select_object_meta(key, csv_meta_params)
print(f"Total rows: {csv_header.rows}, total splits: {csv_header.splits}")

# Kueri baris di mana kolom 3 > 44.
select_csv_params = {
    "CsvHeaderInfo": "None",
    "RecordDelimiter": "\r\n",
    "LineRange": (500, 1000),
}
result = bucket.select_object(
    key, "SELECT * FROM ossobject WHERE _3 > 44", select_callback, select_csv_params
)
print(result.read())

# Simpan hasil ke file lokal.
bucket.select_object_to_file(
    key, "python_select.csv", "SELECT * FROM ossobject WHERE _3 > 44",
    select_callback, select_csv_params
)
bucket.delete_object(key)

# --- Kueri JSON DOCUMENT ---

key = "python_select.json"
content = '{"contacts":[{"key1":1,"key2":"hello world1"},{"key1":2,"key2":"hello world2"}]}'
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,
)
print(result.read())
bucket.delete_object(key)

# --- Kueri JSON LINES ---

key = "python_select_lines.json"
content = '{"key1":1,"key2":"hello world1"}\n{"key1":2,"key2":"hello world2"}'
bucket.put_object(key, content)

select_json_params = {"Json_Type": "LINES"}
json_header = bucket.create_select_object_meta(key, select_json_params)
print(f"Total rows: {json_header.rows}, total splits: {json_header.splits}")

result = bucket.select_object(
    key, "SELECT s.key2 FROM ossobject s WHERE s.key1 = 1", None, select_json_params
)
print(result.read())
bucket.delete_object(key)

Kueri objek menggunakan API OSS

Untuk memanggil SelectObject langsung melalui RESTful API, sertakan perhitungan signature dalam kode Anda. Untuk detailnya, lihat SelectObject.

Jalankan kueri paralel pada objek besar

Untuk objek besar, bagi kueri ke beberapa permintaan konkuren menggunakan split-range.

Kapan menggunakan split vs. byte range:

MethodWhen to use
By split (disarankan)Satu split mencakup beberapa baris dengan ukuran yang kira-kira sama. Gunakan untuk objek JSON dan objek CSV yang nilai kolomnya mungkin mengandung line feed tersemat.
By byte rangeLebih sederhana; tidak memerlukan metadata. Gunakan hanya untuk objek CSV yang nilai kolomnya tidak mengandung line feed.

Langkah-langkah untuk kueri paralel berbasis split:

  1. Panggil CreateSelectObjectMeta untuk mendapatkan jumlah total split. Panggil secara asinkron sebelum kueri pertama untuk menghindari overhead pemindaian tambahan.

  2. Pilih tingkat konkurensi n berdasarkan sumber daya klien yang tersedia.

  3. Bagi jumlah total split dengan n untuk mendapatkan jumlah split per permintaan.

  4. Kirimkan n permintaan SelectObject konkuren, masing-masing dengan parameter split-range. Contoh: split-range=1-20.

  5. Gabungkan hasilnya secara berurutan.

Langkah selanjutnya