MaxCompute SQL menyediakan pernyataan EXPLAIN untuk menganalisis hambatan kinerja dalam pernyataan query atau struktur tabel. Topik ini menjelaskan fungsi, format perintah, dan contoh penggunaan EXPLAIN.
Deskripsi
Pernyataan EXPLAIN menampilkan struktur rencana eksekusi dari pernyataan DQL di MaxCompute SQL. Pernyataan ini membantu Anda memahami cara eksekusi pernyataan SQL dan memberikan panduan untuk optimasi. Satu pernyataan query berkorespondensi dengan beberapa pekerjaan, dan satu pekerjaan berkorespondensi dengan beberapa tugas.
Jika pernyataan query kompleks dan ukuran baris dalam hasil keluaran pernyataan EXPLAIN melebihi 4 MB, ambang batas yang ditentukan oleh API aplikasi lapisan atas tercapai. Akibatnya, hasil keluaran tidak dapat sepenuhnya ditampilkan. Untuk mengatasi masalah ini, Anda dapat membagi pernyataan query menjadi beberapa subquery dan menjalankan pernyataan EXPLAIN pada setiap subquery untuk mendapatkan struktur pekerjaan.
Sintaksis
EXPLAIN <dml query>;dml query: wajib. Pernyataan SELECT. Untuk informasi lebih lanjut, lihat sintaksis SELECT.
Nilai Kembali
Hasil keluaran dari pernyataan EXPLAIN mencakup informasi berikut:
Ketergantungan antar pekerjaan
Sebagai contoh,
job0 adalah pekerjaan root. Jika sebuah query hanya memerlukanjob0, hanya satu baris data yang akan ditampilkan.Ketergantungan antar tugas
Dalam Job job0: tugas root: M1, M2 J3_1_2_Stg1 bergantung pada: M1, M2job0mencakup tugas-tugas berikut:M1,M2, danJ3_1_2_Stg1. MaxCompute menjalankan tugasJ3_1_2_Stg1setelah tugasM1danM2dijalankan.Konvensi penamaan tugas:
Jenis tugas:
MapTask(M),ReduceTask(R),JoinTask(J), danLocalWork(L).nullHuruf pertama dalam nama tugas menunjukkan jenis tugas tersebut. Sebagai contoh,
M2Stg1adalah tugas map.Digit yang mengikuti huruf pertama menunjukkan ID tugas. ID ini unik di antara semua tugas yang sesuai dengan query tertentu.
Digit yang dipisahkan oleh garis bawah (_) merepresentasikan ketergantungan langsung dari suatu tugas. Sebagai contoh,
J3_1_2_Stg1menunjukkan bahwa tugas dengan ID 3 bergantung pada tugas M1 dan M2.
Ketergantungan antar semua operator dalam suatu tugas
String operator menggambarkan semantik eksekusi dari suatu tugas. Struktur string operator:
Dalam Tugas M2: Sumber Data: mf_mc_bj.sale_detail_jt/sale_date=2013/region=china # Sumber data menggambarkan input dari tugas. TS: mf_mc_bj.sale_detail_jt/sale_date=2013/region=china # TableScanOperator FIL: ISNOTNULL(customer_id) # FilterOperator RS: order: + # ReduceSinkOperator nullDirection: * optimizeOrderBy: False valueDestLimit: 0 dist: HASH keys: customer_id values: customer_id (string) total_price (double) partitions: customer_id Dalam Tugas J3_1_2: JOIN: # JoinOperator StreamLineRead1 INNERJOIN StreamLineRead2 keys: 0:customer_id 1:customer_id AGGREGATE: group by:customer_id # GroupByOperator UDAF: SUM(total_price) (__agg_0_sum)[Complete],SUM(total_price) (__agg_1_sum)[Complete] RS: order: + nullDirection: * optimizeOrderBy: True valueDestLimit: 10 dist: HASH keys: customer_id values: customer_id (string) __agg_0 (double) __agg_1 (double) partitions: Dalam Tugas R4_3: SEL: customer_id,__agg_0,__agg_1 # SelectOperator LIM:limit 10 # LimitOperator FS: output: Screen # FileSinkOperator schema: customer_id (string) AS ashop __agg_0 (double) AS ap __agg_1 (double) AS bpDeskripsi operator:
TableScanOperator (TS): menggambarkan logika blok pernyataan
FROMdalam pernyataan query. Alias tabel input ditampilkan dalam hasil keluaran pernyataanEXPLAIN.SelectOperator (SEL): menggambarkan logika blok pernyataan
SELECTdalam pernyataan query. Kolom yang diteruskan ke operator berikutnya ditampilkan dalam hasil eksekusi pernyataanEXPLAIN. Beberapa kolom dipisahkan dengan koma (,).Jika kolom ditentukan, nilainya ditampilkan dalam format
<alias>.<column_name>.Jika ekspresi ditentukan, nilainya ditampilkan sebagai daftar fungsi, seperti
func1(arg1_1, arg1_2, func2(arg2_1, arg2_2)).Jika konstanta ditentukan, nilai konstanta tersebut ditampilkan.
FilterOperator (FIL): menggambarkan logika blok pernyataan
WHEREdalam pernyataan query. Hasil keluaran pernyataanEXPLAINmencakup ekspresiWHERE, yang memiliki bentuk yang mirip dengan SelectOperator.JoinOperator (JOIN): menggambarkan logika blok pernyataan
JOINdalam pernyataan query. Hasil keluaran pernyataanEXPLAINmenunjukkan tabel mana yang digabungkan dan dengan cara apa.GroupByOperator (AGGREGATE): menggambarkan logika operasi agregat. Operator ini ditampilkan jika fungsi agregat digunakan dalam pernyataan query. Isi fungsi agregat ditampilkan dalam hasil eksekusi pernyataan
EXPLAIN.ReduceSinkOperator (RS): menggambarkan logika distribusi data antar tugas. Jika hasil dari suatu tugas ditransfer ke tugas lain, ReduceSinkOperator harus digunakan untuk mendistribusikan data pada tahap terakhir tugas tersebut. Metode pengurutan hasil, kunci distribusi, nilai distribusi, dan kolom yang digunakan untuk menghitung nilai hash ditampilkan dalam hasil keluaran pernyataan
EXPLAIN.FileSinkOperator (FS): menggambarkan logika operasi penyimpanan pada catatan data akhir. Jika blok pernyataan
INSERTdisertakan dalam pernyataan query, nama tabel tempat Anda ingin menyisipkan data ditampilkan dalam hasil keluaran pernyataanEXPLAIN.LimitOperator (LIM): menggambarkan logika blok pernyataan
LIMITdalam pernyataan query. Jumlah baris yang dikembalikan yang ditentukan dalam blok pernyataanLIMITditampilkan dalam hasil eksekusi pernyataanEXPLAIN.MapjoinOperator (HASHJOIN): menggambarkan operasi
JOINpada tabel besar. Operator ini mirip dengan JoinOperator.
Data sampel
Data sampel sumber disediakan agar Anda lebih memahami contoh-contoh dalam topik ini. Pernyataan berikut menunjukkan cara membuat tabel sale_detail dan sale_detail_jt serta menyisipkan data ke dalam tabel tersebut.
-- Buat dua tabel partisi bernama sale_detail dan sale_detail_jt.
CREATE TABLE if NOT EXISTS sale_detail
(
shop_name STRING,
customer_id STRING,
total_price DOUBLE
)
PARTITIONED BY (sale_date STRING, region STRING);
CREATE TABLE if NOT EXISTS sale_detail_jt
(
shop_name STRING,
customer_id STRING,
total_price DOUBLE
)
PARTITIONED BY (sale_date STRING, region STRING);
-- Tambahkan partisi ke dua tabel tersebut.
ALTER TABLE sale_detail ADD PARTITION (sale_date='2013', region='china') PARTITION (sale_date='2014', region='shanghai');
ALTER TABLE sale_detail_jt ADD PARTITION (sale_date='2013', region='china');
-- Masukkan data ke dalam tabel.
INSERT INTO sale_detail PARTITION (sale_date='2013', region='china') VALUES ('s1','c1',100.1),('s2','c2',100.2),('s3','c3',100.3);
INSERT INTO sale_detail PARTITION (sale_date='2014', region='shanghai') VALUES ('null','c5',null),('s6','c6',100.4),('s7','c7',100.5);
INSERT INTO sale_detail_jt PARTITION (sale_date='2013', region='china') VALUES ('s1','c1',100.1),('s2','c2',100.2),('s5','c2',100.2);
-- Query data dari tabel sale_detail dan sale_detail_jt. Contoh pernyataan:
SET odps.sql.allow.fullscan=true;
SELECT * FROM sale_detail;
-- Hasil berikut dikembalikan:
+------------+-------------+-------------+------------+------------+
| shop_name | customer_id | total_price | sale_date | region |
+------------+-------------+-------------+------------+------------+
| s1 | c1 | 100.1 | 2013 | china |
| s2 | c2 | 100.2 | 2013 | china |
| s3 | c3 | 100.3 | 2013 | china |
| null | c5 | NULL | 2014 | shanghai |
| s6 | c6 | 100.4 | 2014 | shanghai |
| s7 | c7 | 100.5 | 2014 | shanghai |
+------------+-------------+-------------+------------+------------+
SET odps.sql.allow.fullscan=true;
SELECT * FROM sale_detail_jt;
-- Hasil berikut dikembalikan:
+------------+-------------+-------------+------------+------------+
| shop_name | customer_id | total_price | sale_date | region |
+------------+-------------+-------------+------------+------------+
| s1 | c1 | 100.1 | 2013 | china |
| s2 | c2 | 100.2 | 2013 | china |
| s5 | c2 | 100.2 | 2013 | china |
+------------+-------------+-------------+------------+------------+
-- Buat tabel untuk operasi JOIN.
SET odps.sql.allow.fullscan=true;
CREATE TABLE shop AS SELECT shop_name, customer_id, total_price FROM sale_detail;Contoh
Contoh berikut didasarkan pada Data Sampel.
Contoh 1
Pernyataan query:
SELECT a.customer_id AS ashop, SUM(a.total_price) AS ap,COUNT(b.total_price) AS bp FROM (SELECT * FROM sale_detail_jt WHERE sale_date='2013' AND region='china') a INNER JOIN (SELECT * FROM sale_detail WHERE sale_date='2013' AND region='china') b ON a.customer_id=b.customer_id GROUP BY a.customer_id ORDER BY a.customer_id LIMIT 10;Dapatkan rencana eksekusi dari pernyataan query:
EXPLAIN SELECT a.customer_id AS ashop, SUM(a.total_price) AS ap,COUNT(b.total_price) AS bp FROM (SELECT * FROM sale_detail_jt WHERE sale_date='2013' AND region='china') a INNER JOIN (SELECT * FROM sale_detail WHERE sale_date='2013' AND region='china') b ON a.customer_id=b.customer_id GROUP BY a.customer_id ORDER BY a.customer_id LIMIT 10;Hasil berikut dikembalikan:
job0 adalah pekerjaan root Dalam Job job0: tugas root: M1 M2_1 bergantung pada: M1 R3_2 bergantung pada: M2_1 R4_3 bergantung pada: R3_2 Dalam Tugas M1: Sumber Data: doc_****.default.sale_detail/sale_date=2013/region=china TS: doc_****.default.sale_detail/sale_date=2013/region=china Statistik: Num rows: 3.0, Data size: 324.0 FIL: ISNOTNULL(customer_id) Statistik: Num rows: 2.7, Data size: 291.6 RS: valueDestLimit: 0 dist: BROADCAST keys: values: customer_id (string) total_price (double) partitions: Statistik: Num rows: 2.7, Data size: 291.6 Dalam Tugas M2_1: Sumber Data: doc_****.default.sale_detail_jt/sale_date=2013/region=china TS: doc_****.default.sale_detail_jt/sale_date=2013/region=china Statistik: Num rows: 3.0, Data size: 324.0 FIL: ISNOTNULL(customer_id) Statistik: Num rows: 2.7, Data size: 291.6 HASHJOIN: Filter1 INNERJOIN StreamLineRead1 keys: 0:customer_id 1:customer_id non-equals: 0: 1: bigTable: Filter1 Statistik: Num rows: 3.6450000000000005, Data size: 787.32 RS: order: + nullDirection: * optimizeOrderBy: False valueDestLimit: 0 dist: HASH keys: customer_id values: customer_id (string) total_price (double) total_price (double) partitions: customer_id Statistik: Num rows: 3.6450000000000005, Data size: 422.82000000000005 Dalam Tugas R3_2: AGGREGATE: group by:customer_id UDAF: SUM(total_price) (__agg_0_sum)[Complete],COUNT(total_price) (__agg_1_count)[Complete] Statistik: Num rows: 1.0, Data size: 116.0 RS: order: + nullDirection: * optimizeOrderBy: True valueDestLimit: 10 dist: HASH keys: customer_id values: customer_id (string) __agg_0 (double) __agg_1 (bigint) partitions: Statistik: Num rows: 1.0, Data size: 116.0 Dalam Tugas R4_3: SEL: customer_id,__agg_0,__agg_1 Statistik: Num rows: 1.0, Data size: 116.0 SEL: customer_id ashop, __agg_0 ap, __agg_1 bp, customer_id Statistik: Num rows: 1.0, Data size: 216.0 FS: output: Screen schema: ashop (string) ap (double) bp (bigint) Statistik: Num rows: 1.0, Data size: 116.0 OK
Contoh 2
Pernyataan query:
SELECT /*+ mapjoin(a) */ a.customer_id AS ashop, SUM(a.total_price) AS ap,COUNT(b.total_price) AS bp FROM (SELECT * FROM sale_detail_jt WHERE sale_date='2013' AND region='china') a INNER JOIN (SELECT * FROM sale_detail WHERE sale_date='2013' AND region='china') b ON a.total_price<b.total_price GROUP BY a.customer_id ORDER BY a.customer_id LIMIT 10;Dapatkan rencana eksekusi dari pernyataan query:
EXPLAIN SELECT /*+ mapjoin(a) */ a.customer_id AS ashop, SUM(a.total_price) AS ap,COUNT(b.total_price) AS bp FROM (SELECT * FROM sale_detail_jt WHERE sale_date='2013' AND region='china') a INNER JOIN (SELECT * FROM sale_detail WHERE sale_date='2013' AND region='china') b ON a.total_price<b.total_price GROUP BY a.customer_id ORDER BY a.customer_id LIMIT 10;Hasil berikut dikembalikan:
job0 adalah pekerjaan root Dalam Job job0: tugas root: M1 M2_1 bergantung pada: M1 R3_2 bergantung pada: M2_1 R4_3 bergantung pada: R3_2 Dalam Tugas M1: Sumber Data: doc_****.sale_detail_jt/sale_date=2013/region=china TS: doc_****.sale_detail_jt/sale_date=2013/region=china Statistik: Num rows: 3.0, Data size: 324.0 RS: valueDestLimit: 0 dist: BROADCAST keys: values: customer_id (string) total_price (double) partitions: Statistik: Num rows: 3.0, Data size: 324.0 Dalam Tugas M2_1: Sumber Data: doc_****.sale_detail/sale_date=2013/region=china TS: doc_****.sale_detail/sale_date=2013/region=china Statistik: Num rows: 3.0, Data size: 24.0 HASHJOIN: StreamLineRead1 INNERJOIN TableScan2 keys: 0: 1: non-equals: 0: 1: bigTable: TableScan2 Statistik: Num rows: 9.0, Data size: 1044.0 FIL: LT(total_price,total_price) Statistik: Num rows: 6.75, Data size: 783.0 AGGREGATE: group by:customer_id UDAF: SUM(total_price) (__agg_0_sum)[Partial_1],COUNT(total_price) (__agg_1_count)[Partial_1] Statistik: Num rows: 2.3116438356164384, Data size: 268.1506849315069 RS: order: + nullDirection: * optimizeOrderBy: False valueDestLimit: 0 dist: HASH keys: customer_id values: customer_id (string) __agg_0_sum (double) __agg_1_count (bigint) partitions: customer_id Statistik: Num rows: 2.3116438356164384, Data size: 268.1506849315069 Dalam Tugas R3_2: AGGREGATE: group by:customer_id UDAF: SUM(__agg_0_sum)[Final] __agg_0,COUNT(__agg_1_count)[Final] __agg_1 Statistik: Num rows: 1.6875, Data size: 195.75 RS: order: + nullDirection: * optimizeOrderBy: True valueDestLimit: 10 dist: HASH keys: customer_id values: customer_id (string) __agg_0 (double) __agg_1 (bigint) partitions: Statistik: Num rows: 1.6875, Data size: 195.75 Dalam Tugas R4_3: SEL: customer_id,__agg_0,__agg_1 Statistik: Num rows: 1.6875, Data size: 195.75 SEL: customer_id ashop, __agg_0 ap, __agg_1 bp, customer_id Statistik: Num rows: 1.6875, Data size: 364.5 FS: output: Screen schema: ashop (string) ap (double) bp (bigint) Statistik: Num rows: 1.6875, Data size: 195.75 OK