ALTER INDEX ALL REBUILD ใช้พื้นที่บันทึกธุรกรรมมากขึ้นด้วยรูปแบบการกู้คืนข้อมูลที่ง่ายกว่าการสร้างดัชนีแต่ละรายการใหม่หรือไม่


18

การดำเนินการ "ALTER INDEX ALL REBUILD" ใน SQL Server 2012 ล้มเหลวเนื่องจากบันทึกธุรกรรมหมดพื้นที่ ดัชนีไม่เคยถูกจัดระเบียบใหม่หรือสร้างใหม่ดังนั้นการกระจายตัวจึงมากกว่า 80% สำหรับเกือบทั้งหมด

DB ใช้รูปแบบการกู้คืนอย่างง่าย ฉันสันนิษฐานว่าต่อไปนี้การดำเนินการแต่ละดัชนีดำเนินการโดยรูปแบบ "ALL" ของคำสั่งข้อมูลบันทึกธุรกรรมจะถูกล้างออกก่อนที่จะสร้างดัชนีครั้งต่อไป นั่นเป็นวิธีการใช้งานจริงหรือดัชนีสร้างใหม่ราวกับว่าพวกเขาเป็นส่วนหนึ่งของการทำธุรกรรมเดียว?

กล่าวอีกนัยหนึ่งฉันสามารถลดการเติบโตของบันทึกธุรกรรมโดยการเขียนสคริปต์เพื่อดำเนินการสร้างใหม่ทีละรายการหรือไม่ มีปัจจัยอื่น ๆ ที่ต้องพิจารณาอีกหรือไม่?


2
หากไม่ระบุข้อมูลที่ชัดเจนไปในทางตรงกันข้ามฉันจะสมมติว่าคำสั่ง SQL เฉพาะจะถูกพิจารณาว่าเป็นธุรกรรมอะตอมมิกเดียวโดยเอ็นจิน DB ในกรณีนี้คุณสามารถทดสอบทฤษฎีได้อย่างง่ายดาย ใช้ดัชนีที่ใหญ่ที่สุดของคุณแล้วลองสร้างมันขึ้นมาใหม่ หากประสบความสำเร็จแสดงว่ามีเหตุผลพอที่จะสมมติว่าบันทึกกำลังรวบรวมข้อมูลจากการสร้างใหม่หลายครั้ง หากล้มเหลวคุณต้องเพิ่มพื้นที่สำหรับบันทึก (เนื่องจากคุณมีปัญหาอย่างใดอย่างหนึ่ง) หรือคุณต้องพยายามจัดระเบียบดัชนีนั้นใหม่แทนที่จะสร้างใหม่ (ถ้าคุณไม่สามารถเพิ่มพื้นที่สำหรับ t- log)
RDFozz

ใช่ความคิดนั้นเกิดขึ้นกับฉันเช่นเดียวกับที่ฉันพิมพ์เสร็จ (เอฟเฟกต์เป็ดยาง) แต่ฉันคิดว่ามันจะเป็นการดีที่สุดที่จะได้รับการยืนยัน ฉันไม่ต้องการทดสอบกับสภาพแวดล้อมนี้ดังนั้นฉันอาจจะเพิ่มพื้นที่ลงในบันทึกอย่างใดอย่างหนึ่ง
Google Fail

คำตอบ:


16

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

1) การล้างบันทึก: โมเดลการกู้คืน SIMPLE ไม่ได้ล้างบันทึกหลังจากทำธุรกรรมทุกครั้ง แต่ที่จุดตรวจสอบ ( ลิงก์สำหรับข้อมูลเพิ่มเติม)

2a) การสร้างใหม่ทั้งหมด: ใช่การสร้างใหม่ทั้งหมดทำงานเป็นธุรกรรมเดียว ดัชนีจะสร้างใหม่ภายในมีการทำธุรกรรมของตัวเอง แต่การดำเนินการโดยรวมยังไม่ได้รับการยืนยันจนกว่าจะสิ้นสุด ใช่คุณอาจ จำกัด การเติบโตของไฟล์บันทึกโดยสร้างดัชนีแต่ละรายการขึ้นใหม่ (และอาจออกคำสั่ง CHECKPOINT

2b) พิสูจน์! ที่นี่มีสคริปต์สาธิต (สร้างขึ้นในปี 2016 dev) ก่อนอื่นให้ตั้งค่าการทดสอบ db ด้วยตารางและดัชนี:

USE master
GO

CREATE DATABASE Test_RebuildLog
GO

ALTER DATABASE Test_RebuildLog
SET RECOVERY SIMPLE
GO

USE Test_RebuildLog
GO

CREATE TABLE IndexTest
(ID int identity(1,1),
a char(1),
b char(1))

CREATE CLUSTERED INDEX CIX_IndexTest_ID ON IndexTest(ID)
CREATE INDEX IX_IndexTest_a ON IndexTest(a)
CREATE INDEX IX_IndexTest_b ON IndexTest(b)

INSERT IndexTest
(a,b)
VALUES ('a','b'),('z','y'),('s','r')

ตอนนี้คุณสามารถเปรียบเทียบกิจกรรมการบันทึกระหว่างการสร้างใหม่ทั้งหมดและสร้างใหม่ทีละรายการ

CHECKPOINT
GO
ALTER INDEX ALL ON IndexTest REBUILD

SELECT *
FROM sys.fn_dblog(NULL,NULL)
WHERE Operation = 'LOP_COMMIT_XACT'
OR Operation = 'LOP_BEGIN_XACT'
GO

CHECKPOINT
GO
ALTER INDEX CIX_IndexTest_ID ON IndexTest REBUILD
ALTER INDEX IX_IndexTest_a ON IndexTest REBUILD
ALTER INDEX IX_IndexTest_b ON IndexTest REBUILD

SELECT *
FROM sys.fn_dblog(NULL,NULL)
WHERE Operation = 'LOP_COMMIT_XACT'
OR Operation = 'LOP_BEGIN_XACT'
GO

สังเกตว่าธุรกรรมที่เปิดครั้งแรก (รหัสธุรกรรม 0000: 000002fa สำหรับฉัน) ไม่ได้ถูกส่งไปจนกว่าจะสิ้นสุด REBUILD ALL แต่สำหรับการสร้างดัชนีทีละดัชนีพวกเขาจะดำเนินการอย่างต่อเนื่อง


ว้าวขอบคุณสำหรับการตอบรับที่ละเอียดมาก ๆ ! นั่นเป็นวิธีที่ยอดเยี่ยมในการดูว่าเกิดอะไรขึ้นภายใต้ประทุนเพื่อพูด
Google Fail

อธิบายอย่างดี
Ramakant Dadhichi

4

นี่เป็นธุรกรรมเดียว


6
ยินดีต้อนรับสู่ DBA.SE! โดยทั่วไปคำตอบที่ดีที่สุดไม่ใช่คำยืนยันง่ายๆ แต่ได้รับการสนับสนุนจากข้อมูลจากเอกสารหรือบทความหรือประสบการณ์ส่วนตัวที่มักจะพิสูจน์คำตอบที่ระบุ คุณสามารถขยายคำตอบของคุณเพื่อให้การสนับสนุนประเภทนั้นได้หรือไม่?
RDFozz

2
@RDFozz Fair แสดงความคิดเห็น แต่คุณดูโปรไฟล์ของ Pedroหรือไม่ การเข้าถึงซอร์สโค้ดอาจถือว่ามีอำนาจมากกว่าประสบการณ์ส่วนตัวหรือเอกสาร :-)
Aaron Bertrand

3
@AaronBertrand - ฉันยอมรับว่าฉันไม่ได้ แน่นอนฉันคิดว่าการเป็นส่วนหนึ่งของทีม SQL Server จะมีสิทธิ์ได้แน่นอน ถึงกระนั้นก็มีมูลค่าอ้างอิงที่ในคำตอบ +1 ไม่ว่าในกรณีใด
RDFozz

3

คำถามเล็กน้อยสำหรับการสร้างแบบออฟไลน์ แน่นอนเป็นธุรกรรมเดียว ลองนึกภาพความเสียหายที่จะเกิดขึ้นหากการดำเนินการแยกดัชนีแต่ละรายการออกเป็นธุรกรรมของตัวเองเนื่องจากจะต้องปลดล็อกเมื่อคอมมิชชันแล้วทำการรับใหม่อีกครั้ง ในขณะที่การปลดล็อคตาราง SCH-M ที่สำคัญถูกปล่อยออกมาดัชนีอาจถูกทิ้งและดัชนีใหม่สามารถสร้างขึ้นได้คำสั่งจะจัดการกรณีดังกล่าวอย่างไร ไม่ต้องพูดถึงตารางที่อาจจะลดลงและแม้จะถูกสร้างขึ้นใหม่ระหว่างการทำธุรกรรมทั้งสอง! รวมถึงกรณีเมื่อตารางได้รับการลดลงและตารางที่แตกต่างกันได้รับการสร้างด้วย ID วัตถุเดียวกัน (ใช่มันสามารถเกิดขึ้นได้) ...

ถ้าคุณเพิ่มคำถามเพื่อบอกว่าจะเกิดอะไรขึ้นถ้าการสร้างดัชนีใหม่เป็นการสร้างออนไลน์ มันเป็นธุรกรรมเดียวหรือหลายรายการ? คำตอบที่มีความซับซ้อนเช่นมีจริงหลายภายในการทำธุรกรรมที่เกี่ยวข้องกับ อย่างไรก็ตามจุดสำคัญคือว่ามีธุรกรรมการทำโค้งโดยรวมที่ครอบคลุมการดำเนินการทั้งหมด (คำสั่ง ALTER) และหมุดนี้เข้าสู่ระบบสถานที่ (ไม่สามารถตัดทอน) ดังนั้นการดำเนินงานจะต้องมีการวางแผนตามเพื่อให้ข้อมูล ~ 1.6x ขนาดสำหรับโหมดการกู้คืนแบบเต็มหรือขนาดข้อมูล 0.2x สำหรับโหมด BULK_LOGGED / SIMPLE ดูกระดาษที่เชื่อมโยงเพื่อดูรายละเอียดเพิ่มเติม

คุณสามารถยืนยันว่าเหตุใดการสร้างออฟไลน์จึงไม่ใช้ธุรกรรมภายในเดียวกันกับโหมดออนไลน์และแยกการดำเนินการออก ปัญหาที่ฉันพูดถึงเกี่ยวกับตารางที่มีการเปลี่ยนแปลง / ลดลงระหว่างการดำเนินการดัชนีแต่ละรายการ (เช่น. ตาราง 'ความมั่นคงของสคีมา') ยังคงต้องการให้มีธุรกรรมที่ครอบคลุมซึ่งเก็บ SCH-S ไว้บนตารางตลอดระยะเวลาของคำสั่ง เนื่องจากธุรกรรมนี้ต้องเก็บ SCH-S ไว้ในระหว่างการกู้คืนจึงจะต้องมีการบันทึกและเช่นนั้นจะมีบันทึกบันทึก BEGIN XACT ที่จะตรึงบันทึกและป้องกันการตัดปลายตลอดระยะเวลาของคำสั่ง ฉันรู้ว่าปัญหานี้กำลังได้รับการแก้ไขในกรอบเวลา SQL 2016-2017 (เนื่องจากปัญหาขนาดบันทึก SQL Azure) แต่ฉันไม่แน่ใจว่ามีการดำเนินการใดบ้าง ดูเหมือนว่าอยู่ในภาพตัวอย่างในขณะนี้:ดำเนินการต่อออนไลน์ดัชนีสร้างเป็นตัวอย่างในที่สาธารณะสำหรับ SQL Server 2017 CTP 2.0


0

ใช่ฉันมีปัญหาเดียวกันกับตารางที่มีขนาดใหญ่มาก เมื่อใดก็ตามที่ฉันออก ALTER INDEX ALL บันทึกธุรกรรมจะเพิ่มขึ้นมาก แต่ถ้าออก ALTER INDEX ทีละรายการการใช้พื้นที่บันทึกจะน้อยกว่า


0

การตอบสนองก่อนหน้าโดย Remus ว่าการสร้างดัชนีออนไลน์ต้อง 1.6 เท่าขนาดดัชนีภายใต้โหมดการกู้คืนแบบเต็มไม่ถูกต้อง สัดส่วนของพื้นที่การบันทึกธุรกรรมที่จำเป็นในการสร้างดัชนีออนไลน์ภายใต้ FULL อาจสูงกว่ามากและเราสังเกตขนาดของดัชนีหลายครั้งโดยเฉพาะอย่างยิ่งเมื่อดัชนีที่ถูกสร้างใหม่ถูกบีบอัดเนื่องจากการบันทึกธุรกรรมไม่ได้ถูกบีบอัด สิ่งนี้เพียงอย่างเดียวควรทำให้ชัดเจนว่าการบันทึกธุรกรรมในระหว่างการสร้างออนไลน์ภายใต้ FULL อาจมีขนาดอย่างน้อยสองสามเท่าของดัชนี เพิ่มค่าใช้จ่ายในบันทึก tlog ซึ่งไม่ได้รับการบันทึกไว้อย่างครบถ้วนโดย Microsoft แต่มักประมาณไว้ที่ 60 ไบต์ต่อแถวและขนาดสัดส่วนของการบันทึกในระหว่างการสร้างดัชนีออนไลน์ภายใต้การกู้คืนแบบเต็มอาจมีขนาดเท่าของดัชนีที่สร้างใหม่ ดัชนีถูกบีบอัด


-1

Rdfozz นั้นถูกต้องซึ่งเป็นวิธีที่ดีที่สุดในการตัดสินใจว่าดัชนีที่ใหญ่ที่สุดของคุณสามารถสร้างใหม่ได้หรือไม่ตามหน่วยเก็บข้อมูลปัจจุบัน เพียงเรียกใช้dm_exec_requestsในขณะที่การดำเนินการเกิดขึ้น (หรือ SQL Profiler) เพื่อดูว่าดัชนีทั้งหมดจะถูกสร้างใหม่ ฉันจะพิจารณาเปลี่ยนรูปแบบการกู้คืนเป็นบันทึกจำนวนมาก นี่คือสิ่งที่ฉันทำและมีการสำรองข้อมูลบันทึกธุรกรรมระหว่างที่หน้าต่างยังคงอยู่ ดูบทความด้านล่าง https://technet.microsoft.com/en-us/library/ms191484(v=sql.105).aspx


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

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