Jika tagihan MaxCompute Anda terus meningkat dan biaya menjadi sulit dikelola, Anda dapat mengoptimalkan pekerjaan SQL dan pekerjaan MapReduce untuk mengurangi biaya komputasi. Topik ini menjelaskan cara mengontrol biaya komputasi untuk pekerjaan SQL dan pekerjaan MapReduce.
Estimasi biaya komputasi
Anda dapat memperkirakan biaya komputasi sebelum menjalankan pekerjaan komputasi. Untuk informasi lebih lanjut, lihat Alat TCO dalam topik "Pilih metode penagihan". Anda juga dapat mengonfigurasi peringatan untuk konsumsi sumber daya guna mencegah biaya tambahan yang tidak diinginkan. Jika biaya komputasi tinggi, Anda dapat menggunakan metode yang dijelaskan dalam topik ini untuk menguranginya.
Kontrol biaya komputasi pekerjaan SQL
Beberapa pekerjaan SQL yang memicu pemindaian tabel penuh menimbulkan biaya komputasi yang tinggi. Penjadwalan pekerjaan SQL yang sering dapat menyebabkan penumpukan pekerjaan, yang juga meningkatkan biaya komputasi. Jika terjadi penumpukan dan metode penagihan bayar sesuai pemakaian digunakan, pekerjaan akan antre dan memerlukan lebih banyak sumber daya. Akibatnya, tagihan yang dihasilkan keesokan harinya menjadi sangat tinggi. Anda dapat menggunakan metode berikut untuk mengontrol biaya komputasi pekerjaan SQL:
Hindari penjadwalan yang sering. MaxCompute menyediakan layanan komputasi untuk memproses sejumlah besar data sekaligus. Ini berbeda dari layanan komputasi waktu nyata. Jika pekerjaan SQL dieksekusi dalam interval pendek, frekuensi komputasi meningkat. Frekuensi komputasi yang meningkat dan eksekusi pekerjaan SQL yang tidak tepat menyebabkan peningkatan biaya komputasi. Jika Anda memerlukan penjadwalan yang sering, gunakan CostSQL untuk memperkirakan biaya pekerjaan SQL guna menghindari biaya tambahan.
Kurangi pemindaian tabel penuh. Anda dapat menggunakan metode berikut:
Tentukan parameter yang diperlukan untuk menonaktifkan fitur pemindaian tabel penuh. Anda dapat menonaktifkan fitur ini untuk Sesi atau Proyek.
-- Nonaktifkan fitur untuk Sesi. set odps.sql.allow.fullscan=false; -- Nonaktifkan fitur untuk Proyek. SetProject odps.sql.allow.fullscan=false;Pangkas kolom. Pemangkasan kolom memungkinkan sistem membaca data hanya dari kolom yang diperlukan. Kami merekomendasikan agar Anda tidak menggunakan pernyataan
SELECT *. Hal ini karena pemindaian tabel penuh dipicu saat Anda mengeksekusi pernyataan tersebut.SELECT a,b FROM T WHERE e < 10;Dalam pernyataan ini, tabel T berisi kolom
a, b, c, d, dan e. Namun, hanya kolom a, b, dan e yang dibaca.Pangkas partisi. Pemangkasan partisi memungkinkan Anda menentukan kondisi filter untuk kolom kunci partisi. Dengan cara ini, sistem membaca data hanya dari partisi yang diperlukan. Ini menghindari kesalahan dan pemborosan sumber daya yang disebabkan oleh pemindaian tabel penuh.
SELECT a,b FROM T WHERE partitiondate='2017-10-01';Optimalkan kata kunci SQL yang menimbulkan biaya. Kata kunci tersebut meliputi JOIN, GROUP BY, ORDER BY, DISTINCT, dan INSERT INTO. Anda dapat mengoptimalkan kata kunci berdasarkan aturan berikut:
Sebelum operasi JOIN, Anda harus memangkas partisi. Jika tidak, pemindaian tabel penuh mungkin dilakukan. Untuk informasi lebih lanjut tentang skenario di mana pemangkasan partisi tidak berlaku, lihat Skenario di mana pemangkasan partisi tidak berlaku dalam topik "Periksa apakah pemangkasan partisi efektif".
Gunakan UNION ALL alih-alih FULL OUTER JOIN.
SELECT COALESCE(t1.id, t2.id) AS id, SUM(t1.col1) AS col1 , SUM(t2.col2) AS col2 FROM ( SELECT id, col1 FROM table1 ) t1 FULL OUTER JOIN ( SELECT id, col2 FROM table2 ) t2 ON t1.id = t2.id GROUP BY COALESCE(t1.id, t2.id); -- Dioptimalkan: SELECT t.id, SUM(t.col1) AS col1, SUM(t.col2) AS col2 FROM ( SELECT id, col1, 0 AS col2 FROM table1 UNION ALL SELECT id, 0 AS col1, col2 FROM table2 ) t GROUP BY t.id;Jangan masukkan GROUP BY dalam UNION ALL. Gunakan GROUP BY di luar UNION ALL.
SELECT t.id, SUM(t.val) AS val FROM ( SELECT id, SUM(col3) AS val FROM table3 GROUP BY id UNION ALL SELECT id, SUM(col4) AS val FROM table4 GROUP BY id ) t GROUP BY t.id; Dioptimalkan:--------------------------- SELECT t.id, SUM(t.val) AS val FROM ( SELECT id, col3 AS val FROM table3 UNION ALL SELECT id, col4 AS val FROM table4 ) t GROUP BY t.id;Untuk mengurutkan data yang diekspor sementara, urutkan data menggunakan alat seperti EXCEL alih-alih ORDER BY.
Jangan gunakan DISTINCT. Gunakan GROUP BY sebagai gantinya.
SELECT COUNT(DISTINCT id) AS cnt FROM table1; Dioptimalkan:--------------------------- SELECT COUNT(1) AS cnt FROM ( SELECT id FROM table1 GROUP BY id ) t;Jangan gunakan INSERT INTO untuk menulis data. Tambahkan bidang partisi sebagai gantinya. Ini mengurangi kompleksitas SQL dan menghemat biaya komputasi.
Jangan jalankan pernyataan SQL untuk melihat pratinjau data tabel. Anda dapat menggunakan fitur pratinjau tabel untuk melihat data tabel. Metode ini tidak mengonsumsi sumber daya komputasi. Jika Anda menggunakan DataWorks, Anda dapat melihat pratinjau tabel dan detail tabel pada halaman Data Map. Untuk informasi lebih lanjut, lihat Lihat Detail Tabel. Jika Anda menggunakan MaxCompute Studio, klik dua kali tabel untuk melihat pratinjau datanya.
Pilih alat yang sesuai untuk komputasi data. MaxCompute merespons permintaan dalam hitungan menit. Ini tidak cocok untuk permintaan frontend. Hasil komputasi disinkronkan ke sistem penyimpanan eksternal. Sebagian besar pengguna menggunakan database relasional untuk menyimpan hasil. Kami merekomendasikan agar Anda menggunakan MaxCompute untuk pekerjaan komputasi ringan dan database relasional, seperti ApsaraDB for RDS, untuk permintaan frontend. Permintaan frontend memerlukan pembuatan hasil permintaan secara real-time. Jika hasil permintaan ditampilkan di frontend, klausa bersyarat tidak dieksekusi pada data. Data tidak diagregasi atau dikaitkan dengan kamus. Permintaan bahkan tidak mencakup klausa WHERE.
Kontrol biaya komputasi pekerjaan MapReduce
Anda dapat menggunakan metode berikut untuk mengontrol biaya komputasi pekerjaan MapReduce:
Konfigurasikan pengaturan yang diperlukan
Ukuran Split
Ukuran split default untuk mapper adalah 256 MB. Ukuran split menentukan jumlah mapper. Jika logika kode untuk mapper memakan waktu, Anda dapat menggunakan
JobConf#setSplitSizeuntuk mengurangiukuran split. Anda harus mengonfigurasiukuran splityang sesuai. Jika tidak, sumber daya komputasi yang berlebihan mungkin dikonsumsi.Instance Reduce MapReduce
Secara default, jumlah reducer yang digunakan untuk menyelesaikan pekerjaan adalah seperempat dari jumlah mapper. Anda dapat mengatur jumlah reducer ke nilai yang berkisar antara 0 hingga 2.000. Lebih banyak reducer memerlukan lebih banyak sumber daya komputasi, yang meningkatkan biaya. Anda harus mengonfigurasi jumlah reducer dengan tepat.
Kurangi jumlah pekerjaan MapReduce
Jika beberapa pekerjaan MapReduce saling terkait dan output suatu pekerjaan merupakan input pekerjaan berikutnya, kami sarankan Anda menggunakan mode pipeline. Mode pipeline memungkinkan Anda menggabungkan beberapa pekerjaan MapReduce seri menjadi satu pekerjaan. Ini mengurangi operasi disk I/O redundan yang disebabkan oleh tabel antara dan meningkatkan kinerja. Ini juga menyederhanakan penjadwalan pekerjaan dan meningkatkan efisiensi pemeliharaan proses. Untuk informasi lebih lanjut, lihat Contoh Pipeline.
Pangkas kolom tabel input
Untuk tabel input yang berisi sejumlah besar kolom, hanya beberapa kolom yang diproses oleh mapper. Saat Anda menambahkan tabel input, Anda dapat menentukan kolom untuk mengurangi jumlah data yang perlu dibaca. Misalnya, untuk memproses data di kolom c1 dan c2, gunakan konfigurasi berikut:
InputUtils.addTable(TableInfo.builder().tableName("wc_in").cols(new String[]{"c1","c2"}).build(), job);Setelah konfigurasi, mapper membaca data hanya dari kolom c1 dan c2. Ini tidak memengaruhi data yang diperoleh berdasarkan nama kolom. Namun, ini mungkin memengaruhi data yang diperoleh berdasarkan subskrip.
Hindari pembacaan sumber daya berulang
Kami sarankan Anda membaca sumber daya di tahap setup. Ini mencegah hilangnya kinerja yang disebabkan oleh pembacaan sumber daya berulang. Anda dapat membaca sumber daya hingga 64 kali. Untuk informasi lebih lanjut, lihat Contoh Penggunaan Sumber Daya.
Kurangi overhead pembuatan objek
Untuk objek Java yang digunakan setiap kali dalam tahap map dan reduce, cegah pembuatannya di fungsi map atau reduce. Anda dapat meletakkannya di tahap setup untuk mencegah overhead yang disebabkan oleh pembuatan berulang.
{ ... Record word; Record one; public void setup(TaskContext context) throws IOException { // Buat objek Java di tahap setup. Ini mencegah pembuatan ulang objek Java di setiap tahap map. word = context.createMapOutputKeyRecord(); one = context.createMapOutputValueRecord(); one.set(new Object[]{1L}); } ... }Gunakan combiner dengan cara yang tepat
Jika output tugas map berisi beberapa kunci duplikat, Anda dapat menggunakan combiner untuk menggabungkan kunci tersebut. Ini mengurangi bandwidth transmisi dan overhead Pengacakan. Jika output tugas map tidak berisi beberapa kunci duplikat, menggunakan combiner dapat menimbulkan overhead tambahan. Combiner mengimplementasikan antarmuka reducer. Kode berikut mendefinisikan combiner dalam program WordCount:
/** * Kelas combiner yang menggabungkan output map dengan menjumlahkannya. */ public static class SumCombiner extends ReducerBase { private Record count; @Override public void setup(TaskContext context) throws IOException { count = context.createMapOutputValueRecord(); } @Override public void reduce(Record key, Iterator<Record> values, TaskContext context) throws IOException { long c = 0; while (values.hasNext()) { Record val = values.next(); c += (Long) val.get(0); } count.set(0, c); context.write(key, count); } }Pilih kolom kunci partisi yang sesuai atau sesuaikan partisioner
Anda dapat menggunakan
JobConf#setPartitionColumnsuntuk menentukan kolom kunci partisi. Kolom kunci partisi default didefinisikan dalam skema kunci. Jika Anda menggunakan metode ini, data ditransfer ke reducer berdasarkan nilai hash kolom yang ditentukan. Ini mencegah masalah ekor panjang yang disebabkan oleh skew data. Anda juga dapat menyesuaikan partisioner jika perlu. Kode berikut menunjukkan cara menyesuaikan partisioner:import com.aliyun.odps.mapred.Partitioner; public static class MyPartitioner extends Partitioner { @Override public int getPartition(Record key, Record value, int numPartitions) { // numPartitions menunjukkan jumlah reducer. // Fungsi ini digunakan untuk menentukan reducer ke mana kunci tugas map ditransfer. String k = key.get(0).toString(); return k.length() % numPartitions; } }Konfigurasikan pengaturan berikut dalam jobconf:
jobconf.setPartitionerClass(MyPartitioner.class)Tentukan jumlah reducer dalam jobconf.
jobconf.setNumReduceTasks(num)Konfigurasikan parameter memori JVM sesuai kebutuhan
Memori besar pekerjaan MapReduce meningkatkan biaya komputasi. Dalam konfigurasi standar, 1 core CPU dan 4 GB memori dikonfigurasi, dan
odps.stage.reducer.jvm.memdiatur ke 4006. Rasio core CPU terhadap memori yang besar (lebih besar dari1:4) juga meningkatkan biaya komputasi.
Referensi
Saat menggunakan MaxCompute, Anda dapat mengoptimalkan biaya dalam hal penyimpanan serta unggah dan unduh data. Untuk informasi lebih lanjut, lihat Optimalkan Biaya Penyimpanan dan Optimalkan Biaya Unggah dan Unduh Data.
Untuk informasi lebih lanjut tentang cara menganalisis dan mengoptimalkan pengecualian dalam tagihan, lihat Kelola Biaya.
Untuk informasi lebih lanjut tentang cara mengoptimalkan biaya komputasi dan meningkatkan pemanfaatan sumber daya, lihat Hasilkan Rencana Optimasi Sumber Daya Komputasi.