YABANCI ANAHTAR'da açık tek ANAHTAR değeriyle MERGE JOIN (INDEX SCAN) üstesinden gelin


9

Eklendi 7/11 Sorun, MERGE JOIN sırasında dizin taraması nedeniyle meydana gelmesi. Bu durumda, FK üst tablosundaki tüm dizinde S kilidi almaya çalışan bir işlem, ancak daha önce başka bir işlem X kilidini dizinin anahtar değerine koyar.

Küçük bir örnekle başlayayım (kullanılan 70-461 kurstan TSQL2012 DB):

CREATE TABLE [Sales].[Orders](
[orderid] [int] IDENTITY(1,1) NOT NULL,
[custid] [int] NULL,
[empid] [int] NOT NULL,
[shipperid] [int] NOT NULL,
... )

Sütunlar buna göre temel [custid], [empid], [shipperid]parametrelerdir [Sales].[Customers], [HR].[Employees], [Sales].[Shippers]. Her durumda, bir ayrıştırma tablosundaki belirtilen bir sütunda kümelenmiş bir dizin bulunur.

ALTER TABLE [Sales].[Orders]  WITH CHECK ADD  CONSTRAINT [FK_Orders_Customers] FOREIGN KEY([custid]) REFERENCES [Sales].[Customers] ([custid])
ALTER TABLE [Sales].[Orders]  WITH CHECK ADD  CONSTRAINT [FK_Orders_Employees] FOREIGN KEY([empid]) REFERENCES [HR].[Employees] ([empid])
ALTER TABLE [Sales].[Orders]  WITH CHECK ADD  CONSTRAINT [FK_Orders_Shippers] FOREIGN KEY([shipperid])REFERENCES [Sales].[Shippers] ([shipperid])

Yabancı anahtarlar dışında aynı yapıya sahip INSERT [Sales].[Orders] SELECT ... FROMdenilen başka bir tabloya çalışıyorum . Tablonun kümelenmiş bir dizin olduğunu belirtmek başka bir şey olabilir .[Sales].[OrdersCache][Sales].[Orders][Sales].[OrdersCache]

CREATE CLUSTERED INDEX idx_c_OrdersCache ON Sales.OrdersCache ( custid, empid )

Beklendiği gibi düşük hacimli veri eklemeye çalıştığımda LOOP JOIN, yabancı anahtarlarda endeks araması yapıyor.

Yüksek hacimli verilerle MERGE JOIN, sorgu optimizer tarafından sorguda foregn anahtarını korumanın en etkili yolu olarak kullanılır.

Ve bizim durumumuzda yabancı anahtarlar ile OPTION (LOOP JOIN) veya açık JOIN durumunda INNER LOOP JOIN kullanılarak yapılan hiçbir şey yoktur.

Ortamımda çalıştırmaya çalıştığım sorgu aşağıdadır:

INSERT Sales.Orders (
        custid, empid, shipperid, ... )
SELECT  custid, empid, 2, ...
FROM Sales.OrdersCache

Plana baktığımızda, 3 yabancı anahtarın hepsinin MERGE JOIN ile doğrulandığını görebiliriz. İndeks kilitlemeli INDEX SCAN kullandığı için benim için uygun bir yol değil. Yabancı anahtarların doğrulanması sırasında MERGE JOIN

SEÇENEK (LOOP JOIN) kullanımı uygun değildir çünkü MERGE JOIN'den neredeyse% 15 daha fazladır (veri hacimlerinin artmasıyla gerileme daha büyük olacaktır).

SELECT deyiminde shipperid, eklenen tüm kümenin özniteliği için tek bir değer görebilirsiniz . Kanımca, eklenen kümenin doğrulama aşamasını en azından değişmez öznitelik için daha hızlı yapmanın bir yolu olmalıdır. Gibi bir şey:

  • JOIN doğrulaması için tanımlanmamış altkümemiz varsa LOOP JOIN, MERGE JOIN, HASH JOIN yap
  • doğrulanmış sütunun yalnızca tek bir açık değeri varsa, doğrulamayı yalnızca bir kez yaparız (INDEX SEEK).

Kod yapılarını, ek DDL nesnelerini vb. Kullanarak yukarıdaki durumun üstesinden gelmek için ortak bir model var mı?

20/07 eklendi. Çözüm. Sorgu Optimize Edici, MERGE JOIN kullanarak zaten bir 'tek anahtar - yabancı anahtar' doğrulama optimizasyonu yapıyor. Ve sadece Sales.Shippers tablosu için yapar, LOOP JOIN'i aynı anda sorgudaki başka birleştirmeler için bırakır. Üst tabloda birkaç satır bulunduğundan Query Optimizer, Sort-merge join algoritmasını kullanır ve iç tablodaki her satırı üst tabloyla yalnızca bir kez karşılaştırır. Tek bir anahtar doğrulaması sırasında bir kümedeki tek değerleri etkin bir şekilde işlemek için herhangi bir mekanizma olup olmadığı sorumun cevabı budur. Bu mükemmel bir karar değil, SQL Server'ın davayı optimize etmesinin yolu bu.

Performans etkisi araştırması, benim durumumda MERGE JOIN ve LOOP JOIN insert ifadesinin, MERGE JOIN'in (CPU zaman kaynağında) aşağıdaki üstünlüğüne sahip 750 eşzamanlı olarak eklenen satırla yaklaşık olarak eşit olduğunu ortaya koydu. Bu yüzden OPTION (LOOP JOIN) kullanmak iş sürecim için uygun bir çözümdür.

Yanıtlar:


8

OPGE (LOOP JOIN) kullanımı uygun değildir, çünkü MERGE JOIN'den neredeyse% 15 daha yüksektir

Showplan çıktısında görüntülenen maliyet yüzdeleri , yürütme sonrası (fiili) planda bile her zaman optimize edici model tahminleridir. Bu maliyetler büyük olasılıkla donanımınızdaki gerçek çalışma zamanı performansını yansıtmaz. Emin olmanın tek yolu, sizin için en önemli olan metrikleri (geçen süre, CPU kullanımı vb.) Ölçerek iş yükünüzle alternatifleri test etmektir.

Deneyimlerime göre, optimize edici yabancı anahtar doğrulaması için birleştirmeyi birleştirmek üzere döngülerden birleştirmelere çok erken. En büyük operasyonlar dışında, döngülerin tercih edilebilir olduğunu gördüm. Ve "büyük" derken, en azından on milyonlarca satır demek istiyorum, sorunuzun yorumlarında kesinlikle bin kadar değil.

Kanımca, eklenen kümenin doğrulama aşamasını en azından değişmez öznitelik için daha hızlı yapmanın bir yolu olmalıdır.

Bu prensipte mantıklıdır, ancak bugün plan oluşturma mantığında yabancı anahtar doğrulamasının kullandığı böyle bir mantık yoktur. Mevcut mantık kasten çok genel ve daha geniş sorguya diktir; spesifik optimizasyonlar testi karmaşıklaştırır ve uç durum hatalarının olasılığını artırır.

Kod yapılarını, ek DDL nesnelerini vb. Kullanarak yukarıdaki durumun üstesinden gelmek için ortak bir model var mı?

Bildiğim kadarıyla ... değil. Birleştirme birleştirme yabancı anahtar doğrulamasında kilitlenme riski iyi bilinmektedir ve en çok kullanılan geçici çözüm OPTION (LOOP JOIN)ipucudur. Yabancı anahtar doğrulaması sırasında paylaşılan kilitlerin alınmasından kaçınmanın bir yolu yoktur, çünkü bunlar satır sürümlendirme yalıtım düzeyleri altında bile doğruluk için gereklidir .

Birden fazla eşzamanlı işlemin üst ve alt tablolara işlemsel olarak satır ekleme yeteneğini korumak istiyorsanız, daha iyi bir genel yanıt (döngü birleştirme ipucundan daha iyi) yoktur. Ancak, veri değişikliklerini (okuma değil) serileştirmek istiyorsanız, sp_getapplock kullanmak güvenilir ve basit bir tekniktir.

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.