ผลกระทบใดที่จะลดขนาดของคอลัมน์ varchar ที่มีต่อไฟล์ฐานข้อมูล


15

เรามีตารางจำนวนหนึ่งในฐานข้อมูลของเราที่มีVARCHAR(MAX)คอลัมน์ที่VARCHAR(500)(หรือบางสิ่งที่เล็กกว่ามาก) จะพอเพียง โดยธรรมชาติฉันต้องการทำความสะอาดสิ่งเหล่านี้และทำให้ขนาดลงไปถึงระดับที่สมเหตุสมผลยิ่งขึ้น 'วิธีการ' ที่จะทำสิ่งนี้ฉันเข้าใจ: คำถามของฉันคือสิ่งที่จะแก้ไขคอลัมน์เหล่านี้ทำในหน้าและที่มีอยู่ในดิสก์? (มีข้อมูลมากมายเกี่ยวกับสิ่งที่เกิดขึ้นเมื่อคุณขยายคอลัมน์ แต่มีปัญหาในการค้นหาข้อมูลเกี่ยวกับสิ่งที่เกิดขึ้นเมื่อคุณย่อขนาด)

ตารางบางตัวมีจำนวนแถวน้อยมากดังนั้นฉันจึงไม่กังวลเกี่ยวกับค่าใช้จ่ายในการเปลี่ยนแปลง แต่บางตารางมีขนาดค่อนข้างใหญ่และฉันกังวลว่าอาจมีการจัดระเบียบใหม่และทำให้การบล็อก / การหยุดทำงานเป็นจำนวนมาก ในทางปฏิบัติฉันต้องการวิธีประมาณหน้าต่างการบำรุงรักษา โดยทั่วไปฉันต้องการทำความเข้าใจให้ดีขึ้นว่าเอ็นจิ้นฐานข้อมูลทำงานอย่างไรในกรณีนี้

ขอบคุณล่วงหน้า!

แก้ไข:

ฉันมีตาราง 20 ตารางที่ฉันดู แต่มีเพียงครึ่งหนึ่งเท่านั้นที่มีจำนวนแถวมากกว่า 1,000 ใหญ่ที่สุดมีเกือบล้านแถว ผู้กระทำความผิดที่เลวร้ายที่สุดคือตารางที่มี 350,000 แถวและสี่VARCHAR(MAX)คอลัมน์ที่สามารถหดได้ถึงVARCHAR(500)ระดับ

คำตอบ:


12

สิ่งแรกสิ่งแรก: มีข้อมูลเท่าใดในตาราง จำนวนแถวและขนาดของตาราง?

ข้อสอง: คุณสามารถสำรองและกู้คืนตารางนี้ไปยังเซิร์ฟเวอร์ทดสอบและเรียกใช้คำสั่งแก้ไขเพื่อดูผลกระทบ (สมมติว่ามันไม่สามารถทำได้เนื่องจากตารางมีขนาดใหญ่เกินไปที่จะพอดีกับระบบที่ไม่ได้ใช้งานจริง)? ฉันมักจะพบว่าการทดสอบในสภาพแวดล้อมของฉันนั้นแม่นยำกว่าคำแนะนำจาก interwebs เนื่องจากมีหลายปัจจัยที่สามารถมีอิทธิพลต่อผลลัพธ์ที่อาจไม่ได้ให้ไว้ในคำถามเพียงเพราะไม่รู้ว่าปัจจัยเหล่านั้นอาจส่งผลต่อผลลัพธ์

ประการที่สาม: การเพิ่มขนาดของฟิลด์ความยาวผันแปรคือ (สมมติว่าคุณไม่ได้เกินขีด จำกัด 8060 ไบต์) การดำเนินการ meta-data อย่างง่ายเนื่องจากไม่มีข้อมูลจริงที่จะเปลี่ยนแปลงสำหรับการดำเนินการดังกล่าว แต่ในทางกลับกันการลดขนาดของเขตข้อมูลความยาวผันแปรแม้จะเป็นสิ่งที่จะเห็นได้ชัดมากกว่าการทำงานไม่ใช่การเปลี่ยนแปลง meta-data อย่างง่ายเพราะ SQL Server ไม่ทราบก่อนทำการสแกนแถวทั้งหมด ขนาดที่ร้องขอใหม่นั้นถูกต้อง

ดังนั้น: ใช่สิ่งนี้จะล็อคตารางเป็นระยะเวลาหนึ่ง ใช้เวลาเท่าไหร่ นี่คือการทดสอบที่ฉันเพิ่งทำ:

จากการทดสอบอื่น ๆ ฉันมีตารางที่มีINT NOT NULLเขตข้อมูลเดียวและ 1 ล้านแถว ฉันคัดลอกไปยังตารางใหม่เพื่อวัตถุประสงค์ในการทำแบบทดสอบนี้ผ่าน:

SELECT *, CONVERT(NVARCHAR(MAX), NEWID()) AS [StringField]
INTO dbo.ResizeTest
FROM dbo.ClusteredUnique;

วิธีนี้ผมก็เริ่มต้นด้วยสถานการณ์ที่คล้ายกันของการมีMAXฟิลด์ (ฉันเพิ่งรู้ว่าคุณมีVARCHARและฉันใช้NVARCHARแต่ที่ไม่ควรปรับเปลี่ยนพฤติกรรมที่ผมเห็น) 500ที่ฉันก็จะเปลี่ยนไป และมีข้อมูลอยู่ในนั้นที่สามารถบรรจุได้ไม่เกิน 500 ตัวอักษร ใช้เวลาไม่กี่นาที

จากนั้นฉันก็วิ่ง:

ALTER TABLE dbo.ResizeTest ALTER COLUMN [StringField] NVARCHAR(500) NULL;

และนั่นใช้เวลาเพียง 11 นาที

ฉันเพิ่งทดสอบซ้ำอีกครั้งคราวนี้วาง[ResizeTest]ตารางและเปลี่ยนทั้งสองNVARCHARเป็นVARCHARเพียงเพื่อให้แน่ใจว่าฉันเปรียบเทียบแอปเปิ้ลกับสิ่งที่อย่างน้อยดูเหมือนแอปเปิ้ล ;-)

การสร้างตารางเริ่มต้นใช้เวลา 20 วินาทีในขณะที่ALTER TABLEใช้เวลา 2 นาที

ดังนั้นในแง่ของการประเมินการหยุดทำงานนั้นยากที่จะทำเพราะมันขึ้นอยู่กับความเร็วของดิสก์ I / O ไม่ว่าการดำเนินการเติบโตอัตโนมัติจะต้องเกิดขึ้นกับไฟล์ข้อมูลและ / หรือบันทึกธุรกรรม ฯลฯ หรือไม่ อาจเป็นส่วนใหญ่ของสาเหตุที่การทดสอบครั้งแรกของฉันใช้เวลา 11 นาทีในการเปลี่ยนแปลงและครั้งที่สองแม้จะมีVARCHARขนาดครึ่งหนึ่งของNVARCHARข้อมูลใช้เวลาเพียง 2 นาทีเท่านั้น (เช่นไฟล์ถูกสร้างไว้ล่วงหน้า ณ จุดนั้น) แต่ถึงกระนั้นคุณควรจำไว้ว่าการทดสอบของฉันทำงานบนแล็ปท็อปของฉันซึ่งไม่ใช่ดิสก์ที่เร็วที่สุด แต่มันก็เป็นเพียง 1 ล้านแถวของคอลัมน์ขนาดเล็ก 2 คอลัมน์ (22 หรือมากกว่าไบต์ต่อแถว)

และเมื่อคุณถามว่ามันจะทำอะไรกับหน้าข้อมูลนี่คือคำตอบของคุณ ฉันได้อย่างsp_spaceusedหลังจากการสร้างตารางหลังจากทำและทำหลังALTER COLUMN ALTER TABLE dbo.ResizeTest REBUILD;ผลลัพธ์ (ตัวเลขต่อไปนี้เป็นไปตามการทดสอบครั้งที่สองที่ใช้VARCHARไม่ใช่การทดสอบครั้งแรกที่ใช้NVARCHAR):

After initial table creation:        526,344 KB
After ALTER COLUMN VARCHAR(500):   1,031,688 KB  <--- !! Yikes!!
After ALTER REBUILD:                 526,472 KB

หากคุณมีความกังวลเกี่ยวกับการทำให้การดำเนินการเป็นไปได้ในระยะเวลาอันสั้นให้ตรวจสอบบทความที่ฉันเขียนเกี่ยวกับการทำเช่นนั้น: ปรับโครงสร้างตาราง 100 ล้านแถว (หรือมากกว่า) ในไม่กี่วินาที SRSLY! (ต้องลงทะเบียนฟรี)


2
ดังนั้นฉันจึงคัดลอกตารางที่แย่ที่สุดไปยังอินสแตนซ์ในพื้นที่ของฉัน (เช่นดิสก์ที่ช้ากว่าและ 1/3 แกน) ฉันALTERแก้ไขแต่ละคอลัมน์อย่างต่อเนื่อง - แต่ละการกระทำใช้เวลาน้อยกว่าหนึ่งวินาที ตามเวลาที่พวกเขาทำตารางมีขนาดสองเท่า แต่เมื่อฉันทำREBUILD(ซึ่งก็เป็นการดำเนินการย่อยที่สอง) ตารางกลับไปที่ขนาดเดิม
nateirvin

@nateirvin ดีที่ได้ยิน คุณสามารถเพิ่มความเร็วในALTER TABLEการดำเนินการได้โดยทำทุกฟิลด์ในนัดเดียวโดยแยกแต่ละคอลัมน์ด้วยเครื่องหมายจุลภาค หากการทำธุรกรรมมีขนาดใหญ่เกินไปให้แบ่งตารางออกเป็น 2 คำสั่ง ALTER ของครึ่งหนึ่งของแต่ละคอลัมน์ และขึ้นอยู่กับว่าโต๊ะใหญ่แค่ไหนคุณสามารถสร้าง REBUILD ระหว่างสองคำสั่ง ALTER มีบางอย่างให้เล่นด้วย นอกจากนี้โปรดทราบว่าการดำเนินการอาจใช้ล็อคสคีมาเป็นระยะเวลาซึ่งจะป้องกันการเข้าถึงตารางทั้งหมด
โซโลมอน Rutzky

1
ฉันALTERแยกกันเพื่อที่ฉันจะได้สามารถติดตามการเปลี่ยนแปลงขนาดระหว่างกันได้ แต่ดีที่จะรู้ ขอบคุณ!
nateirvin

1

จากสิ่งที่ฉันได้รวบรวมการเรียกใช้คำสั่งแก้ไขไม่ควรใช้เวลานานมากที่ตารางไม่ได้ถูกล็อคโดยกระบวนการอื่น ตาม gbn เป็นเพียงการเปลี่ยนแปลงข้อมูลเมตา: /programming/7261909/is-it-bad-to-use-alter-table-to-resize-a-varchar-column-to-a-larger -ขนาด

นอกจากนี้สำหรับวิธีการจัดเก็บดูเหมือนว่า SQL Server จะเก็บข้อมูล varchar ในหน้าขนาด 8k จนกว่าจะเต็มหน้าทั้งหมดซึ่ง ณ จุดนี้จะแทนที่ด้วยตัวชี้และเก็บไว้เป็น BLOB

ฉันสมมติว่าเมื่อคุณเปลี่ยนความยาวคุณจะไม่ตัดทอนบันทึกใด ๆ ถ้าเป็นอย่างนั้นข้อมูลสูงสุดที่คุณแปลงเป็น varchar (500) ควรมีความยาวสูงสุด 502 ไบต์และไม่ควรมีตัวชี้

ดังนั้นเรื่องสั้นที่สั้นมากไม่ควรเปลี่ยนแปลงตราบใดที่คุณไม่ได้ตัดทอนข้อมูลใด ๆ


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