ฉันไม่สามารถบอกได้อย่างชัดเจนว่าทำไมพฤติกรรมนี้จึงเกิดขึ้น แต่ฉันเชื่อว่าฉันได้พัฒนาแบบจำลองพฤติกรรมที่ดีผ่านการทดสอบกำลังดุร้าย ข้อสรุปต่อไปนี้ใช้เฉพาะเมื่อโหลดข้อมูลลงในคอลัมน์เดียวและมีจำนวนเต็มที่กระจายได้ดีมาก
ครั้งแรกที่ฉันพยายามแปรจำนวนแถวที่แทรกเข้าไปใน CCI TOP
โดยใช้ ฉันใช้ID % 16000
สำหรับการทดสอบทั้งหมด ด้านล่างนี้เป็นกราฟเปรียบเทียบแถวที่แทรกกับขนาดเซ็กเมนต์ของ rowgroup ที่ถูกบีบอัด:
ด้านล่างนี้คือกราฟของแถวที่แทรกไปยังเวลา CPU ในหน่วยมิลลิวินาที โปรดทราบว่าแกน X มีจุดเริ่มต้นที่แตกต่างกัน:
เราจะเห็นได้ว่าขนาดเซกเมนต์ของกลุ่มแถวเติบโตในอัตราเชิงเส้นและใช้ CPU จำนวนเล็กน้อยจนถึงประมาณ 1 M แถว ณ จุดนั้นขนาดแถวของกลุ่มจะลดลงอย่างมากและการใช้งาน CPU เพิ่มขึ้นอย่างมาก ดูเหมือนว่าเราจะจ่ายซีพียูเป็นจำนวนมากสำหรับการบีบอัดข้อมูลนั้น
เมื่อแทรกน้อยกว่า 1024,000 แถวฉันลงเอยด้วยกลุ่มแถวเปิดใน CCI อย่างไรก็ตามการบังคับให้บีบอัดโดยใช้REORGANIZE
หรือREBUILD
ไม่มีผลกับขนาด ในฐานะที่เป็นกันฉันพบว่ามันน่าสนใจที่เมื่อฉันใช้ตัวแปรสำหรับTOP
ฉันจบลงด้วยการเปิด rowgroup แต่เมื่อRECOMPILE
ฉันลงเอยด้วยการปิด rowgroup
ต่อไปฉันทดสอบโดยการเปลี่ยนค่าโมดูลัสในขณะที่ยังคงจำนวนแถวเท่าเดิม นี่คือตัวอย่างของข้อมูลเมื่อทำการแทรกแถว 102400:
╔═══════════╦═════════╦═══════════════╦═════════════╗
║ TOP_VALUE ║ MOD_NUM ║ SIZE_IN_BYTES ║ CPU_TIME_MS ║
╠═══════════╬═════════╬═══════════════╬═════════════╣
║ 102400 ║ 1580 ║ 13504 ║ 352 ║
║ 102400 ║ 1590 ║ 13584 ║ 316 ║
║ 102400 ║ 1600 ║ 13664 ║ 317 ║
║ 102400 ║ 1601 ║ 19624 ║ 270 ║
║ 102400 ║ 1602 ║ 25568 ║ 283 ║
║ 102400 ║ 1603 ║ 31520 ║ 286 ║
║ 102400 ║ 1604 ║ 37464 ║ 288 ║
║ 102400 ║ 1605 ║ 43408 ║ 273 ║
║ 102400 ║ 1606 ║ 49360 ║ 269 ║
║ 102400 ║ 1607 ║ 55304 ║ 265 ║
║ 102400 ║ 1608 ║ 61256 ║ 262 ║
║ 102400 ║ 1609 ║ 67200 ║ 255 ║
║ 102400 ║ 1610 ║ 73144 ║ 265 ║
║ 102400 ║ 1620 ║ 132616 ║ 132 ║
║ 102400 ║ 1621 ║ 138568 ║ 100 ║
║ 102400 ║ 1622 ║ 144512 ║ 91 ║
║ 102400 ║ 1623 ║ 150464 ║ 75 ║
║ 102400 ║ 1624 ║ 156408 ║ 60 ║
║ 102400 ║ 1625 ║ 162352 ║ 47 ║
║ 102400 ║ 1626 ║ 164712 ║ 41 ║
╚═══════════╩═════════╩═══════════════╩═════════════╝
จนถึงค่า mod ที่ 1600 ขนาดเซ็กเมนต์ rowgroup จะเพิ่มขึ้นเป็นเส้นตรง 80 ไบต์สำหรับค่าที่ไม่ซ้ำกัน 10 ค่าเพิ่มเติม มันเป็นเรื่องบังเอิญที่น่าสนใจที่โดยBIGINT
ทั่วไปใช้เวลา 8 ไบต์และขนาดเซกเมนต์เพิ่มขึ้น 8 ไบต์สำหรับแต่ละค่าที่ไม่ซ้ำกันเพิ่มเติม ที่ผ่านมาค่า mod ที่ 1600 ขนาดเซ็กเมนต์จะเพิ่มขึ้นอย่างรวดเร็วจนกว่าจะเสถียร
นอกจากนี้ยังเป็นประโยชน์ในการดูข้อมูลเมื่อปล่อยให้ค่าโมดูลัสเหมือนกันและเปลี่ยนจำนวนแถวที่แทรก:
╔═══════════╦═════════╦═══════════════╦═════════════╗
║ TOP_VALUE ║ MOD_NUM ║ SIZE_IN_BYTES ║ CPU_TIME_MS ║
╠═══════════╬═════════╬═══════════════╬═════════════╣
║ 300000 ║ 5000 ║ 600656 ║ 131 ║
║ 305000 ║ 5000 ║ 610664 ║ 124 ║
║ 310000 ║ 5000 ║ 620672 ║ 127 ║
║ 315000 ║ 5000 ║ 630680 ║ 132 ║
║ 320000 ║ 5000 ║ 40688 ║ 2344 ║
║ 325000 ║ 5000 ║ 40696 ║ 2577 ║
║ 330000 ║ 5000 ║ 40704 ║ 2589 ║
║ 335000 ║ 5000 ║ 40712 ║ 2673 ║
║ 340000 ║ 5000 ║ 40728 ║ 2715 ║
║ 345000 ║ 5000 ║ 40736 ║ 2744 ║
║ 350000 ║ 5000 ║ 40744 ║ 2157 ║
╚═══════════╩═════════╩═══════════════╩═════════════╝
ดูเหมือนว่าเมื่อจำนวนแถวที่แทรก <~ 64 * จำนวนค่าที่ไม่ซ้ำกันที่เราเห็นมีการบีบอัดค่อนข้างต่ำ (2 ไบต์ต่อแถวสำหรับ mod <= 65000) และการใช้ CPU เชิงเส้นต่ำ เมื่อจำนวนแถวที่แทรก> ~ 64 * จำนวนค่าที่ไม่ซ้ำกันเราเห็นการบีบอัดที่ดีขึ้นและการใช้ CPU เชิงเส้นยังคงสูงขึ้น มีการเปลี่ยนแปลงระหว่างสองสถานะซึ่งไม่ใช่เรื่องง่ายสำหรับฉันที่จะสร้างแบบจำลอง แต่สามารถเห็นได้ในกราฟ ดูเหมือนจะไม่เป็นความจริงที่เราจะเห็นการใช้งาน CPU สูงสุดเมื่อทำการแทรก 64 แถวสำหรับแต่ละค่าที่ไม่ซ้ำกัน แต่เราสามารถแทรกแถวได้สูงสุด 1048576 แถวในกลุ่มแถวและเราเห็นการใช้ CPU และการบีบอัดที่สูงขึ้นมากเมื่อมีมากกว่า 64 แถวต่อค่าที่ไม่ซ้ำกัน
ด้านล่างนี้เป็นโครงร่างของการเปลี่ยนแปลงเวลาของซีพียูเมื่อจำนวนแถวที่แทรกและจำนวนแถวที่ไม่ซ้ำกันเปลี่ยนแปลง เราสามารถเห็นรูปแบบที่อธิบายไว้ข้างต้น:
ด้านล่างนี้เป็นโครงเรื่องพื้นที่ที่ใช้งานโดยส่วน หลังจากจุดหนึ่งเราเริ่มเห็นการบีบอัดที่ดีขึ้นมากดังที่อธิบายไว้ข้างต้น:
ดูเหมือนว่ามีอัลกอริทึมการบีบอัดที่แตกต่างกันอย่างน้อยสองที่ทำงานที่นี่ ตามที่กล่าวไว้ข้างต้นทำให้รู้สึกว่าเราจะเห็นการใช้งาน CPU สูงสุดเมื่อทำการแทรกแถว 1048576 นอกจากนี้ยังทำให้รู้สึกว่าเราเห็นการใช้งาน CPU มากที่สุด ณ จุดนั้นเมื่อแทรกประมาณ 16,000 แถว 1048576/64 = 16384
ฉันอัปโหลดข้อมูลดิบทั้งหมดของฉันที่นี่ในกรณีที่มีคนต้องการวิเคราะห์
เป็นมูลค่าการกล่าวถึงสิ่งที่เกิดขึ้นกับแผนขนาน ฉันสังเกตเห็นพฤติกรรมนี้ด้วยค่าที่กระจายเท่า ๆ กัน เมื่อทำการแทรกแบบขนานมักจะมีองค์ประกอบของการสุ่มและเธรดมักไม่สมดุล
วาง 2097152 แถวในตารางเตรียมการ:
DROP TABLE IF EXISTS STG_2097152;
CREATE TABLE dbo.STG_2097152 (ID BIGINT NOT NULL);
INSERT INTO dbo.STG_2097152 WITH (TABLOCK)
SELECT TOP (2097152) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) RN
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;
ส่วนแทรกนี้เสร็จสิ้นในเวลาน้อยกว่าหนึ่งวินาทีและมีการบีบอัดที่ไม่ดี:
DROP TABLE IF EXISTS dbo.CCI_BIGINT;
CREATE TABLE dbo.CCI_BIGINT (ID BIGINT NOT NULL, INDEX CCI CLUSTERED COLUMNSTORE);
INSERT INTO dbo.CCI_BIGINT WITH (TABLOCK)
SELECT ID % 16000
FROM dbo.STG_2097152
OPTION (MAXDOP 2);
เราสามารถเห็นผลของเธรดที่ไม่สมดุล:
╔════════════╦════════════╦══════════════╦═══════════════╗
║ state_desc ║ total_rows ║ deleted_rows ║ size_in_bytes ║
╠════════════╬════════════╬══════════════╬═══════════════╣
║ OPEN ║ 13540 ║ 0 ║ 311296 ║
║ COMPRESSED ║ 1048576 ║ 0 ║ 2095872 ║
║ COMPRESSED ║ 1035036 ║ 0 ║ 2070784 ║
╚════════════╩════════════╩══════════════╩═══════════════╝
มีเทคนิคต่าง ๆ ที่เราสามารถทำได้เพื่อบังคับให้เธรดมีความสมดุลและมีการกระจายแถวเดียวกัน นี่คือหนึ่งในนั้น:
DROP TABLE IF EXISTS dbo.CCI_BIGINT;
CREATE TABLE dbo.CCI_BIGINT (ID BIGINT NOT NULL, INDEX CCI CLUSTERED COLUMNSTORE);
INSERT INTO dbo.CCI_BIGINT WITH (TABLOCK)
SELECT FLOOR(0.5 * ROW_NUMBER() OVER (ORDER BY (SELECT NULL))) % 15999
FROM dbo.STG_2097152
OPTION (MAXDOP 2)
การเลือกตัวเลขคี่สำหรับโมดูลัสเป็นสิ่งสำคัญที่นี่ SQL Server จะสแกนตารางลำดับขั้นในแบบอนุกรมคำนวณหมายเลขแถวจากนั้นใช้การกระจายแบบวนรอบเพื่อวางแถวบนเธรดแบบขนาน นั่นหมายความว่าเราจะจบด้วยหัวข้อที่มีความสมดุลอย่างสมบูรณ์แบบ
การแทรกใช้เวลาประมาณ 40 วินาทีซึ่งคล้ายกับการแทรกแบบอนุกรม เราได้รับกลุ่มแถวที่ถูกบีบอัดอย่าง:
╔════════════╦════════════╦══════════════╦═══════════════╗
║ state_desc ║ total_rows ║ deleted_rows ║ size_in_bytes ║
╠════════════╬════════════╬══════════════╬═══════════════╣
║ COMPRESSED ║ 1048576 ║ 0 ║ 128568 ║
║ COMPRESSED ║ 1048576 ║ 0 ║ 128568 ║
╚════════════╩════════════╩══════════════╩═══════════════╝
เราสามารถได้ผลลัพธ์เดียวกันโดยการแทรกข้อมูลจากตาราง staging ดั้งเดิม:
DROP TABLE IF EXISTS dbo.CCI_BIGINT;
CREATE TABLE dbo.CCI_BIGINT (ID BIGINT NOT NULL, INDEX CCI CLUSTERED COLUMNSTORE);
INSERT INTO dbo.CCI_BIGINT WITH (TABLOCK)
SELECT t.ID % 16000 ID
FROM (
SELECT TOP (2) ID
FROM (SELECT 1 ID UNION ALL SELECT 2 ) r
) s
CROSS JOIN dbo.STG_1048576 t
OPTION (MAXDOP 2, NO_PERFORMANCE_SPOOL);
ที่นี่การกระจายแบบโรบินกลมใช้สำหรับตารางที่ได้รับs
ดังนั้นการสแกนหนึ่งตารางจะทำในแต่ละเธรดแบบขนาน:
โดยสรุปเมื่อแทรกจำนวนเต็มกระจายเท่า ๆ กันคุณสามารถเห็นการบีบอัดสูงมากเมื่อแต่ละจำนวนเต็มไม่ซ้ำกันปรากฏขึ้นมากกว่า 64 ครั้ง อาจเกิดจากอัลกอริธึมการบีบอัดที่แตกต่างกัน อาจมีต้นทุนสูงใน CPU เพื่อให้ได้การบีบอัดนี้ การเปลี่ยนแปลงเล็กน้อยในข้อมูลสามารถนำไปสู่ความแตกต่างอย่างมากในขนาดของเซ็กเมนต์กลุ่มแถวที่ถูกบีบอัด ฉันสงสัยว่าการดูกรณีที่เลวร้ายที่สุด (จากมุมมองของ CPU) จะไม่เป็นเรื่องปกติอย่างน้อยสำหรับชุดข้อมูลนี้ ยิ่งยากที่จะเห็นเมื่อทำการแทรกแบบขนาน