PostgreSQL'de üretilen sütunlar ve tetikleyiciler: hangisini kullanmalı
PostgreSQL'de üretilen sütunlar ile tetikleyiciler arasında seçim: toplamlar, durumlar ve normalleştirilmiş değerler için doğru yaklaşımı seçin — yazma/okuma maliyetleri ve hata ayıklama farklarıyla.

Hangi sorunu türetilmiş alanlarla çözmeye çalışıyoruz?
Türev bir alan, diğer verilerden hesaplanabildiği için sakladığınız veya sunduğunuz bir değerdir. Aynı hesaplamayı her sorguda ve her ekranda tekrarlamak yerine kuralı bir kez tanımlayıp yeniden kullanırsınız.
Yaygın örnekleri kolayca hayal edebilirsiniz:
order_totalsatır öğelerinin toplamı eksi indirimler artı vergiye eşittir- tarih ve ödeme kayıtlarına dayalı olarak "paid" veya "overdue" gibi bir durum
- küçük harfe çevrilmiş bir e-posta, kırpılmış telefon numarası veya arama dostu bir isim gibi normalleştirilmiş bir değer
Takımlar türetilmiş alanları kullanır çünkü okuma tarafı daha basit ve daha tutarlı olur. Bir rapor doğrudan order_total seçebilir. Destek, karmaşık mantığı kopyalamadan durumlara göre filtreleyebilir. Paylaşılan bir kural ayrıca servisler, paneller ve arka plan işleri arasındaki küçük farklılıkları azaltır.
Ancak riskler gerçek: en büyüğü verinin bayatlamasıdır — girdiler değişir ama türetilmiş değer değişmez. Bir diğeri gizli mantıktır: kural bir tetikçi, fonksiyon veya eski bir migration içinde yaşar ve kimse varlığını hatırlamaz. Üçüncüsü çoğaltmadır: aynı veya neredeyse aynı kurallar birden fazla yerde olur ve zamanla ayrışır.
İşte bu yüzden PostgreSQL'de üretilen sütunlar ile tetikleyiciler arasındaki seçim önemlidir. Sadece değeri nasıl hesaplayacağınızı seçmiyorsunuz; kuralın nerede duracağını, yazmalardaki maliyetini ve yanlış bir sayıyı nedenine kadar izlemeyi de seçiyorsunuz.
Bu makalenin geri kalanı üç pratik açıya bakıyor: sürdürülebilirlik (insanlar anlayıp değiştirebilir mi), sorgu hızı (okumalar, yazmalar, indeksler) ve hata ayıklama (değer neden yanlış, nasıl bulunur).
Üretilen sütunlar ve tetikleyiciler: basit tanımlar
İnsanlar PostgreSQL'de üretilen sütunları ve tetikleyicileri karşılaştırırken aslında türetilmiş bir değerin nerede olması gerektiğini seçiyorlar: tablo tanımının içinde mi yoksa veri değiştiğinde çalışan prosedürel mantığın içinde mi.
Üretilen sütunlar
Üretilen sütun, aynı satırdaki diğer sütunlardan hesaplanan gerçek bir tablo sütunudur. PostgreSQL'de üretilen sütunlar saklanır (veritabanı hesaplanan sonucu diske kaydeder) ve referans alınan sütunlar değiştiğinde otomatik olarak güncel tutulur.
Üretilen sütun sorgulama ve indeksleme için normal bir sütun gibi davranır, ama doğrudan ona yazmazsınız. Saklanmayan bir hesaplanmış değere ihtiyacınız varsa PostgreSQL genellikle bir view (veya sorgu ifadesi) kullanır.
Tetikleyiciler
Tetikleyici, INSERT, UPDATE veya DELETE gibi olaylarda çalışan mantıktır. Tetikleyiciler değişiklikten ÖNCE (BEFORE) veya SONRA (AFTER) çalışabilir ve satır başına veya ifade başına çalışabilir.
Tetikleyiciler kod olarak çalıştığı için basit matematikten fazlasını yapabilirler. Diğer sütunları güncelleyebilir, başka tablolara yazabilir, özel kurallar uygulayabilir ve birden çok satır üzerindeki değişikliklere tepki verebilirler.
Farkı hatırlamanın faydalı bir yolu:
- Üretilen sütunlar öngörülebilir, satır düzeyindeki hesaplamalara uyar (totaller, normalleştirilmiş metin, basit bayraklar) ve her zaman mevcut satırla eşleşmelidir.
- Tetikleyiciler zamanlama, yan etkiler veya çapraz satır ve çapraz tablo mantığı içeren kurallara uyar (durum geçişleri, denetim günlükleri, stok ayarlamaları).
Bir not: yerleşik kısıtlar (NOT NULL, CHECK, UNIQUE, foreign keys) açık ve deklaratif ama sınırlıdır. Örneğin, bir CHECK kısıtı alt sorgu yoluyla diğer satırlara bağlı olamaz. Bir kural mevcut satırdan fazlasına bağlıysa genellikle tetikleyiciler veya bir yeniden tasarımla karşılaşırsınız.
AppMaster gibi görsel bir araçla inşa ediyorsanız, bu fark "veri modeli formülü" tarzı kurallarla kaydın değiştiğinde çalışan "iş süreci" kuralları arasında güzelce eşleşir.
Sürdürülebilirlik: hangisi zamanla okunabilir kalır?
Ana sürdürülebilirlik farkı kuralın nerede yaşadığıdır.
Üretilen bir sütun mantığı veri tanımının yanında tutar. Birisi tablo şemasını açtığında değeri üreten ifadeyi görebilir.
Tetikleyicilerde kural tetikçi fonksiyonuna taşınır. Ayrıca hangi tabloların ve olayların onu çağırdığını bilmeniz gerekir. Aylar sonra "okunabilirlik" sıklıkla şu anlama gelir: birisi veritabanında dolaşmadan kuralı anlayabilir mi? Üretilen sütunlar genellikle kazanır çünkü tanım tek yerde görünür ve daha az hareketli parçaya sahiptir.
Tetikleyiciler yine de temiz kalabilir; fonksiyonu küçük ve odaklı tutarsanız. Sorun, bir tetikçi fonksiyonu alakasız kurallar için bir depo haline geldiğinde başlar. Çalışabilir ama üzerinde düşünmesi zor ve değiştirmesi riskli hale gelir.
Değişiklikler başka bir baskı noktasıdır. Üretilen sütunlarla güncellemeler tipik olarak tek bir ifadeyi değiştiren bir migration'dır. Bu, gözden geçirmek ve geri almak için basittir. Tetikleyiciler genellikle fonksiyon gövdesi ve tetik tanımı boyunca koordine değişiklikler, ayrıca backfill ve güvenlik kontrolleri gerektirir.
Kuralların zaman içinde keşfedilebilir kalması için birkaç alışkanlık yardımcı olur:
- Sütunları, tetikleyicileri ve fonksiyonları uyguladıkları iş kuralının adıyla adlandırın.
- Yalnızca matematiği değil niyeti açıklayan kısa yorumlar ekleyin.
- Tetikleyici fonksiyonlarını küçük tutun (bir kural, bir tablo).
- Migration'ları versiyon kontrolünde tutun ve incelemeyi zorunlu kılın.
- Düzenli olarak şemadaki tüm tetikleyicileri listeleyin ve artık ihtiyaç duymadıklarınızı kaldırın.
Aynı fikir AppMaster'da da geçerli: hızlıca görebileceğiniz ve denetleyebileceğiniz kuralları tercih edin ve yazma zamanındaki "gizli" mantığı en aza indirin.
Sorgu hızı: okuma, yazma ve indekslerde ne değişir?
Performans sorusu temelde şudur: maliyeti okumalarda mı yoksa yazmalarda mı ödemek istiyorsunuz?
Üretilen bir sütun satır yazıldığında hesaplanır ve sonra saklanır. Okumalar hızlıdır çünkü değer zaten oradadır. Takas, her INSERT ve değerin girdilerini etkileyen her UPDATE işleminin ayrıca üretilen değeri hesaplaması gerektiğidir.
Tetikleyici tabanlı yaklaşım genellikle türetilmiş değeri normal bir sütunda saklar ve bir tetikçiyle güncel tutar. Okumalar yine hızlıdır ama yazmalar daha yavaş ve daha az öngörülebilir olabilir. Tetikleyiciler satır başına ekstra iş ekler ve toplu güncellemelerde yük barizleşir.
İndeksleme, saklanan türetilmiş değerlerin en çok önemli olduğu yerdir. Sık sık türetilmiş bir alanla (normalize e-posta, total, durum kodu) filtreliyorsanız veya sıralıyorsanız, bir indeks yavaş taramayı hızlı bir aramaya çevirebilir. Üretilen sütunlarla üretilen değeri doğrudan indeksleyebilirsiniz. Tetikleyicilerle de bakımı yapılan sütunu indeksleyebilirsiniz ama tetikçinin onu doğru tuttuğuna güveniyorsunuz.
Değeri sorgu içinde hesaplıyorsanız (örneğin WHERE içinde), birçok satır için tekrar hesaplamayı önlemek üzere bir ifade indeksi gerekebilir.
Toplu ithalatlar ve büyük güncellemeler yaygın darboğazlardır:
- Üretilen sütunlar her etkilenen satıra tutarlı bir hesaplama maliyeti ekler.
- Tetikleyiciler hesaplama maliyetine ek olarak tetikleyici üstlüğü ekler ve kötü yazılmış mantık bu maliyeti çarpabilir.
- Büyük güncellemeler tetikçi işinin darboğaz olmasına neden olabilir.
Pratik bir seçim yöntemi gerçek sıcak noktaları aramaktır. Eğer tablo okuma ağırlıklıysa ve türetilmiş alan filtrelerde sık kullanılıyorsa, saklanan değerler (üretilen veya tetikçi ile korunan) ve bir indeks genellikle kazanır. Yazma ağırlıklıysa (olaylar, günlükler), her satıra ek iş eklemeye dikkat edin.
Hata ayıklama: yanlış değerin kaynağını bulmak
Türev bir alan yanlışsa, hatayı tekrarlanabilir hale getirerek başlayın. Hatalı değeri üreten tam satır durumunu yakalayın, sonra yan etkilerle uğraşmamak için aynı INSERT veya UPDATE'i temiz bir işlemde yeniden çalıştırın.
Hızlı bir daraltma şu soruyu sormaktır: değer deterministik bir ifadeden mi geldi, yoksa yazma zamanlı bir mantıktan mı?
Üretilen sütunlar genellikle tutarlı şekillerde başarısız olur. İfade yanlışsa aynı girdiler için her zaman yanlıştır. Yaygın sürprizler NULL işlemi (bir NULL tüm hesaplamayı NULL yapabilir), örtük dönüşümler (text'ten numeric'e) ve sıfıra bölme gibi kenar durumlardır. Ortamlar arasında sonuçlar farklıysa collation, eklentiler veya ifadeyi değiştiren şema değişikliklerini kontrol edin.
Tetikleyiciler daha karışık şekilde başarısız olur çünkü zamanlama ve bağlama bağlıdırlar. Bir tetikleyici beklediğinizde çalışmayabilir (yanlış olay, yanlış tablo, eksik WHEN koşulu). Zincir tetikleyicilerle birden fazla kez çalışabilir. Hatalar ayrıca oturum ayarlarından, search_path'ten veya ortamlarda farklı olan diğer tablolardan kaynaklanabilir.
Bir türetilmiş değer yanlış görünüyorsa bu kontrol listesi genellikle nedeni bulmak için yeterlidir:
- Hatalı değeri üreten minimal INSERT/UPDATE ile yeniden üretilmesini sağlayın.
- Girdileri doğrulamak için türetilmiş sütunun yanında ham giriş sütunlarını seçin.
- Üretilen sütunlar için ifadeyi bir SELECT içinde çalıştırıp karşılaştırın.
- Tetikleyiciler için geçici olarak RAISE LOG bildirimleri ekleyin veya bir debug tablosuna yazın.
- Ortamlar arasındaki şema ve tetikleyici tanımlarını karşılaştırın.
Bilinen sonuçlara sahip küçük test veri setleri sürprizleri azaltır. Örneğin iki sipariş oluşturun: biri NULL indirimle, diğeri 0 indirimle ve sonra toplamların beklendiği gibi davrandığını doğrulayın. Durum geçişleri için de aynı testi yapın ve yalnızca amaçlanan güncellemelerde gerçekleştiğini doğrulayın.
Nasıl seçilir: karar yolu
En iyi seçim genellikle birkaç pratik soruyu yanıtladığınızda netleşir.
Adım 1–3: önce doğruluk, sonra iş yükü
Aşağıyı sırayla ele alın:
- Değer her zaman diğer sütunlarla eşleşmeli mi, istisna olmadan? Evetse veritabanında zorlayın; uygulamada ayarlayıp doğru kalacağını ummayın.
- Formül deterministik mi ve sadece aynı satırdaki sütunlara mı dayanıyor (örneğin
lower(email)veyaprice * quantity)? Evetse üretilen sütun genellikle en temiz seçenektir. - Bu değeri çoğunlukla okuyor musunuz (filtreleme, sıralama, raporlama) yoksa çoğunlukla yazıyor musunuz (çok sayıda insert/update)? Üretilen sütunlar maliyeti yazmalara kaydırır, bu yüzden yazma ağırlıklı tablolar bunu daha hızlı hissedebilir.
Kural diğer satırlara, diğer tablolara veya zamana duyarlı mantığa bağlıysa (örneğin "ödeme yoksa 7 gün sonra overdue yap"), tetikleyici genellikle daha iyi bir uyum sağlar çünkü daha zengin mantık çalıştırabilir.
Adım 4–6: indeksleme, test etme ve basit tutma
Şimdi değerin nasıl kullanılacağını ve doğrulanacağını kararlaştırın:
- Sıkça filtreleyecek veya sıralayacak mısınız? Evetse bir indeks planlayın ve yaklaşımınızın bunu temizce desteklediğinden emin olun.
- Değişiklikleri nasıl test edip gözlemleyeceksiniz? Üretilen sütunlar kuralın tek bir ifadede yaşaması sayesinde daha kolay anlaşılır. Tetikleyiciler hedeflenmiş testler ve net günlükleme gerektirir çünkü değer "yan tarafta" değişir.
- Kısıtları karşılayan en basit seçeneği seçin. Bir üretilen sütun işe yarıyorsa genellikle bakım açısından daha kolaydır. Çapraz satır kuralları, çok adımlı durum değişiklikleri veya yan etkiler gerekiyorsa tetikleyiciyi kabul edin ama onu küçük ve iyi adlandırılmış tutun.
Bir sağlam sezgi kontrolü: kuralı bir cümlede açıklayabiliyorsanız ve sadece mevcut satırı kullanıyorsa üretilen sütunla başlayın. Bir iş akışını tarif ediyorsanız muhtemelen tetikleyici bölgesindesiniz.
Totaller ve normalleştirilmiş değerler için üretilen sütunları kullanma
Üretilen sütunlar, değer tamamen aynı satırdaki diğer sütunlardan türetiliyorsa ve kural sabitse iyi çalışır. Formül tablo tanımında yaşar ve PostgreSQL bunu tutarlı kılar.
Tipik örnekler normalleştirilmiş değerler (küçük harfe çevrilmiş, kırpılmış anahtarlar) ve basit toplamlar (subtotal + tax - discount) içerir. Örneğin bir orders tablosu subtotal, tax ve discount saklayabilir ve total'ı üretilen sütun olarak sunabilir, böylece her sorgu aynı sayıyı görür.
İfadeyi yazarken sıkıcı ve savunmacı tutun:
- Toplamların beklenmedik şekilde NULL olmaması için
COALESCEile NULL'ları ele alın. - Taban tipleri karışmasın diye kasıtlı olarak cast edin.
- Yuvarlamayı tek bir yerde yapın ve yuvarlama kuralını ifadeye dokumente edin.
- Zaman dilimi ve metin kurallarını açıkça belirtin (küçük harfe çevirme, kırpma, boşlukları değiştirme).
- Bir büyük formül yerine birkaç yardımcı sütun tercih edin.
İndeksleme ancak gerçekten değere göre filtrelediğiniz veya join yaptığınızda fayda sağlar. total üzerinde indekslemek eğer asla total ile arama yapmıyorsanız genellikle boşa harcamadır. email_normalized gibi bir anahtarın indexlenmesi genellikle değerlidir.
Şema değişiklikleri önemlidir çünkü üretilen ifadeler diğer sütunlara bağlıdır. Bir sütun yeniden adlandırmak veya tipini değiştirmek ifadeyi kırabilir; bu iyi bir hata şeklidir çünkü migration sırasında yanlış veri yazmak yerine hatayı görürsünüz.
Formül dallanmaya başlarsa (birçok CASE dalı, çok sayıda iş kuralı), bunu bir sinyal olarak değerlendirin. Parçaları ayrı sütunlara bölün veya kuralı okunabilir ve test edilebilir tutmak için yaklaşımı değiştirin. AppMaster'da PostgreSQL şemasını modelliyorsanız, üretilen sütunlar kuralın bir satırda kolayca görüldüğü ve açıklanabildiği durumlarda en iyi çalışır.
Durumlar ve çapraz satır kuralları için tetikleyicileri kullanma
Bir alan mevcut satırdan fazlasına bağlıysa tetikleyiciler genellikle doğru araçtır. Durum alanları yaygın bir örnektir: bir sipariş en az bir başarılı ödeme olduğunda "paid" olur veya bir bilet tüm görevler tamamlandığında "resolved" olur. Bu tür kurallar satırlar veya tablolar arasıdır, üretilen sütunların erişemeyeceği şeylerdir.
İyi bir tetikleyici küçük ve sıkıcıdır. Ona ikinci bir uygulama katmanı gibi davranmayın; koruyucu bir korkuluk gibi düşünün.
Tetikleyicileri öngörülebilir tutun
Gizli yazmalar tetikleyicileri zor yaşanır kılar. Basit bir konvansiyon diğer geliştiricilerin neler olduğunu görmesini kolaylaştırır:
- Bir tetikleyici bir amaç için olsun (durum güncellemeleri; total + denetim + bildirim gibi karışık işler olmasın).
- Açık isimler kullanın (ör.
trg_orders_set_status_on_payment). - Zamanlamayı tutarlı yapın: gelen veriyi düzeltmek için BEFORE, kaydedilmiş satırlara tepki için AFTER kullanın.
- Mantığı tek bir fonksiyonda tutun; bir oturuşta okunabilecek kadar kısa olsun.
Gerçekçi bir akış şöyle görünür: payments succeeded olarak güncellenir. payments üzerinde bir AFTER UPDATE tetikleyicisi, siparişin en az bir succeeded ödemesi varsa ve açık bakiye yoksa orders.status'ı paid yapar.
Kenar durumları için plan yapma
Tetikleyiciler toplu değişikliklerde farklı davranır. Commit etmeden önce backfill ve yeniden çalıştırmaları nasıl ele alacağınızı kararlaştırın. Mevcut veriler için durumu yeniden hesaplayacak tek seferlik bir SQL işi genellikle satır satır tetikleyici çalıştırmaktan daha açıktır. Ayrıca güvenli bir "yeniden işleme" yolu tanımlamak (örneğin tek bir sipariş için durumu yeniden hesaplayan saklı prosedür) faydalıdır. Aynı işlemi yeniden çalıştırmak durumları yanlış çevirmemeli; idempotent olmayı unutmayın.
Son olarak, bir kısıt veya uygulama mantığının daha iyi bir uyum sağlayıp sağlamadığını kontrol edin. Basit izin verilen değerler için kısıtlar daha nettir. AppMaster gibi araçlarda birçok iş akışı İş Sürecinde daha görünür tutulur, veritabanı tetikçisi ise dar bir güvenlik ağı olarak kalır.
Kaçınılması gereken yaygın hatalar ve tuzaklar
Türev alanlarla ilgili birçok acı kendi yaptığımız seçimlerden kaynaklanır. En büyük tuzak varsayılan olarak daha karmaşık aracı seçmektir. Önce şunu sorun: bu yalnızca aynı satırın saf bir ifadesi olarak ifade edilebilir mi? Evetse üretilen sütun genellikle daha sakin bir seçenektir.
Diğer yaygın hata, tetikleyicilerin yavaş yavaş ikinci bir uygulama katmanı haline gelmesine izin vermektir. Başlangıçta "sadece durumu ayarla" ile başlar, sonra fiyatlandırma kuralları, istisnalar ve özel durumlar büyür. Testler olmadan küçük düzenlemeler eski davranışı kırabilir ve fark edilmeden hatalara yol açabilir.
Sık görülen tuzaklar:
- Bir satır başı değer için üretilen sütun daha net ve kendini belgeleyenken tetikleyici kullanmak.
- Bir yerde (checkout) saklanan toplamı güncelleyip başka bir yerde (admin düzenlemeleri, importlar, backfill) unutmak.
- Eşzamanlılığı göz ardı etmek: iki işlem aynı sipariş satırlarını güncelliyor ve tetikleyiciniz değişikliği üzerine yazıyor veya iki kez uyguluyor.
- Her türetilmiş alanı "olursa" indekleme, özellikle sık değişen değerler için.
- Neredeyse hiç aranmayan normalize bir string gibi okumada hesaplanabilecek bir şeyi saklamak.
Küçük bir örnek: order_total_cents saklıyorsunuz ve destek ekibinin satırları ayarlamasına izin veriyorsunuz. Eğer destek aracı satırları güncelliyor ama toplamı değiştirmiyorsa, toplam bayatlar. Daha sonra tetikleyici eklerseniz tarihsel satırları ve kısmi iadeler gibi kenar durumları ele almanız gerekir.
AppMaster ile inşa ediyorsanız aynı kural geçerlidir: iş kurallarını tek bir yerde görünür tutun. "Türetilmiş değer güncellemelerini" birden çok akışa yaymaktan kaçının.
Commit etmeden önce hızlı kontroller
PostgreSQL'de üretilen sütunlar ile tetikleyiciler arasında seçim yapmadan önce kuralı hızlıca stres test edin.
Önce kuralın neye bağlı olduğunu sorun. Eğer sadece aynı satırdaki sütunlardan hesaplanabiliyorsa (normalize telefon numarası, küçük harf e-posta, line_total = qty * price), üretilen sütun genellikle daha kolay yaşanır çünkü mantık tablo yanında durur.
Kural diğer satırlara veya tablolara bağlıysa (son ödeme geldiğinde değişen sipariş durumu, son etkinliğe dayalı hesap bayrağı), tetikleyici bölgesindesiniz veya sorguda hesaplamayı tercih etmelisiniz.
Kısa kontrol listesi:
- Değer sadece mevcut satırdan mı türetilebilir, lookup gerektirmeden?
- Sıkça filtreleyip sıralayacak mısınız?
- Kuralı değiştirdikten sonra tarihsel verileri yeniden hesaplamanız gerekecek mi?
- Bir geliştirici tanımı bulup 2 dakikadan kısa sürede açıklayabilir mi?
- Kuralın çalıştığını kanıtlayan küçük bir örnek veri kümeniz var mı?
Sonra operasyonları düşünün. Toplu güncellemeler, importlar ve backfill'ler tetikleyicilerin sürpriz yaptığı yerlerdir. Tetikleyiciler satır başına tetiklenir; hatalar yavaş yükler, kilit beklemeleri veya yarım güncellenmiş türetilmiş değerler olarak ortaya çıkar.
Pratik bir test basittir: 10.000 satırı staging tablosuna yükleyin, usual import işleminizi çalıştırın ve neyin hesaplandığını doğrulayın. Ardından bir ana giriş sütununu güncelleyin ve türetilmiş değerin doğru kaldığını onaylayın.
AppMaster ile bir uygulama inşa ediyorsanız aynı prensip geçerlidir: basit satır-temelli kuralları veritabanında üretilen sütunlar olarak yakın tutun; çok adımlı, çapraz tablo durum değişikliklerini test edebileceğiniz tek bir yerde toplayın.
Gerçekçi bir örnek: siparişler, toplamlar ve bir durum alanı
Basit bir mağaza hayal edin. orders tablonuzda items_subtotal, tax, total ve bir payment_status var. Amaç, herkesin hızlıca şu soruya cevap bulabilmesi: bu sipariş neden hâlâ ödenmemiş?
Seçenek A: toplamlar için üretilen sütunlar, durum düz olarak saklanır
Aynı satırdaki değerlere dayanan para hesapları için üretilen sütunlar temiz bir uyum sağlar. items_subtotal ve tax normal sütunlar olarak saklanır, sonra total items_subtotal + tax gibi bir üretilen sütun olarak tanımlanır. Bu kuralı tablo üzerinde görünür tutar ve gizli yazma mantığından kaçınır.
payment_status için bunu uygulamanın ödeme oluştururken ayarlaması yeterli olabilir. Bu daha otomatik olmasa da, satırı okuduğunuzda akla yatan ve anlaşılırdır.
Seçenek B: ödemeler tarafından tetiklenen durum değişiklikleri için tetikleyiciler
Şimdi bir payments tablosu ekleyin. Durum artık sadece orders satırına bağlı değildir. Başarılı ödemeler, iadeler ve chargeback'ler gibi ilgili satırlar durumu etkiler. Bir payments tetikleyicisi bir ödeme değiştiğinde orders.payment_status'ı güncelleyebilir.
Bu yolu seçerseniz bir backfill planlayın: mevcut siparişlerin payment_status'ını yeniden hesaplayan tek seferlik bir script ve hata olursa tekrar çalıştırabileceğiniz tekrar edilebilir bir iş.
Destek "neden bu sipariş ödenmemiş?" araştırmasına gittiğinde, Seçenek A onları genellikle uygulamaya ve onun denetim izine yönlendirir. Seçenek B ise veritabanı mantığına da bakmalarını gerektirir: tetikleyici çalıştı mı, hata verdi mi, bir koşul nedeniyle atlandı mı?
Yayın sonrası izlemeniz gereken birkaç sinyal:
paymentsüzerinde yavaş güncellemeler (tetikleyiciler yazmalara iş ekler)ordersüzerinde beklenmedik güncellemeler (durumun beklenenden sık değişmesi)totaldoğru amastatusyanlış olan satırlar (mantığın farklı yerlerde olması)- yoğun ödeme trafiğinde deadlock veya kilit beklemeleri
Sonraki adımlar: en basit yaklaşımı seçin ve kuralları görünür tutun
SQL'e dokunmadan önce kuralı düz bir dille yazın. "Order total line itemların toplamına eksi indirim" gibi bir ifade nettir. "Status, paid_at setliyse ve bakiye sıfırsa paid olur" nettir. Bunu bir veya iki cümlede açıklayamıyorsanız, muhtemelen gözden geçirilip test edilebileceği bir yerde olmalı, veritabanına gömülmemelidir.
Takılırsanız bunu bir deney gibi ele alın. Tablonun küçük bir kopyasını oluşturun, gerçek hayata benzeyen küçük bir veri seti yükleyin ve her iki yaklaşımı da deneyin. Gerçekten önemsediğiniz şeyleri karşılaştırın: okuma sorguları, yazma hızı, indeks kullanımı ve daha sonra anlamanın ne kadar kolay olduğu.
Kısa karar kontrol listesi:
- Her iki seçeneğin prototipini oluşturun ve yaygın okumalarda sorgu planlarını inceleyin.
- Bir yazma-ağırlıklı test (importlar, güncellemeler) çalıştırarak değerleri güncel tutmanın maliyetini görün.
- Backfill, NULL, yuvarlama ve kenar durumları kapsayan küçük bir test scripti ekleyin.
- Uzun vadede mantığın kimde olacağını (DBA, backend, ürün) kararlaştırın ve bu seçimi dokümante edin.
Eğer dahili bir araç veya portal inşa ediyorsanız görünürlük, doğruluk kadar önemlidir. AppMaster (appmaster.io) kullanan ekipler genellikle basit, satır-temelli kuralları veri modeline yakın tutar ve çok adımlı değişiklikleri Business Process'e koyar, böylece mantık incelemelerde okunur kalır.
Son olarak zaman kazandıran bir şey: gerçeğin nerede durduğunu (tablo, tetikçi veya uygulama mantığı) ve güvenli bir şekilde nasıl yeniden hesaplanacağını dokümante edin.
SSS
Türev alanlar, birçok sorgu ve ekran aynı değere ihtiyaç duyduğunda ve tek bir paylaşılmış tanım istediğinizde kullanışlıdır. Genellikle normalize anahtarlar, basit toplamlar veya tutarlı bir bayrak gibi sıkça filtrelenen, sıralanan veya görüntülenen değerler için faydalıdır.
Değer yalnızca aynı satırdaki diğer sütunların fonksiyonuysa ve her zaman onlarla eşleşmesi gerekiyorsa generated column seçin. Bu, kuralı tablo şemasında görünür tutar ve yazma zamanında gizli kod yollarından kaçınır.
Kural diğer satırlara veya tablolara bağlıysa, ya da ilgili kaydı güncelleme veya denetim kaydı yazma gibi yan etkilere ihtiyacınız varsa tetikleyici daha uygundur. Zamanlama ve bağlamın önemli olduğu iş akışı tarzı geçişler için de tetikleyiciler uygundur.
Üretilen sütunlar yalnızca aynı satırdaki sütunları referans alabilir; bu yüzden satır öğelerini toplamak gibi alt satırları toplamak gerekirse üretilen sütun kullanamazsınız. Bu durumda genellikle sorguda hesaplama yapar, tetikleyicilerle korur ya da ihtiyaç duyulan girişlerin aynı satırda olduğu bir şema yeniden tasarımı düşünürsünüz.
Üretilen sütun, yazma zamanında hesaplanıp saklandığı için okuma hızlıdır ve indekslemeye uygun hale gelir; ancak ekleme ve güncelleme işlemleri hesaplama maliyetini taşır. Tetikleyiciler de işi yazma tarafına kaydırır, fakat mantık karmaşıksa veya tetik zincirleri varsa daha yavaş ve öngörülemez olabilir.
Eğer sıkça filtrelediğiniz, join yaptığınız veya sıraladığınız bir türetilmiş değer varsa, örneğin normalize edilmiş bir e-posta veya durum kodu, indeksi düşünün. Sadece değeri gösteriyorsanız ve neredeyse hiç aramıyorsanız, indeks yazma maliyetini artırır ama fayda sağlamaz.
Üretilen sütunlar genellikle daha kolay korunur çünkü mantık tablo tanımında yer alır ve insanlar doğal olarak oraya bakar. Tetikleyiciler de bakımı kolay kalabilir, ancak her tetikleyicinin dar bir amacı, net bir adı ve kolayca gözden geçirilebilen küçük bir fonksiyonu olmalıdır.
Üretilen sütunlarda en yaygın sorunlar NULL işlemi, tür dönüşümleri ve beklenmeyen yuvarlama kurallarıdır. Tetikleyicilerde ise tetikleyicinin tetiklenmemesi, birden fazla kez tetiklenmesi, beklenmeyen sıra veya ortam farklarından kaynaklanan hatalar yaygındır.
Kötü değeri üreten tam insert veya update'i tekrarlayarak başlayın, sonra giriş sütunlarını türetilmiş sütunun yanında seçin. Üretilen sütun için aynı ifadeyi bir SELECT içinde çalıştırıp karşılaştırın; tetikleyici için tetik ve fonksiyon tanımlarını inceleyin ve ne zaman/ nasıl çalıştığını doğrulamak için basit günlüklemeler ekleyin.
Kuralı tek bir cümlede söyleyebiliyorsanız ve sadece mevcut satırı kullanıyorsa, üretilen sütun güçlü bir varsayımdır. Bir iş akışını veya ilişkili kayıtları referans ediyorsanız tetikleyici veya sorguda hesaplama daha uygundur; mantığı tek bir yerde tutup test edilebilir kılın.


