Bir yaklaşım, değerler için #temp tablosu kullanmak ve ayrıca karma birleştirmeye izin vermek için bir kukla equijoin sütunu kullanmak olabilir. Örneğin:
-- Create a #temp table with a dummy column to match the hash join
-- and the actual column you want
CREATE TABLE #values (dummy INT NOT NULL, Col0 CHAR(1) NOT NULL)
INSERT INTO #values (dummy, Col0)
VALUES (0, 'A'),
(0, 'B'),
(0, 'C')
GO
-- A similar query, but with a dummy equijoin condition to allow for a hash join
SELECT v.Col0,
CASE v.Col0
WHEN 'A' THEN cs.DataA
WHEN 'B' THEN cs.DataB
WHEN 'C' THEN cs.DataC
END AS Col1
FROM ColumnstoreTable cs
JOIN #values v
-- Join your dummy column to any numeric column on the columnstore,
-- multiplying that column by 0 to ensure a match to all #values
ON v.dummy = cs.DataA * 0
Performans ve sorgu planı
Bu yaklaşım aşağıdaki gibi bir sorgu planı verir ve karma eşleme toplu modda gerçekleştirilir:
Tüm bu satırları konsola akıtmaktan ve ardından sorguyu etrafta bulunduğum gerçek bir 100MM satır sütun mağaza tablosunda çalıştırmak zorunda kalmamak için ifadeyi SELECT
bir ifadeyle değiştirirsem , gerekli 300MM'yi oluşturmak için oldukça iyi bir performans görüyorum satırlar:SUM
CASE
CPU time = 33803 ms, elapsed time = 4363 ms.
Ve gerçek plan, karma birleştirmenin iyi paralelliğini gösterir.
Tüm satırlar aynı değere sahip olduğunda karma birleştirme paralelleştirmesi hakkında notlar
Bu sorgunun performansı, birleştirme işleminin prob tarafındaki her bir iş parçacığına tam karma tabloya erişime (her bir satırın tek bir iş parçacığıyla eşleşeceği karma bölümlü bir sürümün aksine) büyük ölçüde bağlıdır. için dummy
kolon).
Neyse ki, bu durumda ( Parallelism
prob tarafında bir operatörün eksikliğinden görebildiğimiz gibi ) doğrudur ve güvenilir bir şekilde doğru olmalıdır çünkü toplu mod, iş parçacıkları arasında paylaşılan tek bir karma tablo oluşturur. Bu nedenle, her iş parçacığı satırlarını alabilir Columnstore Index Scan
ve bunları paylaşılan karma tabloyla eşleştirebilir. SQL Server 2012'de bu işlevsellik çok daha az tahmin edilebilirdi, çünkü bir dökülme operatörün Satır modunda yeniden başlatılmasına neden oldu, hem toplu modun faydasını kaybetti hem Repartition Streams
de birleşimin prob tarafında bir operatör gerektirdiğinden bu durumda iplik eğrilmesine neden oldu . Dökülmelerin toplu modda kalmasına izin vermek SQL Server 2014'teki önemli bir gelişmedir.
Bildiğim kadarıyla, satır modu bu paylaşılan karma tablo yeteneğine sahip değil. Bununla birlikte, bazı durumlarda, tipik olarak oluşturma tarafında 100'den az satır tahminiyle SQL Server, her iş parçacığı için karma tablonun ayrı bir kopyasını oluşturur ( Distribute Streams
karma birleştirmeye giden satır tarafından tanımlanabilir ). Bu çok güçlü olabilir, ancak kardinalite tahminlerinize bağlı olduğundan ve SQL Server, her iş parçacığı için karma tablonun tam bir kopyasını oluşturma maliyetine karşı faydaları değerlendirmeye çalıştığı için toplu moddan çok daha az güvenilirdir.
BİRLİĞİ: daha basit bir alternatif
Paul White, UNION ALL
her değer için satırları birleştirmek için başka ve potansiyel olarak daha basit bir seçeneğin kullanılacağına dikkat çekti . Bu SQL'i dinamik olarak oluşturmanın kolay olduğunu varsayarak muhtemelen en iyi bahistir. Örneğin:
SELECT 'A' AS Col0, c.DataA AS Col1
FROM ColumnstoreTable c
UNION ALL
SELECT 'B' AS Col0, c.DataB AS Col1
FROM ColumnstoreTable c
UNION ALL
SELECT 'C' AS Col0, c.DataC AS Col1
FROM ColumnstoreTable c
Bu aynı zamanda parti modunu kullanabilen ve orijinal yanıttan daha iyi performans sağlayan bir plan verir. (Her iki durumda da performans, herhangi bir veriyi seçip bir tabloya yazmanın hızla darboğaz haline gelmesine yetecek kadar hızlıdır.) UNION ALL
Yaklaşım aynı zamanda 0 ile çarpmak gibi oyunlar oynamaktan kaçınır. Bazen basit düşünmek en iyisidir!
CPU time = 8673 ms, elapsed time = 4270 ms.