วิธีการหนึ่งอาจใช้ตาราง #temp สำหรับค่าต่างๆและยังแนะนำคอลัมน์คอลัมน์รูปหุ่นเพื่ออนุญาตให้เข้าร่วมแฮช ตัวอย่างเช่น:
-- 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
แผนประสิทธิภาพและแบบสอบถาม
วิธีการนี้ให้ผลแบบสอบถามแผนดังต่อไปนี้และทำการแฮชตรงกันในโหมดแบทช์:
ถ้าฉันแทนที่SELECT
คำสั่งด้วย a SUM
ของCASE
คำสั่งเพื่อหลีกเลี่ยงการสตรีมแถวเหล่านั้นทั้งหมดไปยังคอนโซลและจากนั้นเรียกใช้แบบสอบถามบนตารางคอลัมน์แถวแถว 100 มม. จริงที่ฉันโกหกฉันเห็นประสิทธิภาพที่ค่อนข้างดีในการสร้างสิ่งที่จำเป็น 300MM แถว:
CPU time = 33803 ms, elapsed time = 4363 ms.
และแผนจริงแสดงให้เห็นถึงการขนานที่ดีของการเข้าร่วมแฮ
หมายเหตุเกี่ยวกับการแฮชการรวมขนานเมื่อแถวทั้งหมดมีค่าเท่ากัน
ประสิทธิภาพการทำงานของแบบสอบถามนี้ขึ้นอยู่กับแต่ละเธรดที่ด้านโพรบของการเข้าร่วมที่มีการเข้าถึงตารางแฮชแบบเต็มรูปแบบ (ซึ่งตรงกันข้ามกับเวอร์ชันที่แบ่งพาร์ติชันแฮชซึ่งจะจับคู่แถวทั้งหมดกับเธรดเดี่ยว สำหรับdummy
คอลัมน์)
โชคดีที่มันเป็นจริงในกรณีนี้ (อย่างที่เราเห็นได้จากการขาดตัวParallelism
ดำเนินการด้านโพรบ) และน่าเชื่อถืออย่างแท้จริงเพราะโหมดแบตช์สร้างตารางแฮชเดี่ยวที่แชร์ข้ามเธรด ดังนั้นแต่ละเธรดสามารถนำแถวจากColumnstore Index Scan
และจับคู่กับตารางแฮชที่แชร์ ใน SQL Server 2012 ฟังก์ชันการทำงานนี้สามารถคาดการณ์ได้น้อยกว่ามากเนื่องจากการรั่วไหลทำให้ตัวดำเนินการเริ่มต้นใหม่ในโหมดแถวทั้งสูญเสียผลประโยชน์ของโหมดแบตช์และยังต้องการตัวRepartition Streams
ดำเนินการในด้านโพรบของการเข้าร่วมซึ่งจะทำให้ . การอนุญาตให้มีการรั่วไหลในโหมดแบตช์เป็นการปรับปรุงที่สำคัญใน SQL Server 2014
สำหรับความรู้ของฉันโหมดแถวไม่ได้มีความสามารถในตารางแฮชที่ใช้ร่วมกันนี้ อย่างไรก็ตามในบางกรณีโดยทั่วไปแล้วมีการประมาณน้อยกว่า 100 แถวในด้านการสร้าง SQL Server จะสร้างสำเนาของตารางแฮชแยกต่างหากสำหรับแต่ละเธรด (สามารถระบุได้โดยDistribute Streams
การนำเข้าสู่การแฮช) สิ่งนี้มีประสิทธิภาพมาก แต่มีความน่าเชื่อถือน้อยกว่าโหมดแบตช์เนื่องจากขึ้นอยู่กับการประเมินความสำคัญของคุณและ SQL Server พยายามประเมินผลประโยชน์เทียบกับค่าใช้จ่ายในการสร้างสำเนาตารางแฮชแบบเต็มสำหรับแต่ละเธรด
ยูเนี่ยนทั้งหมด: ทางเลือกที่ง่ายกว่า
Paul White ชี้ให้เห็นว่าตัวเลือกอื่นและอาจง่ายกว่านั้นคือใช้UNION ALL
เพื่อรวมแถวสำหรับแต่ละค่า นี่น่าจะเป็นทางออกที่ดีที่สุดของคุณโดยสมมติว่าคุณสามารถสร้าง SQL นี้แบบไดนามิกได้ง่าย ตัวอย่างเช่น:
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
สิ่งนี้ยังให้แผนที่สามารถใช้โหมดแบทช์และให้ประสิทธิภาพที่ดียิ่งขึ้นกว่าคำตอบเดิม (แม้ว่าในทั้งสองกรณีประสิทธิภาพจะเร็วพอที่การเลือกหรือเขียนข้อมูลลงในตารางจะกลายเป็นคอขวดอย่างรวดเร็ว) UNION ALL
วิธีการนี้ยังช่วยหลีกเลี่ยงการเล่นเกมเช่นการคูณด้วย 0 บางครั้งก็เป็นการง่ายที่จะคิด!
CPU time = 8673 ms, elapsed time = 4270 ms.