สถาปัตยกรรมดัชนีที่เหมาะสมคืออะไรเมื่อถูกบังคับให้ใช้ IsDeleted (การลบแบบอ่อน)?


17

ขณะนี้เรามีฐานข้อมูลและแอปพลิเคชันที่มีอยู่ซึ่งทำงานได้อย่างสมบูรณ์ ฉันไม่มีความสามารถในการเปลี่ยนสถาปัตยกรรม ณ จุดนี้ วันนี้แต่ละตารางในฐานข้อมูลมีฟิลด์ "IsDeleted" NOT NULL BIT ที่มีค่าเริ่มต้นเป็น '0' เมื่อแอปพลิเคชัน "ลบ" ข้อมูลมันเพียงอัปเดตการตั้งค่าสถานะ IsDeleted เป็น 1

สิ่งที่ฉันมีปัญหาในการทำความเข้าใจคือดัชนีของแต่ละตารางควรมีโครงสร้างอย่างไร ตอนนี้ทุกแบบสอบถาม / เข้าร่วม / ฯลฯ จะดำเนินการตรวจสอบ IsDeleted เป็นมาตรฐานที่นักพัฒนาของเราต้องปฏิบัติตาม ที่ถูกกล่าวว่าฉันพยายามที่จะตรวจสอบว่าดัชนีคีย์หลักคลัสเตอร์ทั้งหมดของฉันในแต่ละตารางจะต้องมีการเปลี่ยนแปลงเพื่อให้รวมถึงคีย์หลักและฟิลด์ BIT IsDeleted นอกจากนี้เนื่องจากทุกแบบสอบถาม / เข้าร่วม / ฯลฯ ต้องใช้การตรวจสอบ IsDeleted เป็นข้อสมมติฐานที่เหมาะสมหรือไม่ที่ดัชนีทุกเดียว (ไม่ใช่คลัสเตอร์ด้วย) ควรรวมเขตข้อมูล IsDeleted เป็นเขตข้อมูลแรกของดัชนีหรือไม่

อีกคำถามหนึ่งที่ฉันมีคือดัชนีรอบตัวกรอง ฉันเข้าใจว่าฉันสามารถใส่ตัวกรองในดัชนีเช่น "WHERE IsDeleted = 0" เพื่อลดขนาดของดัชนี อย่างไรก็ตามเนื่องจากการเข้าร่วม / การสืบค้นทั้งหมดจะต้องใช้การตรวจสอบ IsDeleted นั่นจะป้องกันการใช้ดัชนีที่กรองแล้วหรือไม่ (เนื่องจากมีการใช้คอลัมน์ IsDeleted ในการเข้าร่วม / การสืบค้น)

จำไว้ว่าฉันไม่มีความสามารถในการเปลี่ยนวิธีการ IsDeleted

คำตอบ:


13

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

นอกจากนี้คุณสามารถโอนย้ายตารางขนาดใหญ่บางส่วนไปยังฮีปที่แบ่งพาร์ติชันหรือแบ่งพาร์ติชันแบบแบ่งคอลัมน์ (SQL Server 2016+) โดยปล่อยให้คีย์หลักและดัชนีที่ไม่ซ้ำกันถูกยกเลิกการแบ่งพาร์ติชัน สิ่งนี้จะช่วยให้คุณสามารถผลักคอลัมน์ที่ไม่ใช่คีย์สำหรับแถว IsDeleted ไปยังโครงสร้างข้อมูลแยกซึ่งสามารถบีบอัดเพิ่มเติมหรือเก็บไว้ในกลุ่มไฟล์อื่น

และตรวจสอบให้แน่ใจว่าผู้พัฒนาใช้ตัวอักษรแทนที่จะเป็นพารามิเตอร์เพื่อกรองแถว IsDeleted ออก ด้วยพารามิเตอร์ SQL Server จะต้องใช้แผนแบบสอบถามเดียวกันสำหรับทั้งสองกรณี

เช่น

SELECT ... WHERE ... AND IsDeleted=0

และไม่:

SELECT ... WHERE ... AND IsDeleted=@IsDeleted

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


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

@JeroenMostert คำแนะนำที่ดี RLS ยังสามารถใช้ได้ที่นี่หรือบางอย่างเช่น EF Core Global Query Filter docs.microsoft.com/en-us/ef/core/querying/filters
David Browne - Microsoft

9

นี่อาจเป็นความคิดเห็นที่ไม่เป็นที่นิยม แต่ฉันไม่คิดว่าจะมี "ทำทุกที่" / ขนาดเดียวเหมาะกับทุกคำตอบสำหรับคำถามของคุณ

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

อีกทางเลือกหนึ่งคือการสร้างมุมมองที่จัดทำดัชนีซึ่งสามารถใช้ประโยชน์จากจำนวนแบบสอบถามที่แตกต่างกันซึ่งจะถูกกรองเป็นเพียงแถวที่ไม่ถูกลบ สิ่งนี้อาจเป็นประโยชน์อย่างยิ่งใน Enterprise Edition ซึ่งการจับคู่มุมมองที่จัดทำดัชนีโดยอัตโนมัติทำงานได้โดยไม่ต้องให้NOEXPANDคำใบ้

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


2

ภายใต้สมมติฐานที่สมเหตุสมผลที่การลบนั้นหายากจะไม่มีการเปลี่ยนแปลงดัชนีใด ๆ เป็นวิธีแก้ไขที่เหมาะสม

ฉันพบว่าไม่ช้าก็เร็วเราจะต้องค้นหาการอ้างอิงถึงแถวที่ถูกลบและแถวที่อยู่ในดัชนีนั้นจะคุ้มค่ามาก

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


0

ฉันได้เห็นระบบที่ค่าสถานะ IS_DELETED เป็น 0 หรือค่าของ PK ในระบบอื่นมันเป็นค่าลบของ PK

เนื่องจากข้อความค้นหาส่วนใหญ่ดึงค่าโดยคีย์ "ธรรมชาติ" หรือธุรกิจ (บางครั้งเป็นหลายฟิลด์) คีย์เหล่านั้นจึงไม่เคยถูกสอบถามโดย PK ยกเว้นผ่านการเข้าร่วม แต่พวกเขาเพิ่ม AND IS_DELETED = 0 ไว้ท้ายตารางหลักและตารางที่เข้าร่วม

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


0

หวังว่าคุณมีสิทธิ์และความสามารถในการเปลี่ยนแบบสอบถาม

อย่างไรก็ตามเนื่องจากการเข้าร่วม / การสืบค้นทั้งหมดจะต้องใช้การตรวจสอบ IsDeleted นั่นจะป้องกันการใช้ดัชนีที่กรองแล้วหรือไม่ (เนื่องจากมีการใช้คอลัมน์ IsDeleted ในการเข้าร่วม / การสืบค้น)

ฉันอยากจะบอกจุดสำคัญจุดหนึ่งหวังว่าฉันจะสามารถอธิบายได้

ในแบบสอบถามที่ซับซ้อนที่ใช้Transaction tableและMasterทั้งสองตาราง

ใช้IsDeleted=0เฉพาะในTransactionตาราง อย่าใช้ในMasterตาราง

ตัวอย่าง,

Select * from dbo.Order O
inner join dbo.category C on o.categoryid=o.categoryid
inner join dbo.Product P on P.Productid=o.Productid
where o.isdeleted=0

ไม่มีจุดในc.isdeleted=0(ใช้ในCategoryตาราง) มันไม่จำเป็น

มีจุดใดบ้างในการใช้งานเช่นเดียวกันP.isdeleted=0 ?

เพราะฉันต้องการยกเลิกการลบคำสั่งซื้อและรายละเอียดทั้งหมด

วิธีการสามารถProductถูกลบเมื่อOrderเป็นActiveหรือที่ใดก็ตามProductidคือการอ้างอิง

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

อย่าสร้างดัชนีที่กรองอย่างสุ่มสี่สุ่มห้าก่อนอื่นให้เลือกแบบสอบถามที่สำคัญมากและช้า

เพิ่มประสิทธิภาพการค้นหาช้าเหล่านั้นจากนั้นเลือกเฉพาะดัชนีที่กรองหรือปรับดัชนี

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