การเพิ่ม SPARSE ทำให้ตารางใหญ่ขึ้นมาก


9

ฉันมีตารางบันทึกทั่วไปแถวประมาณ 5 เมตร
มีฟิลด์ "พิมพ์อย่างยิ่ง" ที่จัดเก็บประเภทเหตุการณ์และมีคอลัมน์ "พิมพ์จำนวนมาก" ที่ประกอบด้วยข้อมูลที่เกี่ยวข้องกับเหตุการณ์ นั่นคือความหมายของคอลัมน์ "ที่พิมพ์แบบแพ้ ๆ " นั้นขึ้นอยู่กับประเภทของเหตุการณ์

คอลัมน์เหล่านี้ถูกกำหนดเป็น:

USER_CHAR1 nvarchar(150) null,
USER_CHAR2 nvarchar(150) null,
USER_CHAR3 nvarchar(150) null,
USER_CHAR4 nvarchar(150) null,
USER_CHAR5 nvarchar(150) null,

USER_INTEGER1 int null,
USER_INTEGER2 int null,
USER_INTEGER3 int null,
USER_INTEGER4 int null,
USER_INTEGER5 int null,

USER_FLAG1 bit null,
USER_FLAG2 bit null,
USER_FLAG3 bit null,
USER_FLAG4 bit null,
USER_FLAG5 bit null,

USER_FLOAT1 float null,
USER_FLOAT2 float null,
USER_FLOAT3 float null,
USER_FLOAT4 float null,
USER_FLOAT5 float null

คอลัมน์ 1 และ 2 ในแต่ละประเภทมีการใช้งานอย่างหนัก แต่เริ่มจากหมายเลข 3 ประเภทของกิจกรรมน้อยมากที่จะให้ข้อมูลจำนวนมากนี้ ดังนั้นผมจึง desided คอลัมน์เครื่องหมาย 3-5 SPARSEในแต่ละประเภท

ฉันไม่วิเคราะห์บางครั้งแรกและเห็นว่าจริงอย่างน้อย 80% ของข้อมูลในแต่ละคอลัมน์เหล่านั้นnullและในบาง 100% nullของข้อมูล อ้างอิงถึง40% เงินฝากออมทรัพย์ตารางเกณฑ์ , SPARSEจะเป็นชัยชนะอันยิ่งใหญ่กับพวกเขา

ดังนั้นฉันจึงไปและนำไปใช้SPARSEกับคอลัมน์ 3-5 ในแต่ละกลุ่ม ตอนนี้ตารางของฉันใช้พื้นที่ข้อมูลประมาณ 1.8Gb ตามที่รายงานโดยsp_spaceusedก่อนที่จะแยกเป็น 1Gb

ฉันพยายามdbcc cleantableแต่ก็ไม่มีผล
จากนั้นdbcc shrinkdatabaseไม่มีผลกระทบใด ๆ

งงงวยฉันลบSPARSEและทำซ้ำdbccs ขนาดของโต๊ะยังคงอยู่ที่ 1.8Gb

สิ่งที่ช่วยให้?


จะพยายามทำซ้ำ เพียงใส่ในกรณีที่สร้างความแตกต่างใด ๆ คือตารางกองหรือมีดัชนีกลุ่ม?
Martin Smith

@MartinSmith rowid int not null identity(1,1) primary key clusteredจะมีดัชนีคลัสเตอร์
GSerg

คำตอบ:


14

คุณต้องสร้างดัชนีคลัสเตอร์ใหม่อีกครั้งหลังจากทำให้คอลัมน์กระจัดกระจาย คอลัมน์ที่ถูกดร็อปยังคงอยู่ในหน้าข้อมูลจนกว่าคุณจะทำสิ่งนี้ตามที่เห็นได้โดยใช้แบบสอบถามกับsys.system_internals_partition_columnsหรือใช้DBCC PAGE

SET NOCOUNT ON;
CREATE TABLE Thing 
(
ThingId int IDENTITY CONSTRAINT PK PRIMARY KEY,
USER_CHAR1 nvarchar(150) null,
USER_CHAR2 nvarchar(150) null,
USER_CHAR3 nvarchar(150) null,
USER_CHAR4 nvarchar(150) null,
USER_CHAR5 nvarchar(150) null
)
INSERT INTO Thing
SELECT REPLICATE('A',150),
       CASE WHEN number % 5 = 1 THEN REPLICATE('A',150) END,
       CASE WHEN number % 5 = 2 THEN REPLICATE('A',150) END,
       CASE WHEN number % 5 = 3 THEN REPLICATE('A',150) END,              
       CASE WHEN number % 5 = 4 THEN REPLICATE('A',150) END
FROM master..spt_values   

EXEC sp_spaceused 'Thing'

ALTER TABLE dbo.Thing ALTER COLUMN USER_CHAR2 ADD SPARSE
ALTER TABLE dbo.Thing ALTER COLUMN USER_CHAR3 ADD SPARSE
ALTER TABLE dbo.Thing ALTER COLUMN USER_CHAR4 ADD SPARSE
ALTER TABLE dbo.Thing ALTER COLUMN USER_CHAR5 ADD SPARSE

DECLARE @DynSQL NVARCHAR(MAX);

SELECT @DynSQL =  'DBCC TRACEON (3604);
                   DBCC PAGE(0, ' + LEFT(file_id,10) + ', ' + LEFT(page_id,10) + ', 3); 
                   DBCC TRACEOFF(3604); ' 
FROM Thing
CROSS APPLY sys.fn_PhysLocCracker(%%physloc%%)
WHERE ThingId=76

EXEC(@DynSQL)    

SELECT pc.*
FROM sys.system_internals_partition_columns pc
JOIN sys.partitions p on p.partition_id=pc.partition_id
WHERE p.object_id = object_id('Thing')
AND pc.is_dropped=1

 EXEC sp_spaceused 'Thing'

ALTER INDEX PK ON Thing REBUILD;    

SELECT @DynSQL =  'DBCC TRACEON (3604);
                   DBCC PAGE(0, ' + LEFT(file_id,10) + ', ' + LEFT(page_id,10) + ', 3); 
                   DBCC TRACEOFF(3604); ' 
FROM Thing
CROSS APPLY sys.fn_PhysLocCracker(%%physloc%%)
WHERE ThingId=76

EXEC(@DynSQL)    

SELECT pc.*
FROM sys.system_internals_partition_columns pc
JOIN sys.partitions p on p.partition_id=pc.partition_id
WHERE p.object_id = object_id('Thing')
AND pc.is_dropped=1

EXEC sp_spaceused 'Thing'

DROP TABLE Thing 

1
น่ากลัว เราควรถือว่าเป็นข้อผิดพลาดในเอกสารหรือไม่? "โปรแกรมฐานข้อมูลเซิร์ฟเวอร์ SQL ใช้ขั้นตอนต่อไปนี้เพื่อให้การเปลี่ยนแปลงนี้สำเร็จ: 1) เพิ่มคอลัมน์ใหม่ในตารางในขนาดและรูปแบบการจัดเก็บใหม่ 2) สำหรับแต่ละแถวในตารางอัพเดตและคัดลอกค่าที่เก็บไว้ในแบบเก่า คอลัมน์ไปยังคอลัมน์ใหม่ 3) ลบคอลัมน์เก่าออกจากสคีมาของตาราง 4) สร้างตารางใหม่เพื่อเรียกคืนพื้นที่ที่คอลัมน์เก่าใช้ "
GSerg

3
@GSerg - Ah ใช่ เห็นด้วยดูเหมือนจุดที่ 4 ไม่ถูกต้องแล้ว เนื่องจากคุณกำลังทำสิ่งนี้เป็นเวลา 12 คอลัมน์คุณจะไม่ต้องการให้การสร้างใหม่เกิดขึ้นโดยปริยายสำหรับแต่ละคอลัมน์ แต่ดูเหมือนว่าพฤติกรรมนั้นถูกต้อง แต่ไม่ใช่เอกสาร
Martin Smith

1
@SQLKiwi - ขอบคุณ เสร็จสิ้น
Martin Smith
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.