全部产品
Search
文档中心

AnalyticDB:Gunakan perintah EXPLAIN dan EXPLAIN ANALYZE untuk menganalisis rencana eksekusi

更新时间:Mar 18, 2026

Topik ini menjelaskan cara menggunakan perintah EXPLAIN dan EXPLAIN ANALYZE untuk menganalisis rencana eksekusi.

Prasyarat

Versi kluster AnalyticDB for MySQL adalah V3.1.3 atau lebih baru.

Catatan Untuk informasi tentang cara memeriksa versi kluster AnalyticDB for MySQL, lihat Bagaimana cara saya melihat versi kluster AnalyticDB for MySQL? Untuk meningkatkan versi, Submit a ticket.

EXPLAIN

Anda dapat menggunakan perintah EXPLAIN untuk mengevaluasi jalur eksekusi yang direncanakan dari pernyataan kueri SQL. Evaluasi ini hanya bersifat referensi dan tidak mencerminkan hasil eksekusi aktual.

  • Sintaksis
    EXPLAIN (format text) <SELECT statement>;
    Catatan Jika pernyataan kueri SQL tidak kompleks, Anda dapat menambahkan bidang (format text) ke perintah EXPLAIN untuk meningkatkan keterbacaan hierarki pohon dalam hasil yang dikembalikan.
  • Contoh
    EXPLAIN (format text)
          SELECT count(*)
          FROM
          nation, region, customer
          WHERE
          c_nationkey = n_nationkey
          AND n_regionkey = r_regionkey
          AND r_name = 'ASIA';
    Hasil berikut dikembalikan:
    Output[count(*)]
    │   Outputs: [count:bigint]
    │   Estimates: {rows: 1 (8B)}
    │   count(*) := count
    └─ Aggregate(FINAL)
       │   Outputs: [count:bigint]
       │   Estimates: {rows: 1 (8B)}
       │   count := count(`count_1`)
       └─ LocalExchange[SINGLE] ()
          │   Outputs: [count_0_1:bigint]
          │   Estimates: {rows: 1 (8B)}
          └─ RemoteExchange[GATHER]
             │   Outputs: [count_0_2:bigint]
             │   Estimates: {rows: 1 (8B)}
             └─ Aggregate(PARTIAL)
                │   Outputs: [count_0_4:bigint]
                │   Estimates: {rows: 1 (8B)}
                │   count_4 := count(*)
                └─ InnerJoin[(`c_nationkey` = `n_nationkey`)][$hashvalue, $hashvalue_0_6]
                   │   Outputs: []
                   │   Estimates: {rows: 302035 (4.61MB)}
                   │   Distribution: REPLICATED
                   ├─ Project[]
                   │  │   Outputs: [c_nationkey:integer, $hashvalue:bigint]
                   │  │   Estimates: {rows: 1500000 (5.72MB)}
                   │  │   $hashvalue := `combine_hash`(BIGINT '0', COALESCE(`$operator$hash_code`(`c_nationkey`), 0))
                   │  └─ RuntimeFilter
                   │     │   Outputs: [c_nationkey:integer]
                   │     │   Estimates: {rows: 1500000 (5.72MB)}
                   │     ├─ TableScan[adb:AdbTableHandle{schema=tpch, tableName=customer, partitionColumnHandles=[c_custkey]}]
                   │     │      Outputs: [c_nationkey:integer]
                   │     │      Estimates: {rows: 1500000 (5.72MB)}
                   │     │      c_nationkey := AdbColumnHandle{columnName=c_nationkey, type=4, isIndexed=true}
                   │     └─ RuntimeCollect
                   │        │   Outputs: [n_nationkey:integer]
                   │        │   Estimates: {rows: 5 (60B)}
                   │        └─ LocalExchange[ROUND_ROBIN] ()
                   │           │   Outputs: [n_nationkey:integer]
                   │           │   Estimates: {rows: 5 (60B)}
                   │           └─ RuntimeScan
                   │                  Outputs: [n_nationkey:integer]
                   │                  Estimates: {rows: 5 (60B)}
                   └─ LocalExchange[HASH][$hashvalue_0_6] ("n_nationkey")
                      │   Outputs: [n_nationkey:integer, $hashvalue_0_6:bigint]
                      │   Estimates: {rows: 5 (60B)}
                      └─ Project[]
                         │   Outputs: [n_nationkey:integer, $hashvalue_0_10:bigint]
                         │   Estimates: {rows: 5 (60B)}
                         │   $hashvalue_10 := `combine_hash`(BIGINT '0', COALESCE(`$operator$hash_code`(`n_nationkey`), 0))
                         └─ RemoteExchange[REPLICATE]
                            │   Outputs: [n_nationkey:integer]
                            │   Estimates: {rows: 5 (60B)}
                            └─ InnerJoin[(`n_regionkey` = `r_regionkey`)][$hashvalue_0_7, $hashvalue_0_8]
                               │   Outputs: [n_nationkey:integer]
                               │   Estimates: {rows: 5 (60B)}
                               │   Distribution: REPLICATED
                               ├─ Project[]
                               │  │   Outputs: [n_nationkey:integer, n_regionkey:integer, $hashvalue_0_7:bigint]
                               │  │   Estimates: {rows: 25 (200B)}
                               │  │   $hashvalue_7 := `combine_hash`(BIGINT '0', COALESCE(`$operator$hash_code`(`n_regionkey`), 0))
                               │  └─ RuntimeFilter
                               │     │   Outputs: [n_nationkey:integer, n_regionkey:integer]
                               │     │   Estimates: {rows: 25 (200B)}
                               │     ├─ TableScan[adb:AdbTableHandle{schema=tpch, tableName=nation, partitionColumnHandles=[]}]
                               │     │      Outputs: [n_nationkey:integer, n_regionkey:integer]
                               │     │      Estimates: {rows: 25 (200B)}
                               │     │      n_nationkey := AdbColumnHandle{columnName=n_nationkey, type=4, isIndexed=true}
                               │     │      n_regionkey := AdbColumnHandle{columnName=n_regionkey, type=4, isIndexed=true}
                               │     └─ RuntimeCollect
                               │        │   Outputs: [r_regionkey:integer]
                               │        │   Estimates: {rows: 1 (4B)}
                               │        └─ LocalExchange[ROUND_ROBIN] ()
                               │           │   Outputs: [r_regionkey:integer]
                               │           │   Estimates: {rows: 1 (4B)}
                               │           └─ RuntimeScan
                               │                  Outputs: [r_regionkey:integer]
                               │                  Estimates: {rows: 1 (4B)}
                               └─ LocalExchange[HASH][$hashvalue_0_8] ("r_regionkey")
                                  │   Outputs: [r_regionkey:integer, $hashvalue_0_8:bigint]
                                  │   Estimates: {rows: 1 (4B)}
                                  └─ ScanProject[table = adb:AdbTableHandle{schema=tpch, tableName=region, partitionColumnHandles=[]}]
                                         Outputs: [r_regionkey:integer, $hashvalue_0_9:bigint]
                                         Estimates: {rows: 1 (4B)}/{rows: 1 (B)}
                                         $hashvalue_9 := `combine_hash`(BIGINT '0', COALESCE(`$operator$hash_code`(`r_regionkey`), 0))
                                         r_regionkey := AdbColumnHandle{columnName=r_regionkey, type=4, isIndexed=true}
    Tabel berikut menggambarkan parameter utama dalam hasil sebelumnya.
    ParameterDeskripsi
    Outputs: [symbol:type]Kolom keluaran dan tipe data dari setiap operator.
    Estimates: {rows: %s (%sB)}Perkiraan jumlah baris dan volume data dari setiap operator. Data ini dapat digunakan untuk menentukan urutan penggabungan dan teknik pengacakan data oleh pengoptimal.

EXPLAIN ANALYZE

Anda dapat menggunakan perintah EXPLAIN ANALYZE untuk menganalisis rencana eksekusi terdistribusi dan biaya eksekusi aktual dari kueri, termasuk durasi eksekusi, penggunaan memori, serta volume data masukan dan keluaran.

  • Sintaksis
    EXPLAIN ANALYZE <SELECT statement>;
  • Contoh
    EXPLAIN ANALYZE
    SELECT count(*)
          FROM
          nation, region, customer
          WHERE
          c_nationkey = n_nationkey
          AND n_regionkey = r_regionkey
          AND r_name = 'ASIA';
    Hasil berikut dikembalikan:
    Fragment 1 [SINGLE]
        Output: 1 row (9B), PeakMemory: 178KB, WallTime: 1.00ns, Input: 32 rows (288B); per task: avg.: 32.00 std.dev.: 0.00
        Output layout: [count]
        Output partitioning: SINGLE []
        Aggregate(FINAL)
        │   Outputs: [count:bigint]
        │   Estimates: {rows: 1 (8B)}
        │   Output: 2 rows (18B), PeakMemory: 24B (0.00%), WallTime: 70.39us (0.03%)
        │   count := count(`count_1`)
        └─ LocalExchange[SINGLE] ()
           │   Outputs: [count1:bigint]
           │   Estimates: {rows: ? (?)}
           │   Output: 64 rows (576B), PeakMemory: 8KB (0.07%), WallTime: 238.69us (0.10%)
           └─ RemoteSource[2]
                  Outputs: [count2:bigint]
                  Estimates:
                  Output: 32 rows (288B), PeakMemory: 32KB (0.27%), WallTime: 182.82us (0.08%)
                  Input avg.: 4.00 rows, Input std.dev.: 264.58%
    
    Fragment 2 [adb:AdbPartitioningHandle{schema=tpch, tableName=customer, dimTable=false, shards=32, tableEngineType=Cstore, partitionColumns=c_custkey, prunedBuckets= empty}]
        Output: 32 rows (288B), PeakMemory: 6MB, WallTime: 164.00ns, Input: 1500015 rows (20.03MB); per task: avg.: 500005.00 std.dev.: 21941.36
        Output layout: [count4]
        Output partitioning: SINGLE []
        Aggregate(PARTIAL)
        │   Outputs: [count4:bigint]
        │   Estimates: {rows: 1 (8B)}
        │   Output: 64 rows (576B), PeakMemory: 336B (0.00%), WallTime: 1.01ms (0.42%)
        │   count_4 := count(*)
        └─ INNER Join[(`c_nationkey` = `n_nationkey`)][$hashvalue, $hashvalue6]
           │   Outputs: []
           │   Estimates: {rows: 302035 (4.61MB)}
           │   Output: 300285 rows (210B), PeakMemory: 641KB (5.29%), WallTime: 99.08ms (41.45%)
           │   Left (probe) Input avg.: 46875.00 rows, Input std.dev.: 311.24%
           │   Right (build) Input avg.: 0.63 rows, Input std.dev.: 264.58%
           │   Distribution: REPLICATED
           ├─ ScanProject[table = adb:AdbTableHandle{schema=tpch, tableName=customer, partitionColumnHandles=[c_custkey]}]
           │      Outputs: [c_nationkey:integer, $hashvalue:bigint]
           │      Estimates: {rows: 1500000 (5.72MB)}/{rows: 1500000 (5.72MB)}
           │      Output: 1500000 rows (20.03MB), PeakMemory: 5MB (44.38%), WallTime: 68.29ms (28.57%)
           │      $hashvalue := `combine_hash`(BIGINT '0', COALESCE(`$operator$hash_code`(`c_nationkey`), 0))
           │      c_nationkey := AdbColumnHandle{columnName=c_nationkey, type=4, isIndexed=true}
           │      Input: 1500000 rows (7.15MB), Filtered: 0.00%
           └─ LocalExchange[HASH][$hashvalue6] ("n_nationkey")
              │   Outputs: [n_nationkey:integer, $hashvalue6:bigint]
              │   Estimates: {rows: 5 (60B)}
              │   Output: 30 rows (420B), PeakMemory: 394KB (3.26%), WallTime: 455.03us (0.19%)
              └─ Project[]
                 │   Outputs: [n_nationkey:integer, $hashvalue10:bigint]
                 │   Estimates: {rows: 5 (60B)}
                 │   Output: 15 rows (210B), PeakMemory: 24KB (0.20%), WallTime: 83.61us (0.03%)
                 │   Input avg.: 0.63 rows, Input std.dev.: 264.58%
                 │   $hashvalue_10 := `combine_hash`(BIGINT '0', COALESCE(`$operator$hash_code`(`n_nationkey`), 0))
                 └─ RemoteSource[3]
                        Outputs: [n_nationkey:integer]
                        Estimates:
                        Output: 15 rows (75B), PeakMemory: 24KB (0.20%), WallTime: 45.97us (0.02%)
                        Input avg.: 0.63 rows, Input std.dev.: 264.58%
    
    Fragment 3 [adb:AdbPartitioningHandle{schema=tpch, tableName=nation, dimTable=true, shards=32, tableEngineType=Cstore, partitionColumns=, prunedBuckets= empty}]
        Output: 5 rows (25B), PeakMemory: 185KB, WallTime: 1.00ns, Input: 26 rows (489B); per task: avg.: 26.00 std.dev.: 0.00
        Output layout: [n_nationkey]
        Output partitioning: BROADCAST []
        INNER Join[(`n_regionkey` = `r_regionkey`)][$hashvalue7, $hashvalue8]
        │   Outputs: [n_nationkey:integer]
        │   Estimates: {rows: 5 (60B)}
        │   Output: 11 rows (64B), PeakMemory: 152KB (1.26%), WallTime: 255.86us (0.11%)
        │   Left (probe) Input avg.: 25.00 rows, Input std.dev.: 0.00%
        │   Right (build) Input avg.: 0.13 rows, Input std.dev.: 264.58%
        │   Distribution: REPLICATED
        ├─ ScanProject[table = adb:AdbTableHandle{schema=tpch, tableName=nation, partitionColumnHandles=[]}]
        │      Outputs: [n_nationkey:integer, n_regionkey:integer, $hashvalue7:bigint]
        │      Estimates: {rows: 25 (200B)}/{rows: 25 (200B)}
        │      Output: 25 rows (475B), PeakMemory: 16KB (0.13%), WallTime: 178.81us (0.07%)
        │      $hashvalue_7 := `combine_hash`(BIGINT '0', COALESCE(`$operator$hash_code`(`n_regionkey`), 0))
        │      n_nationkey := AdbColumnHandle{columnName=n_nationkey, type=4, isIndexed=true}
        │      n_regionkey := AdbColumnHandle{columnName=n_regionkey, type=4, isIndexed=true}
        │      Input: 25 rows (250B), Filtered: 0.00%
        └─ LocalExchange[HASH][$hashvalue8] ("r_regionkey")
           │   Outputs: [r_regionkey:integer, $hashvalue8:bigint]
           │   Estimates: {rows: 1 (4B)}
           │   Output: 2 rows (28B), PeakMemory: 34KB (0.29%), WallTime: 57.41us (0.02%)
           └─ ScanProject[table = adb:AdbTableHandle{schema=tpch, tableName=region, partitionColumnHandles=[]}]
                  Outputs: [r_regionkey:integer, $hashvalue9:bigint]
                  Estimates: {rows: 1 (4B)}/{rows: 1 (4B)}
                  Output: 1 row (14B), PeakMemory: 8KB (0.07%), WallTime: 308.99us (0.13%)
                  $hashvalue_9 := `combine_hash`(BIGINT '0', COALESCE(`$operator$hash_code`(`r_regionkey`), 0))
                  r_regionkey := AdbColumnHandle{columnName=r_regionkey, type=4, isIndexed=true}
                  Input: 1 row (5B), Filtered: 0.00%
    Tabel berikut menggambarkan parameter utama dalam hasil sebelumnya.
    ParameterDeskripsi
    Outputs: [symbol:type]Kolom keluaran dan tipe data dari setiap operator.
    Estimates: {rows: %s (%sB)}Perkiraan jumlah baris dan volume data dari setiap operator. Data ini dapat digunakan untuk menentukan urutan penggabungan dan teknik pengacakan data oleh pengoptimal.
    PeakMemory: %sTotal penggunaan memori. Parameter ini digunakan untuk menganalisis penyebab hambatan yang terjadi selama penggunaan memori.
    WallTime: %sTotal durasi eksekusi operator. Parameter ini digunakan untuk menganalisis penyebab hambatan yang terjadi selama operasi komputasi.
    Catatan Durasi ini bukan durasi eksekusi aktual karena komputasi paralel.
    Input: %s rows (%sB)Jumlah baris masukan dan volume datanya.
    per task: avg.: %s std.dev.: %sRata-rata jumlah baris dan deviasi standarnya. Parameter ini digunakan untuk menganalisis kemiringan data yang ada di suatu tahap.
    Output: %s row (%sB)Jumlah baris keluaran dan volume datanya.

Skenario

Anda dapat menggunakan perintah EXPLAIN ANALYZE untuk menganalisis masalah umum yang terkait dengan rencana eksekusi.
  • Filter tidak didorong ke bawah.
    SQL 1 dan SQL 2 pada bagian berikut menunjukkan dua kueri SQL. Dibandingkan dengan SQL 1, SQL 2 berisi fungsi length(string_test) yang tidak dapat didorong ke bawah. Saat SQL 2 dieksekusi, data lengkap dipindai.
    • SQL 1
      SELECT count(*) FROM test WHERE string_test = 'a';
    • SQL 2
      SELECT count(*) FROM test WHERE length(string_test) = 1;
    Anda dapat menggunakan perintah EXPLAIN ANALYZE untuk menganalisis rencana eksekusi dari dua kueri SQL tersebut. Bagian berikut membandingkan Fragment 2 dalam dua rencana eksekusi:
    • SQL 1 menggunakan operator TableScan dan parameter Input avg. disetel ke 0.00 rows. Ini menunjukkan bahwa filter didorong ke bawah dan jumlah baris yang dipindai adalah nol.
      Fragment 2 [adb:AdbPartitioningHandle{schema=test4dmp, tableName=test, dimTable=false, shards=4, tableEngineType=Cstore, partitionColumns=id, prunedBuckets= empty}]
          Output: 4 rows (36B), PeakMemory: 0B, WallTime: 6.00ns, Input: 0 rows (0B); per task: avg.: 0.00 std.dev.: 0.00
          Output layout: [count_0_1]
          Output partitioning: SINGLE []
          Aggregate(PARTIAL)
          │   Outputs: [count_0_1:bigint]
          │   Estimates: {rows: 1 (8B)}
          │   Output: 8 rows (72B), PeakMemory: 0B (0.00%), WallTime: 212.92us (3.99%)
          │   count_0_1 := count(*)
          └─ TableScan[adb:AdbTableHandle{schema=test4dmp, tableName=test, partitionColumnHandles=[id]}]
                 Outputs: []
                 Estimates: {rows: 4 (0B)}
                 Output: 0 rows (0B), PeakMemory: 0B (0.00%), WallTime: 4.76ms (89.12%)
                 Input avg.: 0.00 rows, Input std.dev.: ?%
    • SQL 2 menggunakan operator ScanFilterProject dan parameter Input disetel ke 9999 rows. Selain itu, properti filterPredicate disetel ke (`test4dmp`.`length`(`string_test`) = BIGINT '1'). Ini menunjukkan bahwa filter tidak didorong ke bawah dan jumlah baris yang dipindai adalah 9999.
      Fragment 2 [adb:AdbPartitioningHandle{schema=test4dmp, tableName=test, dimTable=false, shards=4, tableEngineType=Cstore, partitionColumns=id, prunedBuckets= empty}]
          Output: 4 rows (36B), PeakMemory: 0B, WallTime: 102.00ns, Input: 0 rows (0B); per task: avg.: 0.00 std.dev.: 0.00
          Output layout: [count_0_1]
          Output partitioning: SINGLE []
          Aggregate(PARTIAL)
          │   Outputs: [count_0_1:bigint]
          │   Estimates: {rows: 1 (8B)}
          │   Output: 8 rows (72B), PeakMemory: 0B (0.00%), WallTime: 252.23us (0.12%)
          │   count_0_1 := count(*)
          └─ ScanFilterProject[table = adb:AdbTableHandle{schema=test4dmp, tableName=test, partitionColumnHandles=[id]}, filterPredicate = (`test4dmp`.`length`(`string_test`) = BIGINT '1')]
                 Outputs: []
                 Estimates: {rows: 9999 (312.47kB)}/{rows: 9999 (312.47kB)}/{rows: ? (?)}
                 Output: 0 rows (0B), PeakMemory: 0B (0.00%), WallTime: 101.31ms (49.84%)
                 string_test := AdbColumnHandle{columnName=string_test, type=13, isIndexed=true}
                 Input: 9999 rows (110.32kB), Filtered: 100.00%
  • Penggunaan Memori SQL Buruk

    Anda dapat memeriksa total penggunaan memori setiap fragmen untuk menganalisis masalah konsumsi sumber daya menggunakan parameter PeakMemory. Siaran bencana dapat menyebabkan total penggunaan memori tinggi. Kecuali dalam skenario ini, nilai besar untuk parameter PeakMemory biasanya disebabkan oleh pembengkakan data yang digabungkan, volume data besar di tabel yang digabungkan di sisi kiri, atau volume data besar yang dipindai oleh operator TableScan. Anda harus membatasi nilai-nilai ini dengan menambahkan kondisi berdasarkan kebutuhan bisnis. Anda juga dapat memeriksa total penggunaan memori setiap operator untuk mengidentifikasi operator yang paling banyak menggunakan sumber daya menggunakan parameter PeakMemory.