Apa yang EXPLAIN adalah senyap dan bagaimana untuk membuatnya bercakap

Soalan klasik yang dibawa oleh pembangun kepada DBA atau pemilik perniagaannya kepada perunding PostgreSQL hampir selalu berbunyi sama: "Mengapakah permintaan mengambil masa yang lama untuk disiapkan pada pangkalan data?"

Set sebab tradisional:

  • algoritma yang tidak cekap
    apabila anda memutuskan untuk MENYERTAI beberapa CTE dalam beberapa puluh ribu rekod
  • statistik lapuk
    jika taburan sebenar data dalam jadual sudah sangat berbeza daripada yang dikumpul oleh ANALYZE kali terakhir
  • "palam" pada sumber
    dan tiada lagi kuasa pengkomputeran khusus CPU yang mencukupi, memori gigabait sentiasa dipam, atau cakera tidak dapat bersaing dengan semua "kehendak" pangkalan data
  • menyekat daripada proses bersaing

Dan jika penyekatan agak sukar untuk ditangkap dan dianalisis, maka untuk semua perkara lain yang kami perlukan pelan pertanyaan, yang boleh diperolehi menggunakan JELAS operator (Sudah tentu, lebih baik untuk MENJELASKAN (ANALYZE, BUFFERS) dengan segera ...) atau modul auto_explain.

Tetapi, seperti yang dinyatakan dalam dokumentasi yang sama,

"Memahami rancangan adalah satu seni, dan untuk menguasainya memerlukan pengalaman tertentu..."

Tetapi anda boleh melakukannya tanpanya jika anda menggunakan alat yang betul!

Apakah rupa rancangan pertanyaan biasanya? Sesuatu seperti itu:

Index Scan using pg_class_relname_nsp_index on pg_class (actual time=0.049..0.050 rows=1 loops=1)
  Index Cond: (relname = $1)
  Filter: (oid = $0)
  Buffers: shared hit=4
  InitPlan 1 (returns $0,$1)
    ->  Limit (actual time=0.019..0.020 rows=1 loops=1)
          Buffers: shared hit=1
          ->  Seq Scan on pg_class pg_class_1 (actual time=0.015..0.015 rows=1 loops=1)
                Filter: (relkind = 'r'::"char")
                Rows Removed by Filter: 5
                Buffers: shared hit=1

atau seperti ini:

"Append  (cost=868.60..878.95 rows=2 width=233) (actual time=0.024..0.144 rows=2 loops=1)"
"  Buffers: shared hit=3"
"  CTE cl"
"    ->  Seq Scan on pg_class  (cost=0.00..868.60 rows=9972 width=537) (actual time=0.016..0.042 rows=101 loops=1)"
"          Buffers: shared hit=3"
"  ->  Limit  (cost=0.00..0.10 rows=1 width=233) (actual time=0.023..0.024 rows=1 loops=1)"
"        Buffers: shared hit=1"
"        ->  CTE Scan on cl  (cost=0.00..997.20 rows=9972 width=233) (actual time=0.021..0.021 rows=1 loops=1)"
"              Buffers: shared hit=1"
"  ->  Limit  (cost=10.00..10.10 rows=1 width=233) (actual time=0.117..0.118 rows=1 loops=1)"
"        Buffers: shared hit=2"
"        ->  CTE Scan on cl cl_1  (cost=0.00..997.20 rows=9972 width=233) (actual time=0.001..0.104 rows=101 loops=1)"
"              Buffers: shared hit=2"
"Planning Time: 0.634 ms"
"Execution Time: 0.248 ms"

Tetapi membaca pelan dalam teks "dari helaian" adalah sangat sukar dan tidak jelas:

  • dipaparkan dalam nod jumlah dengan sumber subpokok
    iaitu, untuk memahami berapa lama masa yang diambil untuk melaksanakan nod tertentu, atau berapa banyak bacaan dari jadual ini membawa data dari cakera, anda perlu menolak satu daripada yang lain.
  • masa nod diperlukan darab dengan gelung
    ya, penolakan bukanlah operasi yang paling kompleks yang mesti dilakukan "di kepala" - selepas semua, masa pelaksanaan ditunjukkan sebagai purata untuk satu pelaksanaan nod, dan mungkin terdapat ratusan daripadanya
  • baik, dan semua ini bersama-sama menghalang kita daripada menjawab soalan utama - jadi siapa "pautan paling lemah"?

Apabila kami cuba menerangkan semua ini kepada beberapa ratus pembangun kami, kami menyedari bahawa dari luar ia kelihatan seperti ini:

Apa yang EXPLAIN adalah senyap dan bagaimana untuk membuatnya bercakap

Dan itu bermakna kita perlu...

Alat

Di dalamnya kami cuba mengumpul semua mekanik utama yang membantu memahami "siapa yang harus dipersalahkan dan apa yang perlu dilakukan" mengikut rancangan dan permintaan. Baiklah, dan kongsi sebahagian daripada pengalaman anda dengan komuniti.
Temui dan gunakan - explain.tensor.ru

Keterlihatan rancangan

Adakah mudah untuk memahami rancangan itu apabila ia kelihatan seperti ini?

Seq Scan on pg_class (actual time=0.009..1.304 rows=6609 loops=1)
  Buffers: shared hit=263
Planning Time: 0.108 ms
Execution Time: 1.800 ms

Tidak betul.

Tetapi seperti ini, dalam bentuk ringkasanapabila penunjuk utama dipisahkan, ia lebih jelas:

Apa yang EXPLAIN adalah senyap dan bagaimana untuk membuatnya bercakap

Tetapi jika rancangan itu lebih rumit, dia akan datang untuk menyelamatkan taburan masa piechart oleh nod:

Apa yang EXPLAIN adalah senyap dan bagaimana untuk membuatnya bercakap

Nah, untuk pilihan yang paling sukar dia tergesa-gesa untuk membantu carta kemajuan:

Apa yang EXPLAIN adalah senyap dan bagaimana untuk membuatnya bercakap

Sebagai contoh, terdapat situasi yang agak tidak remeh apabila rancangan mungkin mempunyai lebih daripada satu punca sebenar:

Apa yang EXPLAIN adalah senyap dan bagaimana untuk membuatnya bercakapApa yang EXPLAIN adalah senyap dan bagaimana untuk membuatnya bercakap

Petunjuk struktur

Nah, jika keseluruhan struktur pelan dan bintik-bintik sakitnya sudah dibentangkan dan kelihatan, mengapa tidak menyerlahkannya kepada pembangun dan menerangkannya dalam "bahasa Rusia"?

Apa yang EXPLAIN adalah senyap dan bagaimana untuk membuatnya bercakapKami telah mengumpulkan beberapa dozen templat pengesyoran sedemikian.

Pemprofil pertanyaan baris demi baris

Sekarang, jika anda meletakkan pertanyaan asal pada pelan yang dianalisis, anda boleh melihat berapa banyak masa yang dibelanjakan untuk setiap pernyataan individu - seperti ini:

Apa yang EXPLAIN adalah senyap dan bagaimana untuk membuatnya bercakap

...atau pun seperti ini:

Apa yang EXPLAIN adalah senyap dan bagaimana untuk membuatnya bercakap

Menggantikan parameter ke dalam permintaan

Jika anda "melampirkan" bukan sahaja permintaan kepada pelan, tetapi juga parameternya dari baris DETAIL log, anda juga boleh menyalinnya dalam salah satu pilihan:

  • dengan penggantian nilai dalam permintaan
    untuk pelaksanaan langsung di pangkalan anda dan pemprofilan selanjutnya

    SELECT 'const', 'param'::text;
  • dengan penggantian nilai melalui PREPARE/EXECUTE
    untuk meniru kerja penjadual, apabila bahagian parametrik boleh diabaikan - sebagai contoh, apabila bekerja pada jadual partition

    DEALLOCATE ALL;
    PREPARE q(text) AS SELECT 'const', $1::text;
    EXECUTE q('param'::text);
    

Arkib rancangan

Tampal, analisis, kongsi dengan rakan sekerja! Pelan akan kekal diarkibkan dan anda boleh kembali kepadanya kemudian: explain.tensor.ru/archive

Tetapi jika anda tidak mahu orang lain melihat rancangan anda, jangan lupa tandai kotak "jangan terbitkan dalam arkib".

Dalam artikel berikut saya akan bercakap tentang kesukaran dan keputusan yang timbul semasa menganalisis rancangan.

Sumber: www.habr.com

Tambah komen