Tetikleyicinin MySQL'de Saklı Yordam Performansı


11

Burada DBA.StackExchange'te bir yayın ( Kayıtlarda bir revizyon numarasını korumak için tetikleyiciler için en iyi uygulamalar nelerdir? ) MySQL'deki performansla ilgili ilginç bir soru (en azından benim için ilginç) ortaya çıkardı.

Bağlam, güncellenen her satır için bir tabloya kayıt eklemek istiyoruz. Satır güncellenmeden önce, önceki bir değeri saklamak ve ardından sütunlardan birini ("sürüm" sütunu) artırmak istiyoruz.

Bunu bir tetikleyici içinde yaparsak, iyi çalışır. MySQL için, tetikleyiciler satır satırdır , bu yüzden kolay bir çözüm olacaktır. Şu anda tablodaki verileri seçin, günlük tablosuna ekleyin ve yeni verilerdeki "sürüm" sütununu güncelleyin.

Ancak, bu mantığı saklı bir prosedüre taşımak mümkündür. Bunu yaparsanız, eki gerçekleştirir ve ardından tablodaki "sürüm" sütununu artırırsınız. Her şey temel alınır.

Peki, bu eki gerçekleştirmek söz konusu olduğunda, bu set tabanlı saklı yordam yaklaşımını veya tetikleyici tabanlı bir yaklaşımı kullanmak için daha mı performans gösterir?

Bu soru MySQL içindir (çünkü satır satır tetikleyicileri olduğundan), diğer satır satır tetikleyicili DBMS'lere de uygulanabilir.


1
Sürüm mantığını saklı bir prosedüre itme konusunda akılda tutulması gereken bir şey - birisi, bir şekilde doğrudan denetim mekanizmanızı atlayarak masaya yazdığında ne kadar kambur olacaksınız?
billinkc

Katılıyorum. Ancak ölçeğin diğer ucunda, bazı durumlarda bu günlük kaydını kasıtlı olarak atlamak isteyebilirsiniz. Tabii ki, bu tamamen farklı bir soru . Performansın etkilerini gerçekten merak ediyorum.
Richard

Yanıtlar:


7

Basitlik adına, tetikleyiciler veritabanı değişikliklerinin her türlü izlemesini gerçekleştirmenin yoludur. Ancak, tetikleyicileri kullandığınızda kaputun altında neler olduğunu bilmeniz gerekir.

Göre MySQL Saklı Yordam Programlama kafasının altına, sayfa 256 "Tetikleyici Asma" şu şöyle der:

Zorunlu olarak, tetikleyicilerin uygulandıkları DML ifadesine ek yük getirdiğini hatırlamak önemlidir. gerçek ek yük miktarı tetikleyicinin doğasına bağlı olacaktır, ancak --- tüm MySQL tetikleyicilerinin HER SATIR İÇİN yürüttüğü gibi --- ek yük çok sayıda satırı işleyen ifadeler için hızlı bir şekilde birikebilir. Bu nedenle, pahalı SQL deyimlerini veya yordamsal kodları tetikleyicilere yerleştirmekten kaçınmalısınız.

Tetikleyici ek yükünün genişletilmiş açıklaması 529-531. Sayfalarda verilmiştir. Bu bölümdeki sonuç noktası aşağıdakileri belirtir:

Buradaki ders şudur: tetikleme kodu bir DML ifadesinden etkilenen her satır için bir kez çalışacağından, tetikleyici kolayca DML performansında en önemli faktör haline gelebilir. Tetikleyici gövdenin içindeki kodun olabildiğince hafif olması ve özellikle de tetikleyicideki SQL ifadelerinin mümkün olduğunca dizinler tarafından desteklenmesi gerekir.

Tetikleyicileri kullanırken kitapta belirtilmeyen başka bir faktördür: Denetim günlüğü oluşturma söz konusu olduğunda, lütfen verileri ne giriş yaptığınıza dikkat edin. Bunu söylüyorum, çünkü bir MyISAM tablosuna giriş yapmayı seçerseniz, bir MyISAM tablosuna her INSERT, INSERT sırasında tam bir masa kilidi üretir. Bu, yüksek trafikli, yüksek işlem ortamlarında ciddi bir darboğaz haline gelebilir. Ayrıca, tetikleyici bir InnoDB tablosuna karşı ise ve MyISAM'deki değişiklikleri tetikleyiciden kaydederseniz, bu işlem geri alınamayan ACID uyumluluğunu gizlice devre dışı bırakır (yani, blok işlemlerini otomatik tamamlama davranışına indirir).

InnoDB tablolarında tetikleyicileri kullanırken ve günlük değişiklikleri

  • Giriş yaptığınız tablo da InnoDB
  • Otomatik taahhüdünüz kapalı
  • İŞLEMİ BAŞLATIN ... COMMIT / ROLLBACK bloklarını iyice ayarlayın

Bu şekilde, denetim günlükleri ana tablolarda olduğu gibi COMMIT / ROLLBACK'ten yararlanabilir.

Saklı yordamları kullanma konusunda, izlenen tabloya karşı DML'nin her noktasında saklı yordamı titizlikle çağırmanız gerekir. On binlerce satır uygulama kodu karşısında kaydedilen değişiklikleri kolayca gözden kaçırabilirsiniz. Böyle bir kodu bir tetikleyiciye yerleştirmek, tüm bu DML ifadelerini bulmayı ortadan kaldırır.

UYARI

Tetiğin ne kadar karmaşık olduğuna bağlı olarak, yine de bir darboğaz olabilir. Denetim günlüğündeki darboğazları azaltmak istiyorsanız, yapabileceğiniz bir şey vardır. Ancak, küçük bir altyapı değişikliği gerektirecektir.

Emtia donanımını kullanarak iki DB sunucusu daha oluşturun

Bu, denetim günlüğü nedeniyle ana veritabanındaki (MD) yazma G / Ç'sini azaltmak için sunucu oluşturur. Bunu nasıl başarabileceğiniz aşağıda açıklanmıştır:

Adım 01) Ana veritabanındaki ikili günlük kaydını açın.

Adım 02) Ucuz bir sunucu kullanarak, MySQL'i (MD ile aynı sürüm) ikili günlük kaydı etkin olarak kurun. Bu DM olacak. MD'den DM'ye çoğaltma ayarı.

Adım 03) İkinci bir ucuz sunucu kullanarak, MySQL'i (MD ile aynı sürüm) ikili günlük kaydı devre dışı olarak ayarlayın. Her denetim tablosunu --replicate-do-table kullanacak şekilde ayarlayın . Bu AU olacak. DM'den AU'ya çoğaltma ayarı.

Adım 04) mysqldump MD tablo yapıları ve DM ve AU yükleyin.

Adım 05) MD'deki tüm denetim tablolarını BLACKHOLE depolama motorunu kullanmak için dönüştürün

Adım 06) BLACKHOLE depolama motorunu kullanmak için DM ve AU'daki tüm tabloları dönüştürün

Adım 07) AU'daki tüm denetim tablolarını MyISAM depolama motorunu kullanmak için dönüştürün

Bittiğinde

  • DM, MD'den çoğalır ve yalnızca ikili günlüğüne kayıt yapar
  • İle --replicate-do-tablo tüm denetim tablolarda filtresi, AU DM çoğaltılacak olacak

Bu, denetim bilgilerini ayrı bir DB sunucusunda depolamak ve MD'nin normalde sahip olacağı yazma G / Ç bozulmasını azaltmaktır.


Muazzam cevap +++ 1
b_dubb

1

İşte bu güncellemeyi toplu olarak gerçekleştirmek için bir yaklaşım.

Bu örnek için

  • table_A'nın PRIMARY KEY kimliği var
  • PRIMARY KEY olarak sadece id ile table_A_Keys2Update adlı bir tablo oluşturursunuz
  • Table_A_Keys2Update withs kimliklerini table_A'dan güncellersiniz.

Table_A_Keys2Update oluşturmak için aşağıdakileri yapın:

CREATE TABLE table_A_Keys2Update SELECT id FROM table_A;
ALTER TABLE table_A_Keys2Update ADD PRIMARY KEY (id);

Table_A_Keys2Update'i düzeltme numarasının artırılması gereken kimliklerle doldurduktan sonra, kimliği hem table_A hem de table_A_Keys2Update öğesindeki tüm satırların düzeltme sayısını artırmak için aşağıdaki UPDATE JOIN gerçekleştirin:

UPDATE table_A A INNER JOIN table_A_Keys2Update B USING (id)
SET A.revision = A.revision + 1;

Bu tek satırlık sorgu bir tetikleyicinin ve saklı yordamın yerini alabilir.

İsteğe bağlı olarak, bu bir sorguyu saklı bir yordama yerleştirebilir ve isterseniz bunu çağırabilirsiniz.


Gerçekten merak ettiğim insert. Eğer varsa INSERT INTO denetim SEÇ <neyse> <primary_table> <saklı yordam parametreleri> NEREDEN toplu olarak insert yapabilirdi. Tetikleyicide, <güncellenmiş satırdaki veriler> DEĞERLER denetimine EKLEMEK istersiniz . Peki, tek satır, satır satır ekleme, toplu eklemeden daha hızlı olur mu?
Richard

Basitlik açısından, tetikleyici çok daha iyi olurdu 1) birincil_tablonun herhangi bir yoğun zamanın ortasında toplu ekler yaşamaması koşuluyla, 2) denetim bilgilerinin herhangi bir anda talep üzerine okunması ve 3) siteniz trafik işlemleri düşüktür.
RolandoMySQLDBA
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.