ฉันต้องการลดขนาดฐานข้อมูลของฉัน - ฉันเพิ่งปลดปล่อยพื้นที่มาก


35

คำถามนี้ถูกถามในรูปแบบต่าง ๆ ที่นี่ แต่คำถามก็ยังลงไปที่:

ฉันรู้ว่าการลดขนาดฐานข้อมูลมีความเสี่ยง ในกรณีนี้ฉันได้ลบข้อมูลจำนวนมากและฉันจะไม่ใช้มันอีก

  • ฉันจะลดขนาดฐานข้อมูลของฉันได้อย่างไร ฉันจะลดขนาดไฟล์อะไร
  • สิ่งที่ฉันควรพิจารณาเมื่อทำสิ่งนี้คืออะไร?
  • ฉันควรทำอะไรหลังจาก
  • ถ้าเป็นฐานข้อมูลขนาดใหญ่ล่ะ ฉันสามารถหดมันทีละน้อยกว่าได้ไหม?

2
ฉันต่อสู้กับเรื่องนี้มานานแล้ว: dba.stackexchange.com/questions/47310/…ฉันพยายามสรุปประสบการณ์ของฉันในคำตอบของฉัน
Csaba Toth

คำตอบ:


30

บาง Caveats เริ่มต้น:

  1. เป็นที่ทราบกันโดยทั่วไปว่าวิธีปฏิบัติที่เลวร้ายที่สุดที่เคยลดขนาดฐานข้อมูลการผลิตหรือไฟล์ข้อมูล (ไฟล์บันทึกเป็นปัญหาอื่นตามที่คำถามนี้พูดถึง) ฉันแนะนำให้คนไม่ย่อฐานข้อมูลในโพสต์บล็อกเช่นนี้ที่ฉันพูดถึง "ขนาดที่เหมาะสม" และการวางแผนที่ดี ฉันไม่ได้มีคนเดียว ( พอล Randal , Brent Ozarเพียงเพื่อให้การเชื่อมโยงคู่มากขึ้น) การหดขนาดไฟล์ข้อมูลหรือดัชนีส่วนย่อยของฐานข้อมูลนั้นช้าและลำบากกับทรัพยากรของคุณสามารถทำให้ระบบของคุณแย่ลงและเป็นสิ่งที่ต้องทำโดยทั่วไป
  2. ในกรณีนี้เราทุกคนรู้ว่าความเสี่ยงอยู่ที่นั่นเราพร้อมที่จะรับมือกับมัน แต่เราได้ปลดปล่อยพื้นที่มากมายที่เรารู้ว่าเราจะไม่ต้องการอีกต่อไป ดังนั้นในกรณีเฉพาะประเภทนี้การย่อขนาดทำให้เรารู้สึกว่าเป็นหนึ่งในตัวเลือกของเรา

หากคุณได้อ่านเกี่ยวกับความกังวลและความเสี่ยงและคุณยังคงต้องทำหดนี้เนื่องจากคุณปลดปล่อยอย่างมีนัยสำคัญจำนวนของพื้นที่หวังว่าส่วนที่เหลือของคำตอบนี้จะช่วยให้คุณออก แต่พิจารณาความเสี่ยง

มีสองวิธีหลักที่สองพิจารณาที่นี่:

1. ) ลดขนาด ใช่ทำการย่อขนาดที่แท้จริง - ลองใช้DBCC SHRINKFILEแทนคุณDBCC SHRINKDATABASEสามารถควบคุมสิ่งที่หดตัวได้และวิธีการ สิ่งนี้จะทำให้ประสิทธิภาพลดลงอย่างแน่นอน - เป็นการทำงานขนาดใหญ่ที่ใช้ IO มาก คุณสามารถที่อาจได้รับไปกับ shrinks ซ้ำกับขนาดของเป้าหมายที่ได้รับความก้าวหน้าที่มีขนาดเล็ก

นี่คือตัวอย่าง "A. )" ในDBCC SHRINKFILEลิงค์ด้านบน.. datafile กำลังหดเป็นขนาดเป้าหมาย 7MB ในตัวอย่างนี้ รูปแบบนี้เป็นวิธีที่ดีในการย่อขนาดซ้ำ ๆ เนื่องจากหน้าต่างหยุดทำงานช่วย ฉันจะทำสิ่งนี้ในการทดสอบการพัฒนาเพื่อดูว่าประสิทธิภาพการทำงานมีลักษณะอย่างไรและต่ำ / สูงคุณสามารถเพิ่มขึ้นได้อย่างไรและเพื่อกำหนดเวลาที่คาดหวังในการผลิต นี่เป็นการดำเนินการออนไลน์ - คุณสามารถเรียกใช้กับผู้ใช้ในระบบที่เข้าถึงฐานข้อมูลที่กำลังหดตัว แต่จะมีการเสื่อมประสิทธิภาพเกือบรับประกัน ดังนั้นตรวจสอบและดูและดูสิ่งที่คุณทำกับเซิร์ฟเวอร์เลือกช่วงเวลาหยุดทำงานหรือช่วงเวลาที่กิจกรรมเบาลง

USE YourDatabase;
GO
DBCC SHRINKFILE (DataFile1, 7);
GO

โปรดจำไว้เสมอ: - ทุกครั้งที่คุณลดขนาดดัชนีของคุณและควรสร้างดัชนีใหม่หากคุณกำลังจะลดจำนวนชิ้นเป็นระยะเวลานาน ตอนนี้คุณมีค่าใช้จ่ายเกิดขึ้นทุกครั้งหากคุณไม่สามารถทำได้ทั้งหมดในหน้าต่างเดียว

2. ) ฐานข้อมูลใหม่ - คุณสามารถสร้างฐานข้อมูลใหม่และย้ายข้อมูลไปยังฐานข้อมูลได้ คุณจะต้องสคริปต์ฐานข้อมูลที่ว่างเปล่าและกุญแจ, ดัชนี, วัตถุ, procs, ฟังก์ชั่น ฯลฯ ทั้งหมดแล้วย้ายข้อมูลไปยังฐานข้อมูล คุณสามารถเขียนสคริปต์สำหรับสิ่งนี้หรือคุณสามารถใช้เครื่องมือเช่น SQL Data Compare จาก Red Gate หรือผู้ขายรายอื่นด้วยเครื่องมือที่คล้ายกัน นี่คือการติดตั้งเพิ่มเติมในด้านของคุณการพัฒนาและการทดสอบที่มากขึ้นและขึ้นอยู่กับสภาพแวดล้อมของคุณอาจทำให้หน้าต่างการหยุดทำงานของคุณเสียไป แต่ยังมีตัวเลือกให้พิจารณา

เมื่อฉันถูกบังคับให้ลดขนาดฐานข้อมูล ถ้านี่เป็นสภาพแวดล้อมของฉันฉันจะทิ้งพื้นที่สีขาวไว้ในแฟ้มข้อมูลเพราะฉันชอบเป็นหมูดิสก์และเตรียมพร้อมสำหรับการเติบโตในอนาคต / ที่ไม่คาดคิด ดังนั้นผมจะไม่เป็นไรให้กลับพื้นที่ถ้าเราเพียงแค่ลบส่วนใหญ่ของพื้นที่ แต่ฉันไม่เคยไว้วางใจผู้ที่พูดว่า "แต่มันไม่เคยจะเติบโตอีกครั้ง" และยังคงปล่อยให้บางพื้นที่สีขาว เส้นทางที่ฉันอาจจะไปด้วย ( ถอนหายใจ) เป็นวิธีการย่อขนาดถ้าฉันมีหน้าต่างการหยุดทำงานน้อยลงและไม่ต้องการความซับซ้อนในการสร้างฐานข้อมูลเปล่าและย้ายข้อมูลไปยังมัน ดังนั้นฉันจะหดพวงของครั้งเพิ่มขึ้น (อิงจากจำนวนครั้งที่ฉันคิดว่าฉันต้องการที่จะอยู่บนพื้นฐานของการทดสอบของฉันใน dev และขนาดที่ต้องการ. ความก้าวหน้าการเลือกขนาดไฟล์เล็ก) และจากนั้นสร้างดัชนี .. แล้วฉัน' ไม่เคยบอกใครว่าฉันหดฐานข้อมูลของฉัน ;-)


1
ฉันจะเพิ่มกรณีพิเศษว่าถ้าคุณลบข้อมูลจำนวนมากออกจากฮีป (โดยเฉพาะจากกลางฮีป) คุณจะไม่สามารถเรียกคืนพื้นที่นั้นจนกว่าคุณจะเพิ่มดัชนีคลัสเตอร์ลงไป (หวังว่าตลอดไป) จากนั้นปล่อยดัชนีคลัสเตอร์หลังจาก (เปลี่ยนกลับเป็นฮีป) แน่นอนถ้าฮีปถูกตัดทอนอย่างสม่ำเสมอก็ไม่ต้องกังวล แต่ก็ยังมีมูลค่าการกล่าวขวัญ
Jonathan Fite

ใครสามารถอธิบายความหมายของ NOTRUNCATE และ TRUNCATEONLY เห็นได้ชัดว่าหลังไม่จัดเรียงหน้าใหม่และดังนั้นจึงไม่ก่อให้เกิดการกระจายตัวของดัชนี?
David Garcia

4
  1. ฉันจะลดขนาดฐานข้อมูลของฉันได้อย่างไร ฉันจะลดขนาดไฟล์อะไร : คุณสามารถย่อขนาดไฟล์แต่ละไฟล์โดยDBCC SHRINKFILEคำสั่งที่คุณพูดถึง ขึ้นอยู่กับเซิร์ฟเวอร์ของคุณจำนวนไฟล์ที่ฐานข้อมูลของคุณประกอบด้วย ฐานข้อมูลอย่างง่ายมีไฟล์ฐานข้อมูลหนึ่งไฟล์และไฟล์บันทึกธุรกรรมหนึ่งไฟล์
  2. สิ่งที่ฉันควรพิจารณาเมื่อทำสิ่งนี้คืออะไร?: การหดตัวมีผลต่อการกระจายตัวของดัชนีดูจุดที่ 3 นอกจากนี้โปรดทราบว่าคุณไม่ต้องการย่อขนาดไฟล์ฐานข้อมูลให้มีขนาดเล็กที่สุดเท่าที่จะเป็นไปได้เพราะในสภาพแวดล้อมจริงมันจะเติบโตต่อไป ดังนั้นฉันจะปรับขนาด (ในตัวอย่างของคุณคุณให้ 7 เมกะไบต์) ในลักษณะที่คุณปล่อยให้พื้นที่ว่าง 10% -20% ภายในไฟล์ฐานข้อมูลเพราะมันจะถูกเติมในสภาพแวดล้อมการผลิตและคุณสามารถ บันทึกรอบการเติบโตอัตโนมัติบางอย่างเช่นนั้น ดังนั้นจำนวนจริงต้องมีการคำนวณอย่างรอบคอบ นอกจากนี้โปรดทราบว่า "การเพิ่มพื้นที่ว่างขนาดใหญ่" ที่คุณดำเนินการจะขยายไฟล์บันทึกธุรกรรมมากกว่าพื้นที่ที่คุณได้รับภายในไฟล์ DB นอกจากนี้การได้รับพื้นที่จริงที่คุณอาจได้รับจะน้อยกว่าที่คุณคาดหวังทางคณิตศาสตร์! สมมุติว่าคุณปลดปล่อย 12 กิ๊ก
  3. ฉันควรทำอะไรหลังจาก : ดังที่ฉันได้กล่าวไปแล้วก่อนหน้านี้คุณต้องการจัดทำดัชนีใหม่ซึ่งการแตกแฟรกเมนต์ได้รับการบิดเบือนเนื่องจากการเปลี่ยนแปลงของ SHRINK ฉันไม่ได้ทดลองมากพอถ้าคุณต้องการทำอะไรพิเศษเกี่ยวกับสถิติการสืบค้น
  4. ถ้าเป็นฐานข้อมูลขนาดใหญ่ล่ะ ฉันสามารถหดมันทีละน้อยกว่าได้ไหม? การดำเนินการ SHRINK สามารถถูกขัดจังหวะได้ตลอดเวลาและคุณสามารถดำเนินการต่อในภายหลัง ฉันแนะนำให้ทำในฐานข้อมูลออฟไลน์ถ้าเป็นไปได้ โดยการขัดจังหวะและควบคุมมันจะไปข้างหน้าขนาดหดตัวเดียวกันแม้ว่า ในทางทฤษฎีคุณสามารถลดขนาดทีละน้อยลงได้โดยระบุขนาดเป้าหมายที่แคบลงแทนที่จะเป็น 7 เมกะไบต์ แต่ฉันบอกว่าถ้าคุณกำลังแสดงมันในการผลิต อย่างที่คุณเห็นมีปัญหาเกี่ยวกับการกระจายตัวของดัชนีและการเติบโตของบันทึกธุรกรรมที่เป็นไปได้ ดังนั้นฉันจะผ่านเรื่องนี้เพียงครั้งเดียว

เราทุกคนรู้ว่าไม่ควรทำ SHRINK เป็นประจำอยู่แล้ว ฉันพยายามที่จะละทิ้งคำเตือนและคำเตือนที่คุณอาจรู้อยู่ดี สำรองข้อมูลและอย่าทำที่บ้านถ้าเป็นไปได้ :)

โบนัส: ในสภาพแวดล้อมการจำลองแบบถ้าคุณทำเช่นนี้ในฐานข้อมูลผู้เผยแพร่จะไม่ทำให้ฐานข้อมูลสมาชิกลดลง (ซึ่งอาจมีปัญหาขนาดเนื่องจากเป็นรุ่น Express)

ในที่สุดสคริปต์ reindex ของฉัน:

USE YourDBName

DECLARE @TbName VARCHAR(255)
DECLARE @FullTbName VARCHAR(255)
DECLARE @IxName VARCHAR(255)
DECLARE myCursor CURSOR FOR
    SELECT OBJECT_NAME(dmi.object_id) AS TableName,i.name AS IndexName
    FROM sys.dm_db_index_physical_stats(14, NULL, NULL, NULL , 'LIMITED') dmi
    JOIN  sys.indexes i on dmi.object_id = i.object_id and dmi.index_id = i.index_id
    WHERE avg_fragmentation_in_percent > 30
    ORDER BY avg_fragmentation_in_percent
OPEN myCursor
FETCH NEXT FROM myCursor INTO @TbName, @ixName
WHILE @@FETCH_STATUS = 0
BEGIN
    IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES  WHERE TABLE_SCHEMA = 'dba' AND TABLE_NAME = @TbName)
BEGIN
        SET @FullTbName = 'dba.' + @TbName
        IF (@ixName IS NULL)
        BEGIN
            PRINT 'Reindexing Table ' + @FullTbName
            DBCC DBREINDEX(@FullTbName, '', 0)
        END
        ELSE
        BEGIN
             PRINT 'Reindexing Table ' + @FullTbName + ', Index ' + @IxName
             DBCC DBREINDEX(@FullTbName, @IxName, 0)
        END
    END
    FETCH NEXT FROM myCursor INTO @TbName, @ixName
END
CLOSE myCursor
DEALLOCATE myCursor

ตัวแปรเดียวในนี้คือ 14 ซึ่งสามารถรับได้โดยการออก select DB_ID('YourDBName')และสคริปต์จะถือว่าคุณสนใจเฉพาะในตารางใน dba. * schema


2
สำหรับหมายเหตุการสร้างดัชนีใหม่ว่า DBREINDEX นั้นเลิกใช้แล้วใน SQL 2005 แทนที่จะใช้สคริปต์ขนาดใหญ่ที่มีเคอร์เซอร์คุณสามารถใช้: EXEC sp_MSForeachtable @ Command1 = "ALTER INDEX ALL ON ON REBUILD" หวังว่านี่จะช่วยให้ใครบางคน
จูบ

2

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

แต่โดยทั่วไปฉันจะทำทุกสัปดาห์เมื่อฉันคืนค่าการสำรองข้อมูลบนเวิร์กสเตชันของฉันเนื่องจากพื้นที่บนไดรฟ์ SSD ของฉัน โปรดทราบฉันไม่ได้เขียนสคริปต์นี้ แต่พบว่าเมื่อหลายปีก่อน บนฐานข้อมูลอื่น [250 GB] ฉันสร้างแพคเกจ SSIS ที่จะถ่ายโอนตารางที่ฉันต้องการแล้วสร้างดัชนีใหม่สำหรับความรู้สึกที่สดใหม่

DECLARE @DBFileName SYSNAME

DECLARE @TargetFreeMB INT

DECLARE @ShrinkIncrementMB INT

SET @DBFileName = 'Set Name of Database file to shrink'

-- Set Desired file free space in MB after shrink

SET @TargetFreeMB = 500
-- Set Increment to shrink file by in MB
SET @ShrinkIncrementMB = 100

SELECT [FileSizeMB] = convert(NUMERIC(10, 2),
round(a.size / 128., 2)),

[UsedSpaceMB] = convert(NUMERIC(10, 2),

round(fileproperty(a.NAME, 'SpaceUsed') / 128., 2)),

[UnusedSpaceMB] = convert(NUMERIC(10, 2),

round((a.size - fileproperty(a.NAME, 'SpaceUsed')) / 128., 2)),

[DBFileName] = a.NAME

FROM sysfiles a

DECLARE @sql VARCHAR(8000)
DECLARE @SizeMB INT
DECLARE @UsedMB INT

SELECT @SizeMB = size / 128.
FROM sysfiles
WHERE NAME = @DBFileName

SELECT @UsedMB = fileproperty(@DBFileName, 'SpaceUsed') / 128.

SELECT [StartFileSize] = @SizeMB
    ,[StartUsedSpace] = @UsedMB
    ,[DBFileName] = @DBFileName

WHILE @SizeMB > @UsedMB + @TargetFreeMB + @ShrinkIncrementMB

BEGIN
    SET @sql = 'dbcc shrinkfile ( ' + @DBFileName + ', ' + convert(VARCHAR(20), @SizeMB - @ShrinkIncrementMB) + ' ) '

    PRINT 'Start ' + @sql
    PRINT 'at ' + convert(VARCHAR(30), getdate(), 121)

    EXEC (@sql)

    PRINT 'Done ' + @sql
    PRINT 'at ' + convert(VARCHAR(30), getdate(), 121)

    SELECT @SizeMB = size / 128.
    FROM sysfiles
    WHERE NAME = @DBFileName

    SELECT @UsedMB = fileproperty(@DBFileName, 'SpaceUsed') / 128.

    SELECT [FileSize] = @SizeMB
        ,[UsedSpace] = @UsedMB
        ,[DBFileName] = @DBFileName
END

SELECT [EndFileSize] = @SizeMB
    ,[EndUsedSpace] = @UsedMB
    ,[DBFileName] = @DBFileName

SELECT [FileSizeMB] = convert(NUMERIC(10, 2), round(a.size / 128., 2))

    ,[UsedSpaceMB] = convert(NUMERIC(10, 2), round(fileproperty a.NAME, 'SpaceUsed') / 128., 2))

,[UnusedSpaceMB] = convert(NUMERIC(10, 2), round((a.size - fileproperty(a.NAME, 'SpaceUsed')) / 128., 2))

,[DBFileName] = a.NAME

FROM sysfiles a

1

ใบเสนอราคาด้านล่างนี้โดยตรงจาก Microsoft (ใช้กับรุ่น 2008-2016) และให้คำแนะนำว่าควรใช้DBCC SHRINKFILEคำสั่งเมื่อใดและเมื่อใดและอย่างไร

https://msdn.microsoft.com/en-us/library/ms189493.aspx

ปฏิบัติที่ดีที่สุด

พิจารณาข้อมูลต่อไปนี้เมื่อคุณวางแผนที่จะย่อขนาดไฟล์:

  • การดำเนินการย่อขนาดมีประสิทธิภาพมากที่สุดหลังจากการดำเนินการที่สร้างพื้นที่ว่างที่ไม่ได้ใช้จำนวนมากเช่นตารางที่ถูกตัดทอนหรือการดำเนินการตารางแบบเลื่อน
  • ฐานข้อมูลส่วนใหญ่ต้องการพื้นที่ว่างบางส่วนเพื่อให้สามารถใช้งานได้ทุกวัน ถ้าคุณลดขนาดฐานข้อมูลซ้ำ ๆ และสังเกตว่าขนาดฐานข้อมูลขยายตัวอีกครั้งนี่เป็นการระบุว่าจำเป็นต้องใช้พื้นที่ที่ถูกย่อสำหรับการดำเนินการปกติ ในกรณีเหล่านี้การลดขนาดฐานข้อมูลซ้ำเป็นการดำเนินการที่สูญเปล่า
  • การดำเนินการย่อขนาดไม่รักษาสถานะการแตกแฟรกเมนต์ของดัชนีในฐานข้อมูลและโดยทั่วไปจะเพิ่มการแตกแฟรกเมนต์เป็นระดับ นี่เป็นอีกสาเหตุที่ไม่ลดขนาดฐานข้อมูลซ้ำ ๆ
  • ย่อขนาดหลายไฟล์ในฐานข้อมูลเดียวกันตามลำดับแทนพร้อมกัน ความขัดแย้งในตารางระบบอาจทำให้เกิดความล่าช้าเนื่องจากการปิดกั้น
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.