PostgreSQL'de sıfır kesintiyle indeks değişiklikleri: güvenli bir playbook
CONCURRENTLY, basit kilit kontrolleri ve net geri alma adımlarıyla PostgreSQL'de sıfır kesintili indeks değişiklikleri, üretim trafiğini açık tutmak için.

Neden indeks değişiklikleri kesintiye yol açar (ve bundan nasıl kaçınırsınız)
İndeks çalışması zararsız gibi gelir. "Sadece" yardımcı bir yapı ekliyorsunuzdur. Ancak PostgreSQL'de indeks oluşturma, silme veya değiştirme diğer oturumları engelleyebilen kilitler alabilir. Tablo meşgulse bu beklemeler birikir ve uygulama bozulmuş gibi hissedilir.
Kesinti nadiren temiz bir kesinti ilanı gibi görünür. Genellikle sayfaların takılması, arka plan işlerinin geri kalması ve veritabanında bekleyen artan bir istek kuyruğu olarak ortaya çıkar. Biri "Ara"ya basar ve zaman aşımı alır; destek araçları ve yönetim ekranları basit sorgular ihtiyaç duydukları kilidi alamadığı için aniden yavaşlar.
"Sadece gece çalıştır" önerisi iki yaygın nedenle başarısız olur. Birçok sistem gerçekten hiç sessiz değildir (global kullanıcılar, toplu işler, ETL, yedeklemeler). Ve indeks işlemleri beklediğinizden daha uzun sürebilir çünkü çok veri okur ve CPU ile disk için yarışır. Pencere oluşturma sırasında kapanırsa ya daha uzun beklemek ya da işi kesintiye uğratmak arasında kalırsınız.
Sıfır kesintiyle indeks değişiklikleri sihir değildir. En az engelleyen işlemi seçmek, koruyucu önlemler koymak (zaman aşımı ve disk kontrolleri) ve veritabanını çalışırken izlemekle ilgilidir.
Bu playbook pratik üretim alışkanlıklarına odaklanır:
- Okumalar ve yazmalar devam etmeliyse eşzamanlı (concurrent) indeks oluşturmayı tercih edin.
- Engellemeleri ve oluşturma ilerlemesini izleyin ki erken müdahale edebilesiniz.
- Değişiklik regresyona neden olursa veya çok uzun sürerse geri alma yolu hazırlayın.
Kapsamadığı konular: derin indeks tasarım teorisi, geniş sorgu optimizasyonu veya çok fazla veriyi yeniden yazan şema refaktörleri.
İndeks çalışmasının basit kilit modeli
PostgreSQL, birçok oturum aynı tabloya dokunduğunda verinin doğruluğunu korumak için kilitler kullanır. Kilit, şu anda kimin bir nesneyi okuyup yazmasına izin verildiğini ve kimin beklemek zorunda olduğunu söyleyen bir kuraldır.
Çoğu zaman kilitleri fark etmezsiniz çünkü PostgreSQL normal sorguların çalışmasına izin veren hafif modları kullanabilir. DDL farklıdır. Bir indeks oluştururken veya silerken PostgreSQL, katalog ve verinin tutarlı kalmasını sağlamak için tablo üzerinde yeterli kontrol sahibi olmalıdır. Ne kadar fazla kontrol gerekliyse, o kadar çok diğer oturumlar beklemek zorunda kalabilir.
Bir indeksi oluşturmak vs indeksi kullanmak
Bir indeksi kullanmak genellikle kilit açısından ucuzdur. SELECT, UPDATE ve DELETE sorguları indeksleri okurken veya bakımı yaparken diğer oturumların da aynı şeyi yapmasına izin veren modlarda çalışabilir.
İndeks oluşturmak farklıdır. PostgreSQL tablonun tamamını taramak, anahtarları sıralamak veya hash'lemek ve yeni bir yapıyı diske yazmak zorundadır. Bu işler zaman alır ve zaman, üretimde "küçük kilitleri" "büyük problemler"e dönüştüren şeydir.
CONCURRENTLY neyi değiştirir (ve neyi değiştirmez)
Normal bir CREATE INDEX süre boyunca yazmaları engelleyen güçlü bir kilit alır. CREATE INDEX CONCURRENTLY indeksi oluştururken normal okuma ve yazma işlemlerinin devam etmesini sağlamaya yönelik tasarlanmıştır.
Ama "concurrent" kilitsiz demek değildir. Başlangıçta ve bitişte kısa kilit pencereleri olur ve eğer başka bir şey uyumsuz kilitler tutuyorsa oluşturma başarısız olabilir veya bekleyebilir.
En önemli sonuçlar şunlardır:
- Non-concurrent (normal) oluşturma insert, update ve delete işlemlerini bloke edebilir.
- Concurrent oluşturma genellikle okuma ve yazmalara izin verir, ancak uzun süren işlemler tarafından yavaşlatılabilir veya durdurulabilir.
- Bitirme adımları yine kısa kilitler gerektirir; çok yoğun sistemlerde kısa beklemeler görülebilir.
Doğru yaklaşımı seçin: concurrent mi normal mi
İndeks değiştirirken iki temel seçeneğiniz vardır: indeksi normal şekilde oluşturmak (hızlı ama engelleyici) veya CONCURRENTLY ile oluşturmak (uygulama trafiği için genelde engellemez, ama daha yavaş ve uzun işlemlere duyarlıdır).
Ne zaman CONCURRENTLY doğru tercihtir
Tablo gerçek trafik alıyorsa ve yazmaları durduramıyorsanız CREATE INDEX CONCURRENTLY kullanın. Genellikle güvenli tercih şunlar için doğrudur:
- Tablo normal oluşturmanın dakikalar ya da saatler sürebileceği kadar büyükse.
- Tablo düzenli yazma yapıyorsa, sadece okuma değilse.
- Gerçek bir bakım penceresi planlayamıyorsanız.
- Önce indeksi oluşturup doğrulamak, sonra eski indeksi kaldırmak istiyorsanız.
Normal indeks oluşturma ne zaman kabul edilebilir
Tablo küçükse, trafik düşükse veya kontrol edilen bir pencereye sahipseniz normal CREATE INDEX uygun olabilir. Genellikle daha hızlı biter ve çalıştırması daha basittir.
Eğer oluşturma staging'de sürekli hızlıysa ve yazmaları geçici olarak durdurabiliyorsanız normal yaklaşımı değerlendirin.
Eğer benzersizlik gerekiyorsa, erken karar verin. CREATE UNIQUE INDEX CONCURRENTLY çalışır, fakat yineleme değerleri varsa başarısız olur. Birçok üretim sisteminde tekrar eden değerleri bulmak ve düzeltmek gerçek projedir.
Üretime dokunmadan önceki preflight kontrolleri
Çoğu sorun komut başlamadan önce olur. Birkaç kontrol, iki büyük sürprizi önlemenize yardımcı olur: beklenmeyen engellenmeler ve planladığınızdan çok daha uzun (veya daha fazla alan kullanan) bir indeks oluşturma.
-
Bir transaction içinde olmadığınızdan emin olun.
CREATE INDEX CONCURRENTLYeğerBEGINsonrası çalıştırılırsa başarısız olur ve bazı GUI araçları ifadeleri sessizce bir transaction içine alır. Emin değilseniz yeni bir oturum açın ve sadece indeks komutunu orada çalıştırın. -
Zaman ve disk beklentilerini ayarlayın. Concurrent oluşturma genelde normal oluşturmandan daha uzun sürer ve çalışırken ekstra çalışma alanı gerekir. Yeni indeks ve geçici üstyapı için plan yapın ve rahat bir boş disk alanı olduğundan emin olun.
-
Hedefinize uygun zaman aşımlarını ayarlayın. Kilidi alamıyorsanız işlemin hızlıca başarısız olmasını istersiniz, ama agresif bir statement timeout yüzünden oturumun oluşturma sırasında ölmesini istemezsiniz.
-
Bir baseline yakalayın. Değişikliğin yardımcı olduğunu kanıtlamak ve regresyonları hızlıca fark etmek için önceden bir snapshot alın: yavaş sorgu zamanlaması, temsilî bir
EXPLAIN (ANALYZE, BUFFERS), ve CPU, IO, bağlantılar ile boş disk için hızlı bir görünüm kaydedin.
Takımların başlangıç olarak kullandığı güvenli oturum ayarları (kendi kurallarınıza göre ayarlayın):
-- Run in the same session that will build the index
SET lock_timeout = '2s';
SET statement_timeout = '0';
Adım adım: CONCURRENTLY ile indeks oluşturma
Uygulama trafiğinin devam etmesini istiyorsanız ve daha uzun bir oluşturma süresini göze alabiliyorsanız CREATE INDEX CONCURRENTLY kullanın.
Önce tam olarak ne oluşturduğunuza karar verin:
- Sütun sırasına dikkat edin (önemlidir).
- Kısmi (partial) bir indeksin yeterli olup olmadığını değerlendirin. Eğer sorguların çoğu "aktif" satırlara filtreliyorsa, kısmi indeks daha küçük, daha hızlı ve bakım açısından daha ucuz olabilir.
Güvenli bir çalışma şöyle görünür: hedefi ve indeks adını yazın, herhangi bir transaction bloğu dışında oluşturmayı çalıştırın, tamamlanana kadar izleyin, sonra planner'ın onu kullanabildiğini doğrulayın ve başka bir şeyi kaldırmadan önce emin olun.
-- Example: speed up searches by email for active users
CREATE INDEX CONCURRENTLY idx_users_active_email
ON public.users (email)
WHERE status = 'active';
-- Validate it exists
SELECT indexname, indexdef
FROM pg_indexes
WHERE tablename = 'users';
-- Check the plan can use it
EXPLAIN (ANALYZE, BUFFERS)
SELECT id
FROM public.users
WHERE status = 'active' AND email = '[email protected]';
İlerleme notları (denetimler için faydalı): başlama zamanı, bitiş zamanı ve gördüğünüz herhangi bir bekleme kaydedin. Çalışırken başka bir oturumdan pg_stat_progress_create_index sorgulayabilirsiniz.
Doğrulama sadece "indeks var" demek değildir. Planın onu seçebildiğini doğrulayın, sonra dağıtımdan sonra gerçek sorgu zamanlamasını izleyin. Yeni indeks kullanılmıyorsa, eski indeksi aceleyle silmeyin. Önce sorguyu veya indeks tanımını düzeltin.
Adım adım: engellemeden indeksleri değiştirme veya kaldırma
En güvenli desen önce eklemek, trafiğin yeni indeksten faydalanmasına izin vermek ve ancak ondan sonra eski indeksleri kaldırmaktır. Böylece çalışan bir geri dönüş seçeneğiniz kalır.
Eski bir indeksi yeni biriyle değiştirmek (güvenli sıra)
-
Yeni indeksi
CREATE INDEX CONCURRENTLYile oluşturun. -
Bunun kullanıldığını doğrulayın. Önemli yavaş sorgularınızda
EXPLAINkesin ve zaman içinde indeks kullanımını izleyin. -
Ancak bundan sonra eski indeksi concurrently olarak düşürün. Risk yüksekse, herhangi bir şeyi kaldırmadan önce tam bir iş döngüsü boyunca her iki indeksi de tutun.
İndeksleri düşürme: CONCURRENTLY ne zaman işe yarar (ve ne zaman yaramaz)
Kendinizin oluşturduğu normal bir indeks için DROP INDEX CONCURRENTLY genelde doğru seçimdir. İki dikkat edilmesi gereken nokta: transaction bloğu içinde çalışamaz ve yine başlangıç/bitişte kısa kilitler gerektirdiği için uzun süren işlemler tarafından geciktirilebilir.
İndeks bir PRIMARY KEY veya UNIQUE kısıtının parçasıysa, genelde doğrudan silemezsiniz. Önce constraint'i ALTER TABLE ile değiştirmeniz gerekir; bu daha güçlü kilitler gerektirebilir ve ayrı planlı bir bakım operasyonu sayılmalıdır.
İndeksleri isimlendirme
ALTER INDEX ... RENAME TO ... genelde hızlıdır, ama araçlar veya migration'lar indeks adlarına referans veriyorsa bundan kaçının. Daha güvenli bir alışkanlık baştan net bir isim seçmektir.
Eski indeksin hâlâ gerekli olduğu durumlar
Bazen iki farklı sorgu modeli iki farklı indeksi gerektirir. Önemli sorgular eski indekse halen bağımlıysa onu tutun. Yeni indeksi (sütun sırası, kısmi koşul) ayarlamayı düşünün, yanlışlıkla silmek yerine.
İndeks oluşturulurken kilitleri ve ilerlemeyi izleme
CREATE INDEX CONCURRENTLY olsa bile çalışırken neler olduğunu izlemelisiniz. Çoğu sürpriz olay iki şeyden biriyle ilgilidir: fark etmediğiniz bir engelleyen oturum veya oluşturmayı bekleten uzun süreli bir transaction.
Engelleyen oturumları tespit etme (kim kimi engelliyor)
Kilit bekleyen oturumları bulmakla başlayın:
SELECT
a.pid,
a.usename,
a.application_name,
a.state,
a.wait_event_type,
a.wait_event,
now() - a.xact_start AS xact_age,
left(a.query, 120) AS query
FROM pg_stat_activity a
WHERE a.wait_event_type = 'Lock'
ORDER BY xact_age DESC;
Tam engelleyeni bilmeniz gerekirse blocked_pid'den blocking_pid'ye gidin:
SELECT
blocked.pid AS blocked_pid,
blocking.pid AS blocking_pid,
now() - blocked.xact_start AS blocked_xact_age,
left(blocked.query, 80) AS blocked_query,
left(blocking.query, 80) AS blocking_query
FROM pg_stat_activity blocked
JOIN pg_stat_activity blocking
ON blocking.pid = ANY (pg_blocking_pids(blocked.pid))
WHERE blocked.wait_event_type = 'Lock';
Oluşturma ilerlemesini ve "takılma" sinyallerini izleme
PostgreSQL indeks oluşturma ilerlemesini açığa çıkarır. Uzun süre hiç hareket görmüyorsanız, eski bir snapshot tutuyor olabilecek uzun süreli bir işleme bakın (çoğunlukla idle oturumlar).
SELECT
pid,
phase,
lockers_total,
lockers_done,
blocks_total,
blocks_done,
tuples_total,
tuples_done
FROM pg_stat_progress_create_index;
Ayrıca sistem baskısına dikkat edin: disk IO, replikasyon gecikmesi ve artan sorgu süreleri. Concurrent oluşturma uptim'e daha dost olsa da yine de çok fazla veri okur.
Üretimde iyi çalışan basit kurallar:
- İlerleme varsa ve kullanıcı etkisi düşükse bekleyin.
- Oluşturma uzun bir transaction'ın arkasında takıldıysa ve güvenli şekilde sonlandıramıyorsanız iptal edip yeniden planlayın.
- IO müşteri odaklı sorguları olumsuz etkiliyorsa yoğun dönemlerde duraklatın.
- Sadece son çare olarak sonlandırın ve oturumun ne yaptığını doğrulayın.
Ekip iletişimi için güncellemeleri kısa tutun: başlama zamanı, mevcut aşama, engelleyen varsa ne olduğu ve ne zaman tekrar kontrol edeceğiniz.
Geri alma planı: güvenli şekilde nasıl geri dönülür
İndeks değişiklikleri, başlamadan önce çıkışı planlarsanız düşük riskli kalır. En güvenli rollback genellikle dramatik bir geri alma değildir. Yeni işi durdurmak ve eski indeksi yerinde tutmak, genelde en güvenli yaklaşımdır.
İndeks çalışmalarının sık başarısız olma biçimleri
Çoğu üretim hatası tahmin edilebilirdir: oluşturma bir timeout'a takılır, biri bir olay sırasında iptal eder, sunucu diskte boşluk kalmaz veya oluşturma normal trafikle yarışıp kullanıcı gecikmesini artırır.
CREATE INDEX CONCURRENTLY ile iptal genelde uygulama için güvenlidir çünkü sorgular çalışmaya devam eder. Takas, temizlik gerektirir: iptal edilen veya başarısız olan concurrent oluşturma geride geçersiz bir indeks bırakabilir.
Güvenli iptal ve temizlik kuralları
Concurrent oluşturmayı iptal etmek normal bir transaction gibi geri almaz. PostgreSQL bir indeksi var ama planner için geçersiz olarak bırakabilir.
-- Cancel the session building the index (use the PID you identified)
SELECT pg_cancel_backend(\u003cpid\u003e);
-- If the index exists but is invalid, remove it without blocking writes
DROP INDEX CONCURRENTLY IF EXISTS your_index_name;
Silmeden önce neye baktığınızı doğrulayın:
SELECT
c.relname AS index_name,
i.indisvalid,
i.indisready
FROM pg_index i
JOIN pg_class c ON c.oid = i.indexrelid
WHERE c.relname = 'your_index_name';
Eğer indisvalid = false ise, kullanılmıyor demektir ve güvenle düşürülebilir.
Mevcut bir indeksi değiştirirken pratik geri alma kontrol listesi:
- Yeni indeks tam olarak oluşturulup geçerli olana kadar eski indeksi tutun.
- Yeni oluşturma başarısız olduysa veya iptal edildiyse, geçersiz yeni indeksi concurrently olarak silin.
- Eğer zaten eski indeksi sildiyseniz, önceki durumu geri getirmek için onu
CREATE INDEX CONCURRENTLYile yeniden oluşturun. - Disk baskısı hataya yol açtıysa önce alan boşaltın, sonra yeniden deneyin.
- Timeout'lar hataya yol açtıysa, zorlamak yerine daha sessiz bir pencere planlayın.
Örnek: bir yönetici araması için yeni indeks oluşturdunuz, 20 dakika sonra disk alarmları geldi. Oluşturmayı iptal edin, geçersiz indeksi concurrently silin ve eski indeksi trafiğe hizmet etmeye devam etsin. Alan boşalttıktan sonra yeniden deneyebilirsiniz, kullanıcı görünen bir kesinti olmadan.
Sürpriz kesintilere yol açan yaygın hatalar
İndekslerle ilgili çoğu kesinti PostgreSQL'in "yavaşlığı" yüzünden olmaz. Güvenli bir değişikliği engelleyici hale getiren küçük bir detay yüzünden olur.
1) Concurrent oluşturmayı bir transaction içine koymak
CREATE INDEX CONCURRENTLY bir transaction bloğu içinde çalışmaz. Birçok migration aracı varsayılan olarak her değişikliği tek bir transaction içine alır. Sonuç ya sert bir hata olur (en iyi ihtimalle) ya da yeniden denemelerle karışık bir deploy yaşanır.
Migration'ı çalıştırmadan önce aracınızın ifadeyi dış bir transaction olmadan çalıştırabildiğini doğrulayın veya migration'ı özel, non-transactional bir adım olarak ayırın.
2) Yoğun trafik sırasında başlatmak
Concurrent indeks oluşturma engellemeyi azaltır ama yine de yük ekler: ekstra okuma, ekstra yazma ve autovacuum üzerinde daha fazla baskı. Deploy penceresinde trafik zirve yaparken başlatmak, gecikmelerin artmasına ve kullanıcı deneyiminin bozulmasına neden olur.
Sessiz bir dönem seçin ve bunu normal bir üretim bakımı gibi ele alın.
3) Uzun süren işlemleri görmezden gelmek
Tek bir uzun işlem concurrent oluşturmanın temizleme aşamasını tutabilir. İndeks ilerliyor gibi görünebilir, sonra eski snapshot'lar kaybolana kadar bitişe yakın bekleyebilir.
Alışkanlık haline getirin: başlamadan önce ve ilerleme takılıyorsa uzun süreli işlemler için kontrol edin.
4) Yanlış şeyi silmek (veya bir kısıtı kırmak)
Takımlar bazen indeks adını hafızadan siler veya benzersizlik kurallarını destekleyen bir indeksi yanlışlıkla kaldırır. Yanlış nesneyi silerseniz, uygulanabilirliği (unique constraint) kaybedebilir veya anında sorgu performansını geri döndürebilirsiniz.
Hızlı güvenlik kontrolü: indeks adını katalogda doğrulayın, bunun bir constraint destekleyip desteklemediğini kontrol edin, şema ve tabloyu iki kez kontrol edin ve "yeni oluştur" işlemini "eskiyi kaldır" işleminden ayrı tutun. Başlamadan önce geri alma komutunu hazır bulundurun.
Gerçekçi örnek: bir yönetici aramasını hızlandırma
Yönetici panelinde staging'de anlık görünen ama prod'da yavaş olan bir arama sık rastlanan bir sorundur. Diyelim ki tens of millions satırlı büyük bir tickets tablonuz var ve ajanlar sıkça "bir müşterinin açık biletleri, en yeniden başlayarak" araması yapıyor.
Sorgu şöyle:
SELECT id, customer_id, subject, created_at
FROM tickets
WHERE customer_id = $1
AND status = 'open'
ORDER BY created_at DESC
LIMIT 50;
Tam bir indeks (customer_id, status, created_at) yardımcı olur, fakat her ticket güncellemesi için yazma yükü ekler; kapalı olanlar da dahil. Eğer çoğu satır open değilse, kısmi bir indeks genelde daha basit bir kazanımdır:
CREATE INDEX CONCURRENTLY tickets_open_by_customer_created_idx
ON tickets (customer_id, created_at DESC)
WHERE status = 'open';
Prod için güvenli bir zaman çizelgesi:
- Preflight: sorgu şeklinin sabit olduğunu doğrulayın ve tabloya yeni bir indeks oluşturmak için yeterli boş disk olup olmadığını kontrol edin.
- Oluşturma:
CREATE INDEX CONCURRENTLY'yi ayrı bir oturumda net timeout ayarlarıyla çalıştırın. - Doğrulama:
ANALYZE tickets;çalıştırın ve planner'ın yeni indeksi kullandığını doğrulayın. - Temizlik: emin olduktan sonra artık gereksiz olan eski indeksi
DROP INDEX CONCURRENTLYile kaldırın.
Başarı şöyle görünür:
- Yönetici araması tipik müşteriler için saniyelerden onlarca milisaniyeye düşer.
- Oluşturma sırasında okuma ve yazmalar çalışmaya devam eder.
- Oluşturma sırasında CPU ve disk IO yükselir ama normal güvenlik sınırlarınız içinde kalır.
- Net before/after sayıları gösterebilirsiniz: sorgu süresi, taranan satır sayısı ve kilit geçmişi.
Hızlı kontrol listesi ve sonraki adımlar
İndeks çalışması küçük bir üretim sürümü gibi ele alındığında daha güvenlidir: hazırlayın, çalışırken izleyin, sonra sonucu doğrulayın ve cleanup yapın.
Başlamadan önce:
- Kilitler için sürpriz bir bekleme olmasın diye timeout'lar ayarlayın.
- Yeni indeks oluşturma için yeterli boş disk alanı olduğundan emin olun.
- Oluşturmaya yavaşlık yaratabilecek uzun süreli işlemleri arayın.
- Düşük trafik penceresi seçin ve "bitti"nin ne demek olduğunu tanımlayın.
- Şimdi geri alma planınızı yazın.
Çalışırken:
- Engellemeler ve kilit bekleme zincirlerini izleyin.
pg_stat_progress_create_indexile oluşturma ilerlemesini takip edin.- Uygulama semptomlarını izleyin: hata oranı, zaman aşımı ve tabloyla bağlı yavaş uç noktalar.
- Kilit beklemeleri artarsa veya kullanıcı zaman aşımı yükselirse iptal etmeye hazır olun.
- Ne olduğunu kaydedin: başlama zamanı, bitiş zamanı ve herhangi bir uyarı.
Bittiğinde indeksi doğrulayın, kilidin geçerli olduğunu onaylayın, bir veya iki ana sorguyu çalıştırıp plan ve zamanlamanın iyileştiğini görün ve ancak sonra eski indeksleri bloke etmeyecek şekilde kaldırın.
Bunu birden fazla kez yapıyorsanız, işi tekrarlanabilir bir teslimat adımına dönüştürün: küçük bir runbook, üretime benzer verilerle bir staging provası ve oluşturmayı izleyen net bir sahip atayın.
Eğer dahili araçlar veya yönetici panelleri AppMaster (appmaster.io) ile inşa ediyorsanız, veritabanı değişikliklerini indeks oluşturma gibi release kontrol listenizin bir parçası olarak ele almak yardımcı olur: ölçümlenmiş, izlenen ve hızlıca uygulanabilir bir rollback ile.
SSS
Kesinti genellikle tam bir hizmet kesintisi gibi görünmez; kilit beklemeleri olarak ortaya çıkar. Normal bir CREATE INDEX tüm oluşturma süresince yazmaları engelleyebilir; bu yüzden insert, update veya delete yapan istekler beklemeye ve ardından zaman aşımına uğramaya başlar; sayfalar takılır ve kuyruklar birikir.
CREATE INDEX CONCURRENTLY'yi, tablo gerçek trafik alıyorsa ve yazmaları durduramıyorsanız kullanın. Büyük veya yoğun tablolarda genellikle daha güvenli varsayılandır; ancak daha yavaş çalışır ve uzun süreli işlemler tarafından geciktirilebilir.
Hayır. Engellemeyi azaltır ama kilitsiz değildir. Başlangıçta ve bitişte kısa kilit pencereleri olur ve başka oturumlar uyumsuz kilitler tuttuğunda veya uzun süren işlemler son adımların tamamlanmasını engellediğinde işlemin beklemesine neden olabilir.
Çünkü prod genelde gerçekten sessiz değildir ve indeks oluşturma tablo boyutu, CPU ve disk IO nedeniyle beklediğinizden çok daha uzun sürebilir. Süre pencerenizin bitmesi durumunda ya riskli şekilde işin devamını beklemek ya da işlemi ortada iptal etmek zorunda kalırsınız.
Önce, bir transaction içinde olmadığınızdan emin olun; CREATE INDEX CONCURRENTLY transaction içinde çalışmaz. Ardından, yeni indeks ve geçici ek alan için yeterli boş diskiniz olduğundan emin olun ve gerekirse kilit alınamazsa hızlıca hata vermesi için kısa bir lock_timeout ayarlayın.
Yaygın bir başlangıç noktası aynı oturumda SET lock_timeout = '2s'; ve SET statement_timeout = '0'; kullanmaktır. Bu, kilitler için sonsuza dek beklemeyi önlerken, aşırı agresif bir statement timeout yüzünden oluşturmanın yarıda kesilmesini engeller.
Önce pg_stat_progress_create_index ile aşamanın ilerleyip ilerlemediğine bakın. İlerleme durduysa pg_stat_activity'e bakıp kilit beklemeleri ve özellikle eski snapshot tutuyor olabilecek uzun süreli işlemler için kontrol edin.
Yeni indeksi CREATE INDEX CONCURRENTLY ile ekleyin, planlayıcının onu kullanabildiğini doğrulayın (ve gerçek sorgu zamanlamasının iyileştiğini gözlemleyin), ve ancak sonra eski indeksi DROP INDEX CONCURRENTLY ile kaldırın. Bu “önce ekle, sonra kaldır” sırası olası geri dönüş için çalışan bir yedek tutar.
DROP INDEX CONCURRENTLY normal indeksler için genelde güvenlidir, ama başlangıç ve bitişte kısa kilitler gerektirir ve transaction bloğu içinde çalışmaz. İndeks bir PRIMARY KEY veya UNIQUE kısıtını destekliyorsa, genelde doğrudan silemezsiniz; önce constraint üzerinde ALTER TABLE ile değişiklik yapmanız gerekir ve bu daha güçlü kilitler gerektirebilir.
Oluşturan oturumu iptal edin, sonra geride geçersiz bir indeks kalıp kalmadığını kontrol edin. Eğer indisvalid = false ise, DROP INDEX CONCURRENTLY ile onu kaldırın ve eski indeksi koruyun; eğer eski indeksi zaten kaldırdıysanız, önceki durumu geri döndürmek için onu yeniden CREATE INDEX CONCURRENTLY ile oluşturun.


