SQLProgramlamaKıdemli Veritabanı Mühendisi

Sorgu optimizasyon aşamasında, **PostgreSQL** planlayıcısının, **Gather Merge** düğümünün, paralel sonuç konsolidasyonu için **Gather** düğümünden daha iyi olduğunu belirlediği kesin eşik nedir ve bu seçimi belirleyen altında yatan tarayıcı düğümlerinin hangi spesifik özelliğidir?

Hintsage yapay zeka asistanı ile mülakatları geçin

Sorunun Cevabı

PostgreSQL 9.6'da paralel sorgu yeteneklerinin tanıtılması, arka plan işçileri tarafından elde edilen sonuçları lider işleme birleştirmek için Gather düğümünü getirdi. Ancak, standart Gather düğümü, paralel işçiler tarafından üretilen herhangi bir tüp sıralamasını yok eder, bu da diziyi yeniden oluşturmak için liderde pahalı bir son Sırala adımını gerektirir. Doğası gereği sıralı veri akışlarını işlerken bu gereksizliği ortadan kaldırmak için, 10. sürüm Gather Merge düğümünü tanıttı; bu düğüm, işçilerin sıralı girdilerinin k-yönlü birleşimini gerçekleştirir, böylece lider tarafında malzeme oluşturma ve sıralama ihtiyacını atlar.

Planlayıcı, yalnızca paralel alt planın, genellikle Dizin Tarama veya tüp sırasını koruyan Birleştirme ile oluşturulan gerekli bir özelliğe göre sıralanmış çıktı garantilediğinde Gather Merge eklemeyi seçer. Alt plan, Hash Joins veya sırasız toplama gibi işlemler yoluyla sıralamayı kaybederse, Gather Merge uygun olmaktan çıkar, bu da optimizasyoncunun sıralamayı korumak için bir Gather ve ardından pahalı bir Sırala seçme ya da sıralamayı korumak amacıyla paralelliği tamamen terk etme arasında seçim yapmak zorunda kalacağı anlamına gelir.

Alt plan sıralı bir çıktı garantilediğinde, Gather Merge liderin minimum bellek tamponları kullanarak akışlı bir birleşim gerçekleştirmesine olanak tanır; bu, tüm tüpleri malzeme oluşturmak ve sıralamak yerine olur. Bellek stratejisi, liderin sıralama için tek bir büyük tahsisattan, sıralı akışların bakımını gerçekleştiren işçiler başına daha küçük tahsisatlara kayar; bu da büyük ölçekli sıralı alımlarda work_mem tükenmesi ve disk taşmalarını önemli ölçüde azaltır.

Hayattan bir Durum

Ekibimiz, saat başına bölümlenmiş bir PostgreSQL tablosunda sensör okumalarını saklayan bir zaman serisi analitiği platformunu yönetti; bu tablo 2 milyardan fazla satır içeriyordu. Kritik bir gösterge paneli, tüm bölümlerde zaman damgası azalan şekilde sıralanmış son 1000 okumanın görüntülenmesini gerektiriyordu ve gecikme bütçesi 500 milisaniyenin altındaydı. İlk tek iş parçacıklı sorgu planı bu gereksinimleri karşılayamadı ve zirve analiz yükleri sırasında kullanıcı deneyiminde bir darboğaz oluşturdu.

Tek süreç Dizin Tarama: İlk olarak, her bölümde geriye dönük bir Dizin Tarama kullanmayı ve ardından ardışık olarak yürütülen bir Sınırlama düğümü eklemeyi düşündük. Bu yaklaşım, karmaşık paralel koordinasyon olmadan uygulama basitliği ve belirlenebilir sıralama sundu. Ancak, NVMe depolama dizimizin I/O bant genişliğini doygun hale getiremiyor ve zirve yük sırasında sürekli olarak 2 saniyeyi aşıyordu; bu da gerçek zamanlı gösterge paneli güncellemeleri için kabul edilemez hale geliyordu.

Paralel Seq Tarama ile Toplama ve Sıralama: İkinci yaklaşım, max_parallel_workers_per_gather ile etkinleştirme yapmayı ve tüm satırları sona erdirmek için standart bir Toplama düğümü ile birlikte bir Paralel Seq Tarama kullanmayı içeriyordu. Bu, CPU paralelliğinden faydalandı ve tarama verimini büyük ölçüde artırdı. Ancak, lider sürecinin milyonlarca satırı sıralamak için 4 GB'den fazla work_mem tahsis etmesine neden oldu, bu da sık sık disk taşmalarına ve kısıtlı lider düğümünde OutOfMemory hatalarına yol açarak sistem kararlılığını tehlikeye attı.

Paralel Dizin Tarama ile Gather Merge: Nihayet, işçiler Zaman Damgası azalan şekilde Paralel Dizin Tarama gerçekleştirdiği, sonuçları bir Gather Merge düğümüne beslediği bir plan seçtik. İşçiler, gerekli sırada dizin yaprak sayfalarını tarayarak, lider düğüme sıralı tüpleri akıttı ve bu lider, en üstteki 1000 satırı çıkarmak için hafif bir k-yönlü birleşim gerçekleştirdi. Bu mimari, liderde nihai bir sıralama gereksinimini ortadan kaldırarak bellek baskısını dramatik şekilde azaltırken akış verimliliğini korudu.

Gather Merge yaklaşımını seçtik çünkü mevcut dizin yapısını kullanarak hem gecikme hem de bellek kısıtlarını tatmin eden tek çözüm buydu; böylece hash tabanlı işlemlerle savaşmak yerine mevcut yapıyı değerlendirmiş olduk. Bu çözüm, liderin birleşim tamponları için bellek ayak izini 64MB'nin altına düşürdü ve sürekli olarak 300ms altı cevap sürelerini elde etti. Sistem artık zirve yüklerini hafıza tükenmesi olmadan yönetebiliyor, bu sayede paralel yürütme yoluyla sıralamayı korumanın mimari seçimini doğruladı.

Adayların Sıklıkla Göz Ardı Ettiği Noktalar

Neden bir Hash Aggregate'in Gather Merge düğümünün altında yerleştirilmesi, PostgreSQL planlayıcısının planı reddetmesine veya açık bir Sıralama adımı eklemesine neden olur ve bu, GroupAggregate davranışından nasıl farklıdır?

Hash Aggregate, tüpleri gruplamak için sırasız bir hash tablosu oluşturur; bu, altında yatan tarayıcıların ürettiği herhangi bir giriş sırasını yok eder. Gather Merge, akışlı k-yönlü birleşimini gerçekleştirmek için paralel işçilerden gelen tüm sıralı girdi akışlarını gerektirdiğinden, toplama bloklarından gelen sırasız çıktı doğrudan kullanımını engeller. Tersine, GroupAggregate, önceden sıralı girdilerde çalışabilir ve, GROUP BY anahtarları sıralama düzeniyle eşleştiğinde, sıralamayı koruyabilir; bu da onu, arada bir sıralama adımı gerektirmeden Gather Merge ile uyumlu hale getirir.

Planlayıcının sekiz paralel işçiden sıralı akışları birleştirme maliyetini tahmin ettiğinde, parallel_tuple_cost GUC'si, planlayıcının Gather planından Gather Merge planına geçiş yaptığı eşiği nasıl etkiler?

parallel_tuple_cost, paralel işçilerle lider işlem arasında satırları aktarmak için ek bir tüp başına CPU yükü ekler. Gather Merge için bu maliyet, birleştirme yığınını korumak için gereken ek karşılaştırma mantığı nedeniyle standart Gather düğümünden biraz daha yüksektir. Tahmin edilen sonuç kümesi küçük olduğunda, planlayıcı, sekiz birleştirme akışının toplam yükünün, küçük bir tüp yığınının merkezde sıralanmasının maliyetini aşabileceği için liderde ucuz bir Sıralama ile birlikte bir Gather nodunu tercih edebilir.

DECLARE CURSOR kullanırken, SCROLL seçeneği ile bir Gather Merge düğümü içeren sorgu planında ne tür bir spesifik sınırlama ortaya çıkar ve birlemenin akışlı doğasına rağmen neden yürütücü sessizce tüm sonuç kümesini malzeme haline getirebilir?**

SCROLL işaretçileri, sonuç kümesi üzerinden geriye doğru hareket etme yeteneğini gerektirir, bu da, geriye alma işlemlerini desteklemek için satırların work_mem veya diske taşınmasını gerektirir. Gather Merge, verimli bir şekilde akışlı, sıralı bir çıktı üretirken, SCROLL seçeneği yürütücünün, olası geri dönüş için satırları tamponlamak üzere Gather Merge üstüne bir Malzeme düğümü eklemesini zorlar. Bu malzeme oluşturma, sonuç kümesi boyutuna orantılı bellek tüketir; bu da, akışlı bir birleşim stratejisinin bellek verimliliği avantajlarını etkili bir şekilde yok eder ve başlangıçta Gather Merge seçeneği ile kaçınılabilen disk taşmalarına neden olabilir.