ค่าใช้จ่ายของแถวเมื่อใช้การบีบอัดหน้า?


10

ฉันสร้างตารางที่มี 650 คอลัมน์ (19,4) คอลัมน์ เมื่อฉันเปิดการบีบอัดหน้าโดยเรียกใช้

ALTER TABLE fct.MyTable REBUILD  WITH (DATA_COMPRESSION = PAGE);

ฉันเข้าใจ

ข่าวสารเกี่ยวกับ 1975, ระดับ 16, สถานะ 1
ดัชนี 'PK_Mytable' ความยาวแถวเกินความยาวสูงสุดที่อนุญาตได้ของ '8060' ไบต์

แต่ 650 ครั้ง 9 ไบต์มีเพียง 5850 ไบต์ซึ่งค่อนข้างไกลจากขีด จำกัด ที่ระบุไว้ที่ 8060 ไบต์

เซิร์ฟเวอร์กำลังเรียกใช้ Windows 2012 r2 ด้วย SQL Server 2016 SP1 CU2

ค่าใช้จ่ายของแถวเมื่อใช้การบีบอัดหน้า?

นี่คือรหัสเพื่อแสดงสิ่งที่ฉันหมายถึง:

/* test script to demo MSG 1975 */
DECLARE @sql NVARCHAR(max)='', @i INT =0
drop table if exists dbo.mytable;

SET @sql = 'Create table dbo.Mytable (MyTableID bigint not null 
  identity(1,1) primary key clustered, '

WHILE @i < 593 BEGIN
    SET @sql += ' Column' + LTRIM(@i) + ' numeric(19,4) null, '
    SET @i +=1
END

SET @sql += ' LastColumn int) '
--SET @sql += ' with (DATA_COMPRESSION = ROW) '
SET @sql += ' with (DATA_COMPRESSION = PAGE) '

SELECT @sql
EXEC sys.sp_executesql @sql

SELECT top 10000 * FROM dbo.MyTable MT

การบีบอัดแถวก็ล้มเหลวเช่นกัน แต่ในจำนวนแถวที่แตกต่างกัน


คีย์หลักของคุณใหญ่ขนาดไหน หากนี่เป็นตารางข้อเท็จจริงและคุณต้องการบีบอัดและปรับปรุงประสิทธิภาพฉันขอแนะนำให้คุณอ่านดัชนีของคอลัมน์ร้านค้าพวกเขาสามารถสร้างผลกระทบได้ค่อนข้างมาก โอเวอร์เฮดของการบีบอัดหน้าคือการใช้ cpu มากขึ้นในการคลายการบีบอัด
Stijn Wynants

@StijnWynants; 8 ไบต์ใช้สำหรับ BigInts นี่เป็นความจริง แต่มีแถวเข้าไม่เพียงพอที่จะรับประกันดัชนีคอลัมน์
Henrik Staun Poulsen

คำตอบ:


13

หากคุณลองสร้างตารางโดยไม่มีข้อ จำกัด PK แบบคลัสเตอร์และคุณจะได้รับข้อผิดพลาดแตกต่างกันเล็กน้อย:

เกี่ยวกับข้อความ 1701 ระดับ 16 สถานะ 1 บรรทัด 1 การสร้างหรือแก้ไขตาราง 'Mytable' ล้มเหลวเนื่องจากขนาดแถวขั้นต่ำจะเป็น 8067 รวมถึง 1530 ไบต์ของค่าใช้จ่ายภายใน นี่เกินขนาดสูงสุดของแถวตารางที่อนุญาตสูงสุด 8060 ไบต์

ในข้อความแสดงข้อผิดพลาดนี้คุณจะเห็นว่ามีค่าใช้จ่ายภายใน 1530 ไบต์สำหรับการบีบอัดหน้า

ตอนนี้คุณสามารถทำคณิตศาสตร์ได้:

  • 8 ไบต์สำหรับbigintMyTableID
  • 4 ไบต์สำหรับintLastColumn
  • 9 ไบต์สำหรับแต่ละnumeric(19,4)คอลัมน์593 (ผลรวม 5337 ไบต์)
  • ค่าใช้จ่ายในการบีบอัด 1530 ไบต์

ดังนั้น 8 + 4 + (593 * 9) + 1530 = 6879 รอสักครู่ .... ที่ยังต่ำกว่า 8060 เกิดอะไรขึ้นเนี่ย!


อัลกอริทึมการบีบอัดหน้าจะรวมอัลกอริทึมการบีบอัดหลายตัวเข้าด้วยกัน ขั้นตอนแรกคือการใช้การบีบอัด ROW การบีบอัดโอเวอร์เฮดของแถวไม่รวมอยู่ใน 1530 ไบต์ของโอเวอร์เฮดที่แสดงในข้อความแสดงข้อผิดพลาดนั้น

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับวิธีการบีบอัดแถวทำงานที่นี่ในบล็อกของฉันและที่นี่ใน BOL คุณจะได้ทราบในบทความ BOL ที่จะอธิบายถึงnumericการจัดเก็บเป็น "การจัดเก็บข้อมูลตรงนี้เป็นเช่นเดียวกับรูปแบบการจัดเก็บ vardecimal" vardecimalแต่ไม่ได้อธิบาย โพสต์นี้ครอบคลุมvardecimalอีกเล็กน้อย - โดยหลักแล้วจะเพิ่มค่าใช้จ่าย 2 ไบต์ต่อคอลัมน์เพื่อจัดเก็บความยาวจริง (คล้ายกับที่varcharทำ)

การบีบอัดแถวจะต้องเพิ่ม 2 ไบต์สำหรับnumericคอลัมน์593 แต่ละคอลัมน์รวมถึงbigintและintจะต้องใช้ 1 ไบต์ของค่าใช้จ่ายแต่ละรายการ

แถวบีบอัดความต้องการจัดเก็บจะเป็น:

  • 8 ไบต์ + 1 ไบต์ค่าใช้จ่ายสำหรับbigintMyTableID
  • 4 ไบต์ + 1 ไบต์ค่าใช้จ่ายสำหรับintLastColumn
  • 9 ไบต์ + 2 ไบต์ค่าใช้จ่ายสำหรับแต่ละnumeric(19,4)คอลัมน์593
  • 1188 ไบต์ของค่าใช้จ่ายในการบีบอัด ROW

8 + 4 + (593 * 9) = 5349 ไบต์ข้อมูล

1 + 1 + (593 * 2) = 1188 ไบต์ค่าใช้จ่ายในการบีบอัดแถว

ผลรวม 6537 ไบต์สำหรับสคีมาที่บีบอัดแถว


ตอนนี้เรามีขนาดแถวสำหรับ schema ที่บีบอัดแถวแล้วเราสามารถกลับมาทบทวนคณิตศาสตร์ของเราได้ ขนาดแถวที่ถูกบีบอัดหน้าจะเป็นขนาดข้อมูล + ค่าใช้จ่ายในการบีบอัดแถว + ค่าใช้จ่ายในการบีบอัดหน้า:

  • 8 ไบต์สำหรับbigintMyTableID
  • 4 ไบต์สำหรับintLastColumn
  • 9 ไบต์สำหรับแต่ละnumeric(19,4)คอลัมน์593
  • 1188 ไบต์ของค่าใช้จ่ายในการบีบอัด ROW
  • ค่าใช้จ่ายในการบีบอัดหน้า PAGE 1530
  ข้อมูล 5349 ไบต์ 
ค่าใช้จ่ายในการบีบอัดแถว + 1188 ไบต์ 
โอเวอร์เฮดการบีบอัดหน้า + 1530 ไบต์ 

ผลรวม 8067 ไบต์


1
ฉันชอบข้อสรุปของคุณ: "ในกรณีส่วนใหญ่คุณจะพบว่าการบีบอัดแถวสามารถประหยัดพื้นที่ได้ - แต่ไม่เสมอไป" ค่าใช้จ่าย 2718 ไบต์มีค่ามากกว่าที่ฉันคาดไว้มาก ขอบคุณมากที่สละเวลาเขียนคำตอบอย่างละเอียด
Henrik Staun Poulsen

1
@HenrikStaunPoulsen สิ่งสำคัญอีกอย่างที่ควรจำคือ SQL Server จำเป็นต้องสมมติว่าข้อมูลของคุณอาจไม่สามารถบีบอัดได้ ดังนั้นแม้ว่าข้อมูลของคุณจะบีบอัดให้มีขนาดน้อยกว่า 8060 ไบต์ SQL Server จะต้องทำการคำนวณขนาดแถวตามขนาดแถวสูงสุดในทางทฤษฎีสำหรับข้อมูลที่ไม่สามารถบีบอัดได้
ตีสอง

หลังจาก 3 วันฉันยังคงประหลาดใจกับจำนวนไบต์ที่จำเป็นสำหรับการบีบอัดแถว 2 ไบต์ต่อคอลัมน์ การบีบอัดหน้าเพิ่มเกือบ 3 ไบต์ที่ด้านบนของที่ แต่; ขอขอบคุณสำหรับความช่วยเหลือของคุณ. มันมีประโยชน์มากที่สุด
Henrik Staun Poulsen
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.