Hızlı test için PostgreSQL'i optimize edin


203

PostgreSQL için SQLite tipik bir Rails uygulaması için geçiyorum.

Sorun, PG ile çalışan özelliklerin yavaşlamasıdır.
SQLite'de ~ 34 saniye, PG'de 2x'den daha yavaş olan ~ 76 saniyedir .

Bu yüzden şimdi hiçbir kod değişikliği olmadan SQLite ile eşit performans performansını getirmek için bazı teknikler uygulamak istiyorum (ideal olarak muhtemelen mümkün olmayan bağlantı seçeneklerini ayarlayarak).

Başımın üstünden bariz şeyler:

  • RAM Disk (OSX'te RSpec ile iyi kurulum görmek iyi olurdu)
  • Bloke edilmemiş tablolar (tüm komut dosyalarında değişiklik olmamam için veritabanının tamamına uygulanabilir mi?)

Anlayacağınız gibi, güvenilirliği ve geri kalanını umursamıyorum (DB sadece bir ıskarta şeydir).
PG'den en iyi şekilde yararlanmam ve olabildiğince hızlı yapmam gerekiyor .

En iyi cevap ideal olarak sadece bunu yapmak için hileleri , kurulumu ve bu hilelerin dezavantajlarını açıklar .

GÜNCELLEME: fsync = off + full_page_writes = offyalnızca zamanı ~ 65 saniyeye düşürdü (~ -16 sn). İyi bir başlangıç, ancak 34 hedefinden uzak.

GÜNCELLEME 2: Ben kullanım RAM diske çalıştı ama performans kazancı bir hata payı içinde oldu. Yani buna değmez gibi görünüyor.

GÜNCELLEME 3: * En büyük darboğazı buldum ve şimdi özellikleri SQLite olanlar kadar hızlı çalışıyor.

Sorun, kesme işlemini yapan veritabanı temizliğiydi . Görünüşe göre SQLite orada çok hızlı.

"Düzeltmek" için her testten önce bir işlem açar ve sonunda geri alırım.

~ 700 testleri için bazı sayılar.

  • Kesme: SQLite - 34s, PG - 76s.
  • İşlem: SQLite - 17s, PG - 18s.

SQLite için 2 kat hız artışı. PG için 4 kat hız artışı.


2
SQLite kadar hızlı gideceğinizden şüpheliyim. Tek bir kullanıcı ile SQLite inanılmaz derecede hızlı. SQLite tasarımı düşük kullanıcı sayısı ile çok hızlıdır ve zayıf ölçeklendirilmiştir; Pg'nin tasarımı iyi ölçeklenir, ancak tek bir kullanıcıyla basit toplu çalışma için hızlı değildir.
Craig Ringer

1
Bunu anlıyorum, ancak PG'yi (test çalıştırmaları) için optimize etmeyi umduğum özel bir durum var, bu yüzden olabildiğince hızlı. Orada biraz daha yavaş olması umrumda değil , ama 2.2x biraz fazla yavaş. Neyi kastettiğimi anla?
Dmytrii Nagirniak

+1 Bununla ilgili herhangi bir sonuç alırsanız RAM disk yaklaşımındaki güncellemelerle çok ilgilenirim.
tscho

@tscho Kesinlikle buraya göndereceğim. Ama diğer şeyler üzerinde çalışıyorum ve "arka plan" PG şeyler "araştırma" beri biraz zamana ihtiyacım var.
Dmytrii Nagirniak

olduğunu ekleme veri sorununuzu veya sorgulama ? Sorunuz net değil.
a_horse_with_no_name

Yanıtlar:


281

İlk olarak, daima PostgreSQL'in en son sürümünü kullanın. Performans iyileştirmeleri her zaman geliyor, bu nedenle eski bir sürümü ayarlıyorsanız muhtemelen zamanınızı boşa harcıyorsunuz. Örneğin, PostgreSQL 9.2, hızını önemli ölçüde artırırTRUNCATE ve elbette yalnızca dizin taramaları ekler. Küçük sürümler bile daima takip edilmelidir; bkz sürüm politikası .

Yapılmaması Gerekenler

Do DEĞİL RamDisk'i veya diğer dayanıksız depolama bir bir tablo koydu .

Bir tablo alanını kaybederseniz, tüm veritabanı zarar görebilir ve önemli bir iş yapmadan kullanımı zor olabilir. Bunun sadece UNLOGGEDtabloları kullanmak ve zaten önbellek için çok fazla RAM'e kıyasla çok az avantajı var .

Gerçekten ramdisk tabanlı bir sistem istiyorsanız, ramdisk initdbüzerinde initdbyeni bir PostgreSQL örneği oluşturarak ramdisk üzerinde tamamen yeni bir küme istiyorsanız, tamamen tek kullanımlık bir PostgreSQL örneğine sahip olursunuz.

PostgreSQL sunucu yapılandırması

Test yaparken sunucunuzu dayanıklı olmayan ancak daha hızlı çalışacak şekilde yapılandırabilirsiniz .

Bu, fsync=offPostgreSQL'deki ayar için kabul edilebilir tek kullanımdan biridir. Bu ayar, PostgreSQL'e sıralı yazma işlemleri veya diğer kötü veri bütünlüğü koruma ve çarpışma güvenliği öğelerinden herhangi birini rahatsız etmemesini söyler, böylece güç kaybederseniz veya bir OS çökmesi varsa verilerinizi tamamen çöpe atmasına izin verir.

Söylemeye gerek yok, fsync=offPg'yi başka bir yerden yeniden oluşturabileceğiniz veriler için geçici bir veritabanı olarak kullanmadığınız sürece asla üretimde etkinleştirmemelisiniz . Eğer sadece fsync'i kapatmaya çalışıyorsanız, full_page_writesartık o kadar iyi olmadığı için de kapanabilir. O sakının fsync=offve full_page_writesen geçerli küme onlar etkileyen seviyesi, bu nedenle tüm PostgreSQL örneğinde veritabanlarını.

Üretim kullanımı synchronous_commit=offiçin commit_delay, fsync=offdev veri bozulma riski olmadan aynı avantajların çoğunu alacağınız için muhtemelen bir a kullanabilirsiniz . Zaman uyumsuzluğu etkinleştirirseniz, son veri kaybı için küçük bir pencereniz vardır - ancak bu kadar.

UNLOGGEDDDL'yi biraz değiştirme seçeneğiniz varsa, WAL günlüğünden tamamen kaçınmak ve sunucu çöktüğünde tabloların silinmesi pahasına gerçek bir hız artışı elde etmek için Pg 9.1+'deki tabloları da kullanabilirsiniz . Tüm tabloların bloke edilmesini sağlayacak bir yapılandırma seçeneği yoktur, sırasında ayarlanmalıdır CREATE TABLE. Test için iyi olmanın yanı sıra, güvenli olması gereken şeyler içeren bir veritabanında oluşturulan veya önemsiz verilerle dolu tablolarınız varsa bu kullanışlıdır.

Günlüklerinizi kontrol edin ve çok fazla kontrol noktası hakkında uyarı alıp almadığınızı görün. Eğer öyleyse, kontrol noktanızı_segmentlerinizi artırmalısınız . Ayrıca düzgün yazma işlemleri için checkpoint_completion_target'ınızı ayarlamak isteyebilirsiniz.

Ayarlama shared_buffersiş yükünüzü sığdırmak için. Bu işletim sistemine bağlıdır, makinenizde başka neler olup bittiğine bağlıdır ve biraz deneme yanılma gerektirir. Varsayılanlar son derece muhafazakardır. shared_buffersPostgreSQL 9.2 ve altı sürümlerde yükselirseniz işletim sisteminin maksimum paylaşılan bellek sınırını artırmanız gerekebilir ; 9.3 ve üstü, bundan kaçınmak için paylaşılan belleği kullanma biçimlerini değiştirdi.

Çok fazla iş yapan sadece birkaç bağlantı kullanıyorsanız, work_memonlara vb. Oynamak için daha fazla RAM vermek için artırın . Çok yüksek bir work_memayarın bellek yetersiz sorunlara neden olabileceğine dikkat edin, çünkü bir sorguda çok sayıda iç içe sıralama olabilir. Yalnızca gerçekten artırmalıyız work_memsen diske dökülmesini türlü görürse EXPLAINveya birlikte günlüğe log_temp_filesayarı (önerilir), ancak daha yüksek bir değer de Pg akıllı planlar almak izin verebilir.

Burada başka bir posterde de belirtildiği gibi, xlog ve ana tabloları / dizinleri mümkünse ayrı HDD'lere koymak akıllıca olacaktır. Ayrı bölümler oldukça anlamsız, gerçekten ayrı sürücüler istiyorsun. Bu ayrıştırma ile çalışıyorsanız çok daha az fayda sağlar fsync=offve UNLOGGEDtablo kullanıyorsanız neredeyse hiç yoktur .

Son olarak, sorgularınızı ayarlayın. Emin olun random_page_costve seq_page_costsisteminizin performansını yansıtın effective_cache_size, doğru olduğundan emin olun vb. EXPLAIN (BUFFERS, ANALYZE)Tek tek sorgu planlarını incelemek için kullanın ve auto_explaintüm yavaş sorguları bildirmek için modülü açın. Genellikle uygun bir dizin oluşturarak veya maliyet parametrelerini düzenleyerek sorgu performansını önemli ölçüde artırabilirsiniz.

AFAIK, bir veritabanının veya kümenin tamamını olarak ayarlamanın bir yolu yoktur UNLOGGED. Bunu yapabilmek ilginç olurdu. PostgreSQL posta listesini sormayı düşünün.

Ana bilgisayar işletim sistemi ayarı

İşletim sistemi düzeyinde de yapabileceğiniz bazı ayarlamalar var. Yapmak isteyebileceğiniz en önemli şey, işletim sistemini yazma işlemlerini diske agresif bir şekilde akıtmamaya ikna etmektir, çünkü diske ne zaman / yaptıklarını gerçekten umursamıyorsunuz.

Linux size bu kontrol edebilirsiniz sanal bellek alt sisteminin 'ın dirty_*gibi seçenekleri dirty_writeback_centisecs.

Geri yazma ayarlarının çok gevşek olmasıyla ilgili tek sorun, başka bir program tarafından yapılan bir yıkamanın, tüm PostgreSQL'in biriken arabelleklerinin de temizlenmesine ve her şey yazarken blokların durmasına neden olabilmesidir. PostgreSQL'i farklı bir dosya sisteminde çalıştırarak bunu hafifletebilirsiniz, ancak bazı kızarmalar dosya sistemi düzeyinde değil cihaz düzeyinde veya tüm ana makine düzeyinde olabilir, bu nedenle buna güvenemezsiniz.

Bu ayar, iş yükünüz için neyin en iyi olduğunu görmek için ayarlarla oynamayı gerçekten gerektirir.

Daha yeni çekirdeklerde, vm.zone_reclaim_modePostgreSQL'in yönetme şekliyle etkileşimler nedeniyle NUMA sistemleriyle (günümüzde çoğu sistemde) ciddi performans sorunlarına neden olabileceğinden sıfıra ayarlandığından emin olmak isteyebilirsiniz shared_buffers.

Sorgu ve iş yükü ayarı

Bunlar kod değişiklikleri gerektiren DO şeyler; size uymayabilirler. Bazıları uygulayabileceğiniz şeyler.

Daha büyük işlemlere toplu iş yapmıyorsanız başlayın. Birçok küçük işlem pahalıdır, bu nedenle mümkün olduğunda ve pratik olduğunda bir şeyler topluyor olmalısınız. Zaman uyumsuzluk taahhüdü kullanıyorsanız, bu daha az önemlidir, ancak yine de şiddetle tavsiye edilir.

Mümkünse geçici tablolar kullanın. WAL trafiği oluşturmazlar, bu nedenle ekler ve güncellemeler için çok daha hızlıdırlar. Bazen bir grup veriyi geçici bir tabloya dönüştürmek, ancak gereken şekilde manipüle etmek, ardından INSERT INTO ... SELECT ...son tabloya kopyalamak için bir yapmak gerekir. Geçici tabloların oturum başına olduğunu unutmayın; oturumunuz sona ererse veya bağlantınızı kaybederseniz geçici tablo kaybolur ve başka hiçbir bağlantı bir oturumun geçici tablolarının içeriğini göremez.

PostgreSQL 9.1 veya daha yenisini kullanıyorsanız UNLOGGED, oturum durumu gibi kaybetmeyi göze alabileceğiniz veriler için tabloları kullanabilirsiniz . Bunlar farklı oturumlarda görülebilir ve bağlantılar arasında korunur. Sunucu temiz olmayan bir şekilde kapanırsa kesilirler, böylece yeniden oluşturamayacağınız bir şey için kullanılamazlar, ancak önbellekler, materyalleştirilmiş görünümler, durum tabloları vb.

Genel olarak, yapma DELETE FROM blah;. TRUNCATE TABLE blah;Bunun yerine kullanın ; bir tablodaki tüm satırları boşaltırsanız çok daha hızlı olur. TRUNCATEMümkünse , bir çağrıda birçok tabloyu kısaltın . Yine de TRUNCATEStekrar tekrar birçok küçük masa yapıyorsanız bir uyarı var ; bakınız: Postgresql Kesme hızı

Yabancı anahtarlar üzerinde dizinleriniz yoksa, DELETEbu yabancı anahtarların başvuruda bulunduğu birincil anahtarları içeren anahtarlar çok yavaş olacaktır. DELETEReferans verilen tablolardan beklediğinizde bu tür dizinler oluşturduğunuzdan emin olun . İçin dizinler gerekli değildir TRUNCATE.

İhtiyacınız olmayan dizinler oluşturmayın. Her endeksin bir bakım maliyeti vardır. Çok az sayıda büyük, pahalı çok sütunlu dizin tutmak yerine, çok az sayıda dizin dizini kullanmaya ve bitmap dizin taramasının bunları birleştirmesine izin verin. Dizinler gerektiğinde, önce tabloyu doldurmaya çalışın, ardından sonunda dizinler oluşturun.

Donanım

Eğer tüm veritabanı tutmak için yeterli RAM olması onu yönetebilir eğer büyük bir kazançtır.

Yeterli RAM'iniz yoksa, daha hızlı depolama alanı daha iyi olabilir. Ucuz bir SSD bile, eğirme pası üzerinde büyük bir fark yaratır. Ancak üretim için ucuz SSD'lere güvenmeyin, genellikle güvenli değildir ve verilerinizi yiyebilir.

Öğrenme

Greg Smith'in PostgreSQL 9.0 Yüksek Performans adlı kitabı, biraz daha eski bir versiyona atıfta bulunulmasına rağmen alakalı olmaya devam ediyor. Yararlı bir referans olmalıdır.

PostgreSQL genel posta listesine katılın ve takip edin.

Okuma:


10
Ayrıca @GregSmith tarafından PostgreSQL 9.0 Yüksek Performansı önerebilirim, gerçekten harika bir okuma. Kitap, disk düzeninden sorgu ayarlamaya kadar performans ayarlamasının tüm yönlerini kapsar ve PG dahili bileşenlerini çok iyi anlar.
tscho

10
Yayınlanmasından bu yana yayımlanan tek sürüm olan PostgreSQL 9.1 kitabında bir güncelleme yayınlamadım, çünkü 9.1'de bunu garanti etmek için performansla ilgili değişiklikler yeterli değildi.
Greg Smith

3
Harika bir yazı. Küçük bir güncelleme gibi, PostgreSQL 9.3 “ postgresql.org/docs/9.3/static/release-9-
Gunnlaugur Briem

1
@ brauliobo Testlerim genellikle yüksek TPS'de birçok tx yapıyor ... çünkü eşzamanlılık ağır iş yükleri de dahil olmak üzere üretimi simüle etmeye çalışıyorum. "Tek bağlantı, doğrusal test" demek istiyorsan, sana katılıyorum.
Craig Ringer

1
stackoverflow.com/questions/11419536/… DELETE, birkaç satır içeren tablolar için TRUNCATE değerinden daha hızlı olabilir; bu, testlerde olması muhtemeldir.
Jonathan Crosmer

9

Farklı disk düzeni kullanın:

  • $ PGDATA için farklı disk
  • $ PGDATA / pg_xlog için farklı disk
  • tem dosyaları için farklı disk (veritabanı başına $ PGDATA / base // pgsql_tmp) (work_mem hakkındaki nota bakın)

postgresql.conf tweaks:

  • shared_memory: Kullanılabilir RAM'in% 30'u, ancak 6 ila 8 GB'den fazla değil. Yazma yoğun iş yükleri için daha az paylaşılan belleğe (2GB - 4GB) sahip olmak daha iyi görünüyor
  • work_mem: çoğunlukla sıralama / toplama içeren belirli sorgular için. Bu bağlantı ayarına göredir ve sorgu bu değeri birden çok kez ayırabilir. Veriler sığmıyorsa disk kullanılır (pgsql_tmp). Ne kadar belleğe ihtiyacınız olduğunu görmek için "analiz et" açıklamasını kontrol edin
  • fsync ve simultaneous_commit: Varsayılan değerler güvenlidir ancak kaybedilen verilere tahammül edebiliyorsanız kapatıp kapatabilirsiniz
  • random_page_cost: SSD veya hızlı RAID diziniz varsa bunu SSD için 2.0 (RAID) veya daha düşük (1.1) değerine düşürebilirsiniz.
  • checkpoint_segments: 32 veya 64 daha yükseğe çıkabilir ve checkpoint_completion_target değerini 0.9 olarak değiştirebilirsiniz. Düşük değer, çarpışma sonrası daha hızlı kurtarma sağlar

4
Zaten çalışıyorsanız fsync=off, pg_xlog dosyasını ayrı bir diske yerleştirmenin artık çok fazla gelişmeyeceğini unutmayın.
intgr

SSD için 1.1 değeri çok niteliksiz görünüyor. Bazı profesyonellerin körü körüne önerdiğini kabul ediyorum. SSD'ler bile sıralı okumalar için rastgele okumalardan önemli ölçüde daha hızlıdır.
Acumenus

@ABB Evet, ancak iş yerinizde OS arabellek önbellekleme efektlerine de sahipsiniz. Tüm bu parametreler yine de biraz el sallıyor ...
Craig Ringer
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.