Bir Java geliştiricisinin gözünden PostgreSQL'deki indekslerin sağlığı

Selam.

Adım Vanya ve ben bir Java geliştiricisiyim. Öyle oluyor ki PostgreSQL ile çok çalışıyorum; veritabanını kuruyorum, yapıyı, performansı optimize ediyorum ve hafta sonları biraz DBA oynuyorum.

Son zamanlarda mikro hizmetlerimizdeki birkaç veri tabanını düzenledim ve bir Java kütüphanesi yazdım. pg-index-sağlıkBu işi kolaylaştırıyor, bana zaman kazandırıyor ve geliştiricilerin yaptığı bazı yaygın hatalardan kaçınmama yardımcı oluyor. Bugün konuşacağımız şey bu kütüphane.

Bir Java geliştiricisinin gözünden PostgreSQL'deki indekslerin sağlığı

Feragatname

Çalıştığım PostgreSQL'in ana sürümü 10'dur. Kullandığım tüm SQL sorguları da sürüm 11'de test ediliyor. Desteklenen minimum sürüm 9.6'dır.

tarih öncesi

Her şey neredeyse bir yıl önce bana tuhaf gelen bir durumla başladı: birdenbire rekabetçi bir endeksin yaratılması bir hatayla sonuçlandı. Dizinin kendisi her zamanki gibi veritabanında geçersiz bir durumda kaldı. Günlük analizi bir eksiklik gösterdi temp_file_limit. Ve başlıyoruz... Daha derine indiğimde, veritabanı konfigürasyonunda bir sürü sorun keşfettim ve kollarımı sıvayıp, gözlerimde bir ışıltıyla bunları düzeltmeye başladım.

Birinci sorun - varsayılan yapılandırma

Muhtemelen herkes, bir kahve makinesinde çalıştırılabilen Postgres metaforundan oldukça bıkmıştır, ancak... varsayılan konfigürasyon gerçekten de birçok soruyu gündeme getiriyor. En azından dikkat etmekte fayda var bakım_iş_mem, temp_file_limit, deyim_zaman aşımı и lock_timeout.

Bizim durumumuzda bakım_iş_mem varsayılan 64 MB idi ve temp_file_limit 2 GB civarında bir şey - büyük bir tabloda dizin oluşturmak için yeterli belleğimiz yoktu.

Bu nedenle, pg-index-sağlık Bir dizi topladım anahtar, bence her veritabanı için yapılandırılması gereken parametreler.

İkinci sorun - yinelenen dizinler

Veritabanlarımız SSD sürücülerinde yaşıyor ve kullanıyoruz HA-birden fazla veri merkezi, ana ana bilgisayar ve n- kopya sayısı. Disk alanı bizim için çok değerli bir kaynaktır; performans ve CPU tüketiminden daha az önemli değildir. Dolayısıyla bir yandan hızlı okuma için indekslere ihtiyacımız var, diğer yandan da yer kapladığı ve veri güncellemeyi yavaşlattığı için gereksiz indeksleri veritabanında görmek istemiyoruz.

Ve şimdi her şeyi geri yükledikten sonra geçersiz dizinler ve yeterince gördükten sonra Oleg Bartunov'un raporları“Büyük” bir tasfiye düzenlemeye karar verdim. Geliştiricilerin veritabanı belgelerini okumayı sevmedikleri ortaya çıktı. Pek hoşlanmıyorlar. Bu nedenle, iki tipik hata ortaya çıkar: birincil anahtarda manuel olarak oluşturulan bir dizin ve benzersiz bir sütunda benzer bir "manuel" dizin. Gerçek şu ki onlara ihtiyaç yok - Postgres her şeyi kendisi yapacak. Bu tür indeksler güvenli bir şekilde silinebilir ve bu amaç için teşhisler ortaya çıkmıştır. kopyalanan_indeksler.

Üçüncü sorun - kesişen endeksler

Çoğu acemi geliştirici, tek bir sütunda dizinler oluşturur. Yavaş yavaş, bu işi iyice deneyimleyen insanlar, sorgularını optimize etmeye ve birkaç sütun içeren daha karmaşık dizinler eklemeye başlar. Sütunlardaki dizinler bu şekilde görünür A, A + B, A + B + C ve benzeri. Bu endekslerden ilk ikisi, üçüncünün öneki oldukları için güvenle atılabilir. Bu aynı zamanda çok fazla disk alanı tasarrufu sağlar ve bunun için tanılamalar vardır kesişen_indeksler.

Dördüncü sorun - indekssiz yabancı anahtarlar

Postgres, bir destek dizini belirtmeden yabancı anahtar kısıtlamaları oluşturmanıza olanak tanır. Çoğu durumda bu bir sorun değildir ve hatta kendini göstermeyebilir bile... Şimdilik...

Bizim için de durum aynıydı: Sadece bir noktada, bir programa göre çalışan ve test siparişleri veri tabanını temizleyen bir iş, ana sunucu tarafından bize "eklenmeye" başladı. CPU ve IO boşa gitti, istekler yavaşladı ve zaman aşımına uğradı, hizmet beş yüzdü. Hızlı analiz pg_stat_activity şunun gibi sorgular gösterdi:

delete from <table> where id in (…)

Bu durumda elbette hedef tabloda id'ye göre bir indeks vardı ve duruma göre çok az sayıda kayıt silindi. Her şeyin işe yaraması gerekiyormuş gibi görünüyordu ama ne yazık ki olmadı.

Harika olan kurtarmaya geldi Analizi açıkla hedef tablodaki kayıtların silinmesinin yanı sıra referans bütünlüğü kontrolünün de yapıldığını, ilgili tablolardan birinde bu kontrolün başarısız olduğunu söyledi. sıralı tarama uygun bir indeksin bulunmamasından kaynaklanmaktadır. Böylece teşhis doğdu yabancı_anahtarlar_without_index.

Beşinci sorun – dizinlerdeki boş değer

Varsayılan olarak Postgres, btree indekslerinde boş değerler içerir, ancak bunlara genellikle ihtiyaç duyulmaz. Bu nedenle, bu boş değerleri (teşhis) özenle atmaya çalışıyorum indexes_with_null_values), türe göre null yapılabilir sütunlarda kısmi dizinler oluşturma where <A> is not null. Bu sayede indekslerimizden birinin boyutunu 1877 MB'tan 16 KB'ye düşürmeyi başardım. Ve hizmetlerden birinde, boş değerlerin endekslerden hariç tutulması nedeniyle veritabanı boyutu toplamda% 16 (mutlak sayılarla 4.3 GB) azaldı. Çok basit değişikliklerle disk alanından büyük tasarruf. 🙂

Altıncı sorun – birincil anahtarların eksikliği

Mekanizmanın doğası gereği Postgres'te MVCC böyle bir durum mümkün kabartmakÇok sayıda ölü kayıt nedeniyle tablonuzun boyutu hızla büyüdüğünde. Bunun bizi tehdit etmeyeceğine ve bunun bizim tabanımızın başına gelmeyeceğine safça inandım, çünkü biz, vay!!!, normal geliştiricileriz... Ne kadar aptal ve safmışım...

Bir gün harika bir geçiş, büyük ve aktif olarak kullanılan bir tablodaki tüm kayıtları aldı ve güncelledi. Birdenbire tablo boyutuna +100 GB aldık. Çok yazık oldu ama talihsizliklerimiz bununla bitmedi. Bu masadaki otovakumun 15 saat sonra sona ermesinin ardından fiziki konumun geri dönmeyeceği netleşti. Hizmeti durdurup VACUUM FULL yapamadığımız için kullanmaya karar verdik. pg_repack. Ve sonra ortaya çıktı ki pg_repack tabloların birincil anahtar veya başka bir benzersizlik kısıtlaması olmadan nasıl işleneceğini bilmiyor ve tablomuzun birincil anahtarı yoktu. Böylece teşhis doğdu tablolar_without_primary_key.

Kütüphane sürümünde 0.1.5 Tablolardan ve dizinlerden veri toplama ve bunlara zamanında yanıt verme yeteneği eklendi.

Yedinci ve sekizinci sorunlar - yetersiz dizinler ve kullanılmayan dizinler

Aşağıdaki iki teşhis şunlardır: table_with_missing_indexes и kullanılmayan_indeksler Nispeten yakın zamanda son haliyle ortaya çıktı. Mesele şu ki, bunlar öylece alınıp eklenemez.

Daha önce de yazdığım gibi, birkaç kopya içeren bir konfigürasyon kullanıyoruz ve farklı ana bilgisayarlardaki okuma yükü temelde farklı. Sonuç olarak, bazı ana bilgisayarlardaki bazı tabloların ve dizinlerin pratikte kullanılmadığı ve analiz için kümedeki tüm ana bilgisayarlardan istatistik toplamanız gerektiği ortaya çıkıyor. İstatistikleri sıfırla Bu aynı zamanda kümedeki her ana bilgisayarda da gereklidir; bunu yalnızca ana bilgisayarda yapamazsınız.

Bu yaklaşım, hiç kullanılmayan dizinleri kaldırarak ve nadiren kullanılan tablolara eksik dizinleri ekleyerek onlarca gigabayt tasarruf etmemizi sağladı.

Sonuç olarak

Elbette hemen hemen tüm teşhisler için yapılandırabilirsiniz Hariç listesi. Bu şekilde uygulamanızda hızlı bir şekilde kontroller uygulayabilir, yeni hataların ortaya çıkmasını engelleyebilir ve ardından eski hataları kademeli olarak düzeltebilirsiniz.

Bazı tanılamalar, veritabanı geçişlerinin kullanıma sunulmasından hemen sonra işlevsel testlerde gerçekleştirilebilir. Ve bu belki de kütüphanemin en güçlü özelliklerinden biri. Bir kullanım örneği şurada bulunabilir: gösteri.

Kullanılmayan veya eksik dizinlerin yanı sıra şişkinlik kontrollerini yalnızca gerçek bir veritabanında gerçekleştirmek mantıklıdır. Toplanan değerler kaydedilebilir Tıklama Evi veya izleme sistemine gönderilir.

gerçekten bunu umuyorum pg-index-sağlık faydalı ve talep görecek. Ayrıca bulduğunuz sorunları bildirerek ve yeni teşhisler önererek kütüphanenin gelişimine katkıda bulunabilirsiniz.

Kaynak: habr.com

Yorum ekle