Sorunuzda, ekleme seçeneğinin ayrı sütunları karşılaştırmaktan daha hızlı olduğunu "kanıtladığınız" yerde hazırladığınız bazı testleri ayrıntılı olarak açıklıyorsunuz. Test metodolojinizin @gbn ve @srutzky'nin belirttiği gibi çeşitli şekillerde kusurlu olabileceğinden şüpheleniyorum.
İlk olarak, SQL Server Management Studio'yu (veya kullandığınız herhangi bir istemciyi) test etmediğinizden emin olmanız gerekir. Örneğin, SELECT *
3 milyon satırlı bir tablodan çalıştırıyorsanız , SSMS'nin satırları SQL Server'dan çekme ve bunları ekranda oluşturma yeteneğini test edersiniz. SELECT COUNT(1)
Ağ boyunca milyonlarca satırı çekme ve bunları ekranda oluşturma ihtiyacını ortadan kaldıran bir şey kullanmaktan çok daha iyisiniz .
İkincisi, SQL Server'ın veri önbelleğinin farkında olmanız gerekir. Genellikle, verileri depolamadan okuma ve bu verileri işleme, bir soğuk önbellekten test ediyoruz (yani SQL Server'ın arabellekleri boş). Bazen, tüm testlerinizi sıcak bir önbellek ile yapmak mantıklıdır, ancak testinize açıkça aklınızda yaklaşmanız gerekir.
Soğuk önbellek testi için, testin her çalıştırılmasından önce CHECKPOINT
ve çalıştırmanız gerekir DBCC DROPCLEANBUFFERS
.
Sorunuzda sorduğunuz test için aşağıdaki test yatağını oluşturdum:
IF COALESCE(OBJECT_ID('tempdb..#SomeTest'), 0) <> 0
BEGIN
DROP TABLE #SomeTest;
END
CREATE TABLE #SomeTest
(
TestID INT NOT NULL
PRIMARY KEY
IDENTITY(1,1)
, A INT NOT NULL
, B FLOAT NOT NULL
, C MONEY NOT NULL
, D BIGINT NOT NULL
);
INSERT INTO #SomeTest (A, B, C, D)
SELECT o1.object_id, o2.object_id, o3.object_id, o4.object_id
FROM sys.objects o1
, sys.objects o2
, sys.objects o3
, sys.objects o4;
SELECT COUNT(1)
FROM #SomeTest;
Bu, makinemde 260.144.641 sayısını döndürüyor.
"Ekleme" yöntemini test etmek için çalıştırın:
CHECKPOINT 5;
DBCC FREEPROCCACHE;
DBCC DROPCLEANBUFFERS;
SET STATISTICS IO, TIME ON;
GO
SELECT COUNT(1)
FROM #SomeTest st
WHERE (st.A + st.B + st.C + st.D) = 0;
GO
SET STATISTICS IO, TIME OFF;
Mesajlar sekmesi şunları gösterir:
'#SomeTest' tablosu. Tarama sayısı 3, mantıksal okuma 1322661, fiziksel okuma 0, okuma öncesi okuma 1313877, lob mantıksal okuma 0, lob fiziksel okuma 0, lob okuma önceden okuma 0.
SQL Server Yürütme Süreleri: CPU süresi = 49047 ms, geçen süre = 173451 ms.
"Ayrık sütunlar" testi için:
CHECKPOINT 5;
DBCC FREEPROCCACHE;
DBCC DROPCLEANBUFFERS;
SET STATISTICS IO, TIME ON;
GO
SELECT COUNT(1)
FROM #SomeTest st
WHERE st.A = 0
AND st.B = 0
AND st.C = 0
AND st.D = 0;
GO
SET STATISTICS IO, TIME OFF;
yine mesajlar sekmesinden:
'#SomeTest' tablosu. Tarama sayısı 3, mantıksal okumalar 1322661, fiziksel okumalar 0, okuma öncesi okumalar 1322661, lob mantıksal okumalar 0, lob fiziksel okumalar 0, lob okuma öncesi okumalar 0.
SQL Server Yürütme Süreleri: CPU süresi = 8938 ms, geçen süre = 162581 ms.
Yukarıdaki istatistiklerden, 0'a kıyasla ayrık sütunlarla ikinci varyantı görebilirsiniz, geçen süre yaklaşık 10 saniye daha kısadır ve CPU süresi yaklaşık 6 kat daha azdır. Yukarıdaki testlerimdeki uzun süreler çoğunlukla diskten çok sayıda satır okumanın bir sonucudur. Satır sayısını 3 milyona düşürürseniz, oranların yaklaşık olarak aynı kaldığını görürsünüz, ancak disk G / Ç'nin çok daha az etkisi olduğu için geçen süreler belirgin bir şekilde düşer.
"Toplama" yöntemi ile:
'#SomeTest' tablosu. Tarama sayısı 3, mantıksal okumalar 15255, fiziksel okumalar 0, okuma öncesi okumalar 0, lob mantıksal okumalar 0, lob fiziksel okumalar 0, lob okuma öncesi okumalar 0.
SQL Server Yürütme Süreleri: CPU süresi = 499 ms, geçen süre = 256 ms.
"Ayrık sütunlar" yöntemiyle:
'#SomeTest' tablosu. Tarama sayısı 3, mantıksal okumalar 15255, fiziksel okumalar 0, okuma öncesi okumalar 0, lob mantıksal okumalar 0, lob fiziksel okumalar 0, lob okuma öncesi okumalar 0.
SQL Server Yürütme Süreleri: CPU süresi = 94 ms, geçen süre = 53 ms.
Bu test için gerçekten çok büyük bir fark ne olacak? Uygun bir dizin, örneğin:
CREATE INDEX IX_SomeTest ON #SomeTest(A, B, C, D);
"Ekleme" yöntemi:
'#SomeTest' tablosu. Tarama sayısı 3, mantıksal okuma 14235, fiziksel okuma 0, okuma öncesi okuma 0, lob mantıksal okuma 0, lob fiziksel okuma 0, lob okuma önceden okuma 0.
SQL Server Yürütme Süreleri: CPU süresi = 546 ms, geçen süre = 314 ms.
"Ayrık sütunlar" yöntemi:
'#SomeTest' tablosu. Tarama sayısı 1, mantıksal okumalar 3, fiziksel okumalar 0, okuma öncesi okumalar 0, lob mantıksal okumalar 0, lob fiziksel okumalar 0, lob okuma öncesi okumalar 0.
SQL Server Yürütme Süreleri: CPU süresi = 0 ms, geçen süre = 0 ms.
Her bir sorgu için yürütme planı (yukarıdaki dizin yerinde) oldukça açıklayıcıdır.
Tüm indeksin taranması gereken "ekleme" yöntemi:
ve baştaki dizin sütununun A
sıfır olduğu dizinin ilk satırını arayabilen "ayrık sütunlar" yöntemi :