PostgreSQL bana tam olarak neyi anlatıyor?


116

MySQL'in açıklama çıktısı oldukça basittir. PostgreSQL'ler biraz daha karmaşıktır. Ben de bunu açıklayan iyi bir kaynak bulamadım.

Tam olarak neyin söylendiğini tarif edebilir misin veya en azından beni iyi bir kaynak yönünde gösterebilir misin?

Yanıtlar:


50

Explaining_EXPLAIN.pdf de yardımcı olabilir.


65
İnsanların neden slayt destelerinin iyi teknik dokümantasyon oluşturduğunu düşündüklerine şaşırdım. Konuşmanın bir videosu yardımcı olabilir, ancak bu slayt destesinin bilgi yoğunluğu sıfıra çok yakındır. İlk altı slaytta (toplamın 1 / 5'i), tam olarak 1 teknik içerik cümlesi vardır: "• EXPLAIN yalnızca SELECT (yani GÜNCELLEME, SİLME ve EKLEME) değil herhangi bir DML üzerinde çalışır". En büyük yanlış anlamam, "başlangıç" zamanının ne anlama geldiğidir ve bu, bu ~ 30 slaytta hiçbir yerde açıklanmamıştır.
Mark E. Haase

80

Her zaman kafa karıştırıcı bulduğum kısım, başlangıç ​​maliyeti ile toplam maliyettir. Bunu her unuttuğumda Google'da aradım, bu da beni buraya getiriyor, bu farkı açıklamıyor, bu yüzden bu cevabı yazıyorum. Bu benim panoda da budur Postgres EXPLAINbelgelerinde , Anladığım kadarıyla açıkladı.

İşte bir forumu yöneten bir uygulamadan bir örnek:

EXPLAIN SELECT * FROM post LIMIT 50;

Limit  (cost=0.00..3.39 rows=50 width=422)
  ->  Seq Scan on post  (cost=0.00..15629.12 rows=230412 width=422)

İşte PgAdmin'in grafik açıklaması:

ilk sorgunun grafik açıklaması

(PgAdmin'i kullanırken, maliyet ayrıntılarını okumak için farenizi bir bileşenin üzerine getirebilirsiniz.)

Ekonomik maliyeti, örneğin bir demet olarak temsil edilir LIMITolan cost=0.00..3.39ve sırayla tarama maliyeti postolan cost=0.00..15629.12. Demetteki ilk sayı başlangıç ​​maliyetidir ve ikinci sayı toplam maliyettir . Kullandığım EXPLAINve kullanmadığım için EXPLAIN ANALYZE, bu maliyetler gerçek ölçüler değil tahminlerdir.

  • Başlangıç ​​maliyeti zor bir kavramdır. Sadece o bileşenin başlamasından önceki süreyi temsil etmez . Bileşenin çalıştırılmaya başlaması (verilerde okuma) ile bileşenin ilk satırını çıktısı aldığı zaman arasındaki süreyi temsil eder .
  • Toplam maliyet , bileşenin verileri okumaya başladığı andan çıktısını yazmayı bitirdiği ana kadar tüm yürütme süresidir.

Bir karmaşıklık olarak, her "ana" düğümün maliyeti, alt düğümlerinin maliyetlerini içerir. Metin temsilinde, ağaç girintiyle temsil edilir, örneğin LIMITbir ana düğümdür ve Seq Scanonun alt öğesidir. PgAdmin gösteriminde, oklar çocuktan ebeveyne işaret eder - veri akışının yönü - bu, grafik teorisine aşina iseniz mantıksız olabilir.

Belgeler, maliyetlerin tüm alt düğümleri kapsadığını söylüyor, ancak ebeveynin toplam maliyetinin, alt düğümün toplam maliyetinden 3.39çok daha düşük olduğuna dikkat edin 15629.12. Toplam maliyet kapsamlı değildir çünkü gibi bir bileşenin LIMITtüm girdisini işlemesi gerekmez. Postgres belgelerindekiEXPLAIN SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000 LIMIT 2; örneğe bakın .EXPLAIN

Yukarıdaki örnekte, başlangıç ​​zamanı her iki bileşen için de sıfırdır, çünkü hiçbir bileşenin satır yazmaya başlamadan önce herhangi bir işlem yapması gerekmez: sıralı bir tarama, tablonun ilk satırını okur ve yayar. LIMITOnun ilk satırı okur ve sonra yayar.

Bir bileşenin herhangi bir satır çıktısını almaya başlayabilmesi için ne zaman çok fazla işlem yapması gerekir? Pek çok olası neden var, ancak net bir örneğe bakalım. İşte öncekinden aynı sorgu, ancak şimdi bir ORDER BYcümle içeriyor :

EXPLAIN SELECT * FROM post ORDER BY body LIMIT 50;

Limit  (cost=23283.24..23283.37 rows=50 width=422)
  ->  Sort  (cost=23283.24..23859.27 rows=230412 width=422)
        Sort Key: body
        ->  Seq Scan on post  (cost=0.00..15629.12 rows=230412 width=422)

Ve grafiksel olarak:

ikinci sorgunun grafik açıklaması

Bir kez daha, sıralı taramanın postbaşlangıç ​​maliyeti yoktur: hemen satırları çıkarmaya başlar. Ancak sıralamanın önemli bir başlangıç ​​maliyeti vardır 23283.24çünkü tek bir satır bile çıktı verebilmesi için tüm tabloyu sıralamak zorundadır . Sıralamanın toplam maliyeti 23859.27, başlangıç ​​maliyetinden yalnızca biraz daha yüksektir, bu da tüm veri kümesi sıralandıktan sonra sıralanan verilerin çok hızlı bir şekilde yayınlanabileceği gerçeğini yansıtır.

Uyarı başlangıç zamanı o LIMIT 23283.24tür başlatma zaman tam olarak eşittir. Bunun nedeni LIMIT, başlangıç ​​süresinin yüksek olması değildir . Aslında kendi başına sıfır başlangıç ​​süresine sahiptir, ancak EXPLAINher ebeveyn için tüm alt maliyetleri toplar, bu nedenle LIMITbaşlangıç ​​süresi, çocuklarının toplam başlangıç ​​sürelerini içerir.

Bu maliyet toplamı, her bir bileşenin yürütme maliyetini anlamayı zorlaştırabilir. Örneğin, LIMITbaşlangıç ​​zamanımız sıfır, ancak bu ilk bakışta açık değil. Bu nedenle, Hubert Lubaczewski (diğer adıyla depesz) tarafından yaratılan ve diğer şeylerin yanı sıra çocuk maliyetlerini ebeveyn maliyetlerinden çıkararak anlamaya yardımcı olan bir araç olan açıklama.depesz.com ile bağlantılı birkaç kişi daha EXPLAIN. Aracıyla ilgili kısa bir blog yazısında diğer bazı karmaşıklıklardan bahsediyor .


4
Bunun için teşekkür ederim. Ayrıca, çıktıyı (imo) görüntülemede daha da iyi bir iş çıkaran bir açıklama görselleştirici eklemek istiyorum. tatiyants.com/pev
Jonathan Porter

Mükemmel cevap. Ve başlangıç ​​maliyetinin ilk satıra kadar geçen süreyi içerdiğine dair yorumunuz , Sıralama için başlangıç ​​maliyetinin neden sadece 15629.12 olmadığını anlamama yardımcı oldu.
Joel Wigton

43

En çok girintili ile en az girintili arasında çalışır ve planın en altından en üste doğru inanıyorum. (Dolayısıyla, iki girintili bölüm varsa, sayfanın daha aşağısındaki biri önce çalıştırır, sonra diğeriyle karşılaştıklarında onları birleştiren kural yürütülür.)

Buradaki fikir, her adımda gelen ve bir kural tarafından işlenen 1 veya 2 veri kümesi olmasıdır. Yalnızca bir veri kümesi varsa, bu işlem o veri kümesine yapılır. (Örneğin, hangi satırları istediğinizi bulmak, bir veri kümesini filtrelemek veya sıralamak için bir dizini tarayın.) Eğer iki ise, iki veri kümesi daha fazla girintili olan iki şeydir ve gördüğünüz kuralla birleştirilirler. Kuralların çoğunun anlamı makul ölçüde kolayca tahmin edilebilir (özellikle daha önce bir dizi açıklama planı okuduysanız), ancak tek tek öğeleri belgelere bakarak veya (daha kolay) yalnızca ifadeyi atarak doğrulamayı deneyebilirsiniz. Google gibi birkaç anahtar kelime ile birlikte EXPLAIN.

Açıkçası bu tam bir açıklama değil, ancak genellikle ne istersen bulman için yeterli bağlam sağlıyor. Örneğin bu planı gerçek bir veritabanından düşünün:

explain analyze
select a.attributeid, a.attributevalue, b.productid
from orderitemattribute a, orderitem b
where a.orderid = b.orderid
and a.attributeid = 'display-album'
and b.productid = 'ModernBook';

------------------------------------------------------------------------------------------------------------------------------------------------------------

 Merge Join  (cost=125379.14..125775.12 rows=3311 width=29) (actual time=841.478..841.478 rows=0 loops=1)
   Merge Cond: (a.orderid = b.orderid)
   ->  Sort  (cost=109737.32..109881.89 rows=57828 width=23) (actual time=736.163..774.475 rows=16815 loops=1)
         Sort Key: a.orderid
         Sort Method:  quicksort  Memory: 1695kB
         ->  Bitmap Heap Scan on orderitemattribute a  (cost=1286.88..105163.27 rows=57828 width=23) (actual time=41.536..612.731 rows=16815 loops=1)
               Recheck Cond: ((attributeid)::text = 'display-album'::text)
               ->  Bitmap Index Scan on (cost=0.00..1272.43 rows=57828 width=0) (actual time=25.033..25.033 rows=16815 loops=1)
                     Index Cond: ((attributeid)::text = 'display-album'::text)
   ->  Sort  (cost=15641.81..15678.73 rows=14769 width=14) (actual time=14.471..16.898 rows=1109 loops=1)
         Sort Key: b.orderid
         Sort Method:  quicksort  Memory: 76kB
         ->  Bitmap Heap Scan on orderitem b  (cost=310.96..14619.03 rows=14769 width=14) (actual time=1.865..8.480 rows=1114 loops=1)
               Recheck Cond: ((productid)::text = 'ModernBook'::text)
               ->  Bitmap Index Scan on id_orderitem_productid  (cost=0.00..307.27 rows=14769 width=0) (actual time=1.431..1.431 rows=1114 loops=1)
                     Index Cond: ((productid)::text = 'ModernBook'::text)
 Total runtime: 842.134 ms
(17 rows)

Kendiniz için okumayı deneyin ve mantıklı olup olmadığına bakın.

Okuduğum şey, veritabanının önce id_orderitem_productidindeksi taraması, istediği satırları bulmak için bunu orderitemkullanarak, daha sonra bir hızlı sıralama kullanarak bu veri kümesini sıralaması (veriler RAM'e sığmazsa kullanılan sıralama değişecektir) ve ardından bunu bir kenara koymasıdır.

Daha sonra, orditematt_attributeid_idxistediği satırları bulmak için tarar orderitemattributeve ardından bir hızlı sıralama kullanarak bu veri kümesini sıralar.

Daha sonra iki veri kümesini alır ve bunları birleştirir. (Birleştirme birleştirme, sıralı iki veri kümesini paralel olarak yürüterek eşleştiklerinde birleştirilmiş satırı yayan bir tür "sıkıştırma" işlemidir.)

Dediğim gibi, planın iç kısmından dış kısmına, aşağıdan yukarıya doğru çalışıyorsunuz.



13

PgAdmin size açıklama planının grafiksel bir sunumunu gösterecektir. İkisi arasında gidip gelmek, metin temsilinin ne anlama geldiğini anlamanıza gerçekten yardımcı olabilir. Bununla birlikte, sadece ne yapacağını bilmek istiyorsanız, her zaman GUI'yi kullanabilirsiniz.



0

Pgadmin'i kurarsanız, metin çıktısının ne olup bittiğine dair diyagramlar çizmesinin yanı sıra neler olduğunu görmek için gerçekten yararlı bulduğum filtreleri, sıraları ve alt küme birleştirmelerini gösteren bir Açıkla düğmesi vardır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.