全部产品
Search
文档中心

MaxCompute:Ikhtisar

更新时间:Jul 02, 2025

MaxCompute memperkenalkan tipe data yang ditentukan pengguna (UDTs) berdasarkan mesin SQL generasi baru. UDTs memungkinkan Anda mereferensikan kelas atau objek dari bahasa pemrograman pihak ketiga dalam pernyataan SQL untuk memanggil metode atau mendapatkan data.

Pengenalan

UDTs yang didukung oleh banyak mesin SQL mirip dengan tipe STRUCT di MaxCompute. UDTs yang didukung oleh MaxCompute mirip dengan pernyataan CREATE TYPE. Sebuah UDT mencakup bidang dan metode. Anda tidak perlu menggunakan pernyataan DDL untuk mendefinisikan tipe data baru di MaxCompute. Sebagai gantinya, MaxCompute memungkinkan Anda mereferensikan tipe data baru secara langsung dalam pernyataan SQL. Contoh berikut menunjukkan cara menggunakan UDTs.

Sebagai contoh, untuk memanggil paket java.lang dalam pernyataan SQL, Anda dapat menggunakan salah satu metode berikut:

  • Gunakan UDTs untuk memanggil java.lang.

    -- Aktifkan tipe data baru. Contoh berikut menggunakan tipe INTEGER baru (INT).
    set odps.sql.type.system.odps2=true;    
    SELECT java.lang.Integer.MAX_VALUE;

    Mirip dengan Java, paket java.lang dapat dihilangkan. Oleh karena itu, pernyataan sebelumnya setara dengan pernyataan berikut:

    set odps.sql.type.system.odps2=true;
    SELECT Integer.MAX_VALUE;

    Hasil berikut dikembalikan:

    +-----------+
    | max_value |
    +-----------+
    | 2147483647 |
    +-----------+
  • Gunakan fungsi yang ditentukan pengguna (UDFs) untuk memanggil java.lang.

    1. Kembangkan kode. Kode berikut mendefinisikan kelas UDF.

      package com.aliyun.odps.test;
      public class IntegerMaxValue extends com.aliyun.odps.udf.UDF {
        public Integer evaluate() {
           return Integer.MAX_VALUE;
        } 
      }
    2. Kompilasi UDF menjadi paket JAR, unggah paket tersebut, dan buat fungsi.

      add jar odps-test.jar;
      create function integer_max_value as 'com.aliyun.odps.test.IntegerMaxValue' using 'odps-test.jar';
    3. Panggil fungsi dalam pernyataan SQL.

      select integer_max_value();

    Dalam contoh ini, UDTs menyederhanakan prosedur bagi Anda untuk menggunakan bahasa pemrograman lain guna memperluas fitur SQL.

Skenario

UDTs cocok untuk skenario berikut:

  • Anda ingin menggunakan beberapa fitur yang tidak disediakan oleh MaxCompute tetapi dapat diimplementasikan dalam bahasa pemrograman lain.

    Sebagai contoh, untuk mengimplementasikan beberapa fitur, Anda hanya perlu memanggil kelas bawaan Java sekali. Namun, MaxCompute tidak menyediakan metode untuk mengimplementasikan fitur-fitur ini. Jika Anda menggunakan UDF untuk menjalankan tugas-tugas ini, prosedurnya rumit.

  • Anda ingin memanggil pustaka pihak ketiga dalam pernyataan SQL untuk mengimplementasikan fitur terkait. Dalam skenario ini, UDF memungkinkan Anda langsung menggunakan fungsi yang disediakan oleh pustaka pihak ketiga dalam pernyataan SQL, alih-alih membungkus fungsi tersebut di dalam UDF.

  • Anda ingin langsung memanggil kode sumber bahasa pemrograman pihak ketiga dalam pernyataan SQL. SELECT TRANSFORM memungkinkan Anda menyertakan skrip dalam pernyataan SQL agar pernyataan SQL ini lebih mudah dibaca dan dipelihara. Untuk beberapa bahasa pemrograman, seperti Java, kode sumber hanya dapat dieksekusi setelah dikompilasi. Anda dapat menggunakan UDTs untuk mereferensikan objek dan kelas dari bahasa-bahasa ini dalam pernyataan SQL.

Batasan

Anda tidak dapat menggunakan UDF, UDAF, atau UDT untuk membaca data dari jenis tabel berikut:

  • Tabel tempat dilakukan evolusi skema.

  • Tabel yang berisi tipe data kompleks.

  • Tabel yang berisi tipe data JSON.

  • Tabel transaksional.

Implementasi

Contoh berikut menunjukkan cara menjalankan UDT.

-- Data sampel.
@table1 := select * from values ('100000000000000000000') as t(x);
@table2 := select * from values (100L) as t(y);
-- Logika kode.
-- Buat objek menggunakan metode baru.
@a := select new java.math.BigInteger(x) x from @table1;
-- Panggil metode statis.
@b := select java.math.BigInteger.valueOf(y) y from @table2;
-- Panggil metode instans.
select /*+mapjoin(b)*/ x.add(y).toString() from @a a join @b b;

-- Hasil berikut ditampilkan:
100000000000000000100

Gambar berikut menunjukkan proses.

UDT ini memiliki tiga tahap: M1, R2, dan J3. Jika operasi JOIN digunakan dalam MapReduce, data harus diacak ulang. Akibatnya, data diproses di beberapa tahap. Proses dan mesin fisik yang memproses data bervariasi di setiap tahap.

Hanya metode new java.math.BigInteger(x) yang dipanggil pada tahap M1.

Metode java.math.BigInteger.valueOf(y) dan x.add(y).toString() dipanggil secara terpisah pada tahap J3. Metode-metode ini dipanggil pada tahap yang berbeda dan dieksekusi dalam proses dan mesin fisik yang berbeda. UDT mengenkapsulasi tahapan ini untuk mencapai efek seperti semua tahap diimplementasikan pada Java Virtual Machine (JVM) yang sama.

Contoh sebelumnya menunjukkan bahwa hasil subquery mendukung kolom UDT. Kolom x yang diambil oleh variabel a adalah tipe java.math.BigInteger, bukan tipe bawaan. Anda dapat mentransfer data UDT ke operator lain dan kemudian memanggil metodenya. Anda juga dapat menggunakan data UDT dalam pengacakan data.

Fitur

  • UDTs hanya mendukung Java. Secara default, semua kelas dari SDK untuk Java dapat direferensikan oleh UDTs.

    Catatan

    Lingkungan runtime JDK adalah JDK 1.8. Versi yang lebih baru dari JDK 1.8 mungkin tidak didukung.

  • UDTs juga memungkinkan Anda mengunggah paket JAR dan langsung mereferensikan paket-paket ini. Bendera spesifik disediakan untuk UDTs.

    • set odps.sql.session.resources: menentukan sumber daya yang ingin Anda referensikan. Anda dapat menentukan beberapa sumber daya dan memisahkannya dengan koma (,). Contoh: set odps.sql.session.resources=foo.sh,bar.txt;.

      Catatan

      Bendera ini bekerja sama seperti bendera yang digunakan untuk menentukan sumber daya dalam pernyataan SELECT TRANSFORM. Oleh karena itu, bendera ini mengontrol dua fitur. Sebagai contoh, Anda dapat menggunakan UDT untuk mereferensikan paket JAR UDF yang telah kami sebutkan di Ikhtisar.

      set odps.sql.type.system.odps2=true;
      set odps.sql.session.resources=odps-test.jar;
      -- Tentukan paket JAR yang ingin Anda referensikan. Paket ini harus diunggah ke proyek yang diperlukan.
      select new com.aliyun.odps.test.IntegerMaxValue().evaluate();
    • odps.sql.session.java.imports: menentukan paket Java default. Anda dapat menentukan beberapa paket dan memisahkannya dengan koma (,). Bendera ini mirip dengan pernyataan IMPORT dalam Java. Anda dapat menentukan jalur kelas, seperti java.math.BigInteger, atau menggunakan *. Static import tidak didukung.

      Sebagai contoh, Anda dapat menggunakan UDT untuk mereferensikan paket JAR UDF yang telah kami sebutkan di Ikhtisar.

      set odps.sql.type.system.odps2=true;
      set odps.sql.session.resources=odps-test.jar;
      set odps.sql.session.java.imports=com.aliyun.odps.test.*;
      -- Tentukan paket JAR default.
      select new IntegerMaxValue().evaluate();
  • UDTs mendukung akses sumber daya. Dalam SQL MaxCompute, Anda dapat memanggil metode statis com.aliyun.odps.udf.impl.UDTExecutionContext.get() untuk mendapatkan objek ExecutionContext. Kemudian, Anda dapat menggunakan objek ini untuk mengakses kelas ExecutionContext saat ini dan kemudian mengakses sumber daya, seperti file dan tabel.

  • UDTs mendukung operasi berikut:

    • Buat objek menggunakan metode new.

    • Buat array menggunakan metode new. Daftar inisialisasi dapat digunakan. Contoh: new Integer[] { 1, 2, 3 }.

    • Panggil metode, termasuk metode statis.

    • Akses bidang, termasuk bidang statis.

    Catatan
    • Hanya metode publik dan bidang publik yang didukung.

    • Pengenal dalam UDT mencakup nama paket, kelas, metode, dan bidang. Semua pengenal bersifat peka huruf besar/kecil.

    • Kelas anonim dan ekspresi lambda tidak didukung.

    • UDTs digunakan dalam ekspresi. Fungsi yang tidak mengembalikan nilai tidak dapat dipanggil dalam ekspresi. Masalah ini akan diselesaikan di versi mendatang.

  • UDTs mendukung tipe data berikut:

    • UDTs mendukung konversi tipe SQL, seperti cast(1 as java.lang.Object). UDTs tidak mendukung konversi tipe Java, seperti (Object)1.

    • Tipe data Java dipetakan ke tipe data bawaan. Pemetaan ini dapat diterapkan pada UDTs. Untuk informasi lebih lanjut, lihat tabel pemetaan tipe data di Java UDFs.

      • Anda dapat langsung memanggil metode tipe Java ke mana tipe bawaan dipetakan. Contoh: '123'.length() , 1L.hashCode().

      • UDTs dapat digunakan dalam fungsi bawaan dan UDF. Sebagai contoh, dalam chr(Long.valueOf('100')), Long.valueOf mengembalikan nilai tipe java.lang.Long. Fungsi bawaan CHR mendukung tipe BIGINT bawaan.

      • Data dari tipe primitif Java secara otomatis dikonversi menjadi tipe kotak dan dua aturan sebelumnya berlaku.

      Catatan

      Untuk tipe data bawaan baru tertentu, Anda harus menggunakan set odps.sql.type.system.odps2=true; untuk mendeklarasikan tipe-tipe ini. Jika tidak, akan terjadi kesalahan.

    • Aturan konversi tipe berikut berlaku dalam UDTs:

      • Objek UDT dapat dikonversi secara implisit menjadi objek kelas dasarnya.

      • Objek UDT dapat dikonversi secara paksa menjadi objek kelas dasar atau kelas turunan.

      • Konversi tipe data antara dua objek tanpa pewarisan mengikuti aturan konversi asli. Namun, konversi semacam itu dapat mengakibatkan perubahan data. Sebagai contoh, data tipe java.lang.Long dapat dikonversi secara paksa menjadi tipe java.lang.Integer. Konversi ini menggunakan aturan yang digunakan untuk mengonversi tipe BIGINT bawaan menjadi tipe INT. Proses ini dapat mengakibatkan perubahan data dan bahkan hilangnya presisi data.

      Catatan

      Objek UDT tidak dapat disimpan ke disk. Ini berarti bahwa objek UDT tidak dapat dimasukkan ke dalam tabel karena pernyataan DDL tidak mendukung UDT. Namun, jika tipe data dapat dikonversi secara implisit menjadi salah satu tipe bawaan, Anda dapat membuat tabel yang berisi objek UDT. BINARY adalah tipe bawaan dan mendukung serialisasi otomatis. Anda dapat menyimpan array byte[] ke disk. Array byte[] yang disimpan dapat dideserialisasi ke tipe BINARY. Untuk menyimpan UDT, Anda harus memanggil metode serialisasi dan deserialisasi untuk mengonversi tipe data menjadi BINARY.

      Output tidak dapat berupa UDT. Namun, Anda dapat memanggil metode toString() untuk mengonversi tipe data menjadi tipe java.lang.String karena metode toString() mendukung semua kelas Java. Anda dapat menggunakan metode ini untuk memeriksa data UDT selama debugging.

      Anda juga dapat menambahkan bendera set odps.sql.udt.display.tostring=true; untuk mengaktifkan MaxCompute mengonversi semua data UDT keluaran menjadi string menggunakan metode java.util.Objects.toString(...). Ini memudahkan debugging. Bendera ini biasanya digunakan untuk debugging karena hanya dapat diterapkan pada pernyataan PRINT. Tidak dapat diterapkan pada pernyataan INSERT.

    • UDTs mendukung generics Java. Sebagai contoh, kompiler dapat menentukan bahwa nilai yang dikembalikan oleh java.util.Arrays.asList(new java.math.BigInteger('1')) adalah tipe java.util.List<java.math.BigInteger> berdasarkan tipe parameter.

      Catatan

      Anda harus menentukan parameter tipe dalam fungsi konstruktor atau menggunakan java.lang.Object. Ini sama seperti Java.

      Sebagai contoh, hasil dari new java.util.ArrayList(java.util.Arrays.asList('1', '2')) adalah tipe java.util.ArrayList<Object>. Hasil dari new java.util.ArrayList<String>(java.util.Arrays.asList('1', '2')) adalah tipe java.util.ArrayList<String>.

  • Semua operator menggunakan semantik SQL MaxCompute alih-alih UDTs.

    • Kombinasi string: Hasil dari String.valueOf(1) + String.valueOf(2) adalah 3. Dua string secara implisit dikonversi menjadi nilai bertipe DOUBLE dan dijumlahkan. Jika Anda menggunakan penggabungan string Java untuk menggabungkan string, hasilnya adalah 12.

    • Operasi =: Operator = dalam pernyataan SQL digunakan sebagai operator perbandingan. Digunakan untuk membandingkan satu ekspresi dengan ekspresi lain. Anda harus memanggil metode equals dalam Java untuk memeriksa apakah dua objek setara. Operator = tidak dapat digunakan untuk memverifikasi kesetaraan dua objek.

  • UDTs tidak memiliki definisi yang jelas tentang kesetaraan objek. Hal ini disebabkan oleh pengacakan data. Objek mungkin ditransmisikan antara proses atau mesin fisik yang berbeda. Selama transmisi objek, sebuah objek mungkin direferensikan sebagai dua objek yang berbeda. Sebagai contoh, sebuah objek mungkin diacak ke dua mesin dan kemudian diacak ulang. Oleh karena itu, ketika menggunakan UDTs, Anda harus menggunakan metode equals alih-alih operator = untuk memverifikasi kesetaraan dua objek.

    Objek dalam baris atau kolom yang sama berkorelasi dalam beberapa hal. Namun, korelasi antara objek dalam baris atau kolom yang berbeda tidak dapat dijamin.

  • UDTs tidak dapat digunakan sebagai kunci shuffle dalam klausa, seperti JOIN, GROUP BY, DISTRIBUTE BY, SORT BY, ORDER BY, atau CLUSTER BY.

    UDTs dapat digunakan pada tahap ekspresi, tetapi tidak dapat digunakan sebagai output. Sebagai contoh, Anda tidak dapat memanggil metode group by new java.math.BigInteger('123'). Namun, Anda dapat memanggil metode group by new java.math.BigInteger('123').hashCode(). Ini karena nilai yang dikembalikan oleh hashCode adalah tipe int.class, yang dapat digunakan sebagai tipe INT bawaan. Ini menerapkan aturan baik tipe bawaan maupun tipe Java tertentu.

  • Anda dapat menggunakan UDTs untuk mengimplementasikan fitur yang disediakan oleh fungsi SCALAR. Anda dapat menggunakan fungsi bawaan COLLECT_SET dan Fungsi lainnya dengan UDTs untuk mengimplementasikan fitur yang disediakan oleh fungsi agregat dan fungsi bernilai tabel.

Manfaat

UDTs memberikan manfaat berikut:

  • UDTs mudah digunakan. Anda tidak perlu mendefinisikan fungsi.

  • UDTs mendukung semua fitur JDK. Ini meningkatkan fleksibilitas SQL.

  • Kode UDT dapat disimpan dalam file yang sama dengan kode SQL. Ini memudahkan pengelolaan kode.

  • Anda dapat langsung mereferensikan pustaka bahasa pemrograman lain dan menggunakan kembali kode yang telah Anda tulis dalam bahasa lain.

  • Anda dapat membuat fitur berorientasi objek.

Fitur yang perlu ditingkatkan:

  • Panggil fungsi yang tidak mengembalikan nilai dan fungsi yang langsung menggunakan data yang ditransfer. Untuk fungsi yang langsung menggunakan data yang ditransfer, nilai kembaliannya diabaikan. Sebagai contoh, jika Anda memanggil metode add yang disediakan oleh antarmuka List, metode ini mengembalikan daftar yang telah Anda transfer.

  • Gunakan kelas anonim dan ekspresi lambda.

  • Gunakan UDTs sebagai kunci shuffle.

  • Dukung lebih banyak bahasa pemrograman, seperti Python.

Kinerja

UDTs berjalan dengan cara yang mirip dengan UDFs. Oleh karena itu, kinerja UDTs hampir sama dengan UDFs. Mesin komputasi yang dioptimalkan meningkatkan kinerja UDTs dalam skenario tertentu.

  • Jika objek UDT digunakan dalam proses yang berbeda, objek tersebut harus diserialisasi dan dideserialisasi. Jika Anda menggunakan UDTs untuk melakukan operasi yang tidak memerlukan pengacakan data, seperti JOIN atau AGGREGATE, overhead serialisasi dan deserialisasi dihindari.

  • Runtime UDTs didasarkan pada Codegen alih-alih refleksi. Oleh karena itu, tidak ada kehilangan kinerja. Beberapa UDTs dapat dieksekusi dalam satu panggilan fungsi. Dalam contoh sebelumnya, values[x].add(values[y]).divide(java.math.BigInteger.valueOf(2)) hanya dipanggil sekali. Oleh karena itu, tidak ada overhead antarmuka tambahan yang disebabkan meskipun unit operasional UDTs kecil.

Keamanan

Mirip dengan UDFs, UDTs dibatasi oleh model sandbox Java. Untuk melakukan operasi yang dibatasi, Anda harus membatalkan isolasi sandbox untuk operasi tersebut atau mengajukan permohonan untuk bergabung dengan daftar putih sandbox.