แยกธงกับตาราง


10

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

ฉันพิจารณาตัวเลือกการออกแบบสองตัว:

  • ธงบิต
  • ตารางแยกรายการ "ที่ไม่ผ่านการอนุมัติ" - เมื่อรายการได้รับการอนุมัติจะถูกย้ายไปที่ตาราง "ปกติ" (การต่ออายุ ID ของรายการไม่ใช่ปัญหา)

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

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


1
อาจช่วยให้จำได้ว่าคุณสามารถใช้ดัชนีที่กรองแล้วเพื่อช่วยให้เข้าถึงระเบียนที่อนุมัติได้เร็วขึ้น brentozar.com/archive/2013/11/…
mendosi

น่าเสียดายที่ดัชนีที่กรองไม่ใช้ในการสืบค้นแบบกำหนดพารามิเตอร์
Dima

@Dima ไม่จริงทั้งหมด หากดัชนีที่กรองแล้วพูดWHERE status='A'และแบบสอบถามมีWHERE status = 'A' AND (... other columns and parameters here...)อยู่ดัชนีนั้นอาจยังคงถูกใช้
ypercubeᵀᴹ

คำตอบ:


6

คุณสามารถมีได้ทั้งสองวิธีมีมุมมองที่แบ่งพาร์ติชัน

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

ประโยชน์คือ
ก) ดัชนีตื้นกว่า อย่างไรก็ตามทำคณิตศาสตร์กับดัชนีแฟนเอาต์ ในระดับนั้นและแบ่งระหว่างค่าสถานะของคุณเป็นไปได้ที่ดัชนีจะมีความลึกเท่ากันในตารางที่แยกตามที่ควรจะเป็นในตารางรวม
b) ไม่มีการเปลี่ยนแปลงรหัสแอปพลิเคชัน ข้อมูลยังคงปรากฏโดยรวมอย่างต่อเนื่อง
c) ค่าสถานะใหม่ในอนาคตสามารถรวมได้โดยการเพิ่มตารางฐานใหม่พร้อมข้อ จำกัด และสร้างมุมมองใหม่

ค่าใช้จ่ายคือการเคลื่อนย้ายข้อมูลทั้งหมด มีการเขียนสองหน้าและดัชนีที่เกี่ยวข้องสำหรับการอัพเดตสถานะแต่ละครั้ง IO มากมายที่ต้องจัดการ การเคลื่อนไหวที่มากจะทำให้เกิดการแตกแฟรกเมนต์เช่นกัน


5

ตารางรายการซึ่งอาจมีหลายสิบล้านระเบียน

ที่จริงแล้วไม่มากนักเพราะสิ่งที่ SQL Server สามารถจัดการได้อย่างมีประสิทธิภาพ แน่นอนฉันจำหนึ่งในงานก่อนหน้าของฉันที่หนึ่งในตารางที่ใหญ่ที่สุด (ระบบอินสแตนซ์เดียว) มี 2 ล้านแถวและนั่นเป็นงานที่ฉันทำมากที่สุด จากนั้นงานต่อไปจะมีอินสแตนซ์การผลิต 17 รายการโดยมีบางตารางที่มีหลายร้อยล้านแถวและทั้งหมดนั้นรวมเข้ากับ Data Warehouse โดยมีตารางข้อเท็จจริงหลายตารางมีมากกว่า 1 พันล้านแถว ไม่ได้รับฉันผิดฉันไม่ได้เย้ยหยันที่หลายสิบล้านแถวฉันเพียงแค่เน้นว่าด้วยรูปแบบข้อมูลที่ดีและการสร้างดัชนีที่เหมาะสม (และการบำรุงรักษาดัชนี), SQL Server สามารถจัดการมาก

มากถึง 50% ของรายการอาจ "ไม่ผ่านการอนุมัติ" ในเวลาใดก็ได้

อืมมม แต่นั่นไม่ได้เสียงที่ถูกต้อง อัตราการ "อนุมัติ" รายการจะเป็นครึ่งหนึ่งของอัตราการได้รับรายการใหม่หรือไม่? สำหรับทุก 2 รายการใหม่เพียง 1 รายการเท่านั้นที่จะได้รับ "อนุมัติ" ในตัวอย่างของคุณ 2 ล้านแถวและ 1 ล้านแถวสำหรับ "อนุมัติ" และ "ไม่อนุมัติ" ไม่กี่ปีต่อมามีอีก 10 ล้านรายการคุณคาดหวัง 6 ล้านแถวสำหรับ "อนุมัติ" และ "ไม่อนุมัติ" หรือไม่? หรือว่า 1 ล้านคน "ยังไม่ได้รับการอนุมัติ" จะยังคงค่อนข้างคงที่เช่นที่มี 10 ล้านรายการใหม่จะมี 11 ล้านคน "อนุมัติ" และยังคง 1 ล้าน "ไม่อนุมัติ"

บันทึกอาจกลายเป็น "อนุมัติ" แต่ไม่ใช่ในทางกลับกัน

วันนี้เป็นจริงแต่สิ่งต่าง ๆ เปลี่ยนแปลงไปตามกาลเวลาดังนั้นจึงมีความเป็นไปได้ที่ธุรกิจจะตัดสินใจอนุญาตให้ "ไม่อนุมัติ" หรือสถานะอื่น ๆ เช่น "เก็บถาวร" เป็นต้น

ดังนั้นเรามาดูทางเลือก:

ตั้งค่าสถานะ (หรืออาจเป็นTINYINT"สถานะ")

  • ช้าลงเล็กน้อยสำหรับการค้นหาของแต่ละสถานะ
  • มีความยืดหยุ่นมากขึ้นเมื่อเวลาผ่านไป / ง่ายต่อการรวมการเปลี่ยนแปลงเช่นสถานะที่สาม (เช่น "เก็บถาวร") ด้วยค่าสถานะการค้นหาใหม่เท่านั้น ไม่มีตารางใหม่ (จำเป็น), โค้ดใหม่บางรหัสเท่านั้นที่มีการอัปเดต
  • ทำงานน้อยลง (เช่นรหัสการทดสอบ ฯลฯ ) และพื้นที่น้อยลงสำหรับข้อผิดพลาดในการอัปเดตTINYINTคอลัมน์เดียว
  • ซับซ้อนน้อยลง = ลดค่าใช้จ่ายในการบำรุงรักษาเมื่อเวลาผ่านไปลดเวลาในการฝึกอบรมเพื่อให้พนักงานใหม่เข้าใจ
  • (อาจเป็นไปได้) ผลกระทบที่น้อยลงในบันทึกธุรกรรมเป็นหนึ่งตารางที่มีการปรับปรุง
  • เพียงต้องการตารางค้นหาสำหรับ "RecordStatus" และ FK ระหว่างสองตาราง

สองตารางแยกกัน (หนึ่งสำหรับ "อนุมัติ", หนึ่งตารางสำหรับ "ไม่อนุมัติ")

  • เร็วขึ้นเล็กน้อยสำหรับข้อความค้นหาของแต่ละสถานะ
  • มีความยืดหยุ่นน้อยลงเมื่อเวลาผ่านไป / ยากกว่าที่จะรวมการเปลี่ยนแปลงเช่นสถานะที่สาม (เช่น "เก็บถาวร"); สถานะใหม่จะต้องมีโอกาสมากที่สุดในตารางอื่นและรหัสใหม่และปรับปรุงอย่างแน่นอน
  • การทำงานมากขึ้น (เช่นรหัสการทดสอบ ฯลฯ ) และห้องเพิ่มเติมสำหรับข้อผิดพลาดในการย้ายระเบียนจากตาราง "ไม่อนุมัติ" ไปยังตาราง "อนุมัติ"
  • ซับซ้อนมากขึ้น = ค่าใช้จ่ายในการบำรุงรักษาที่สูงขึ้นเมื่อเวลาผ่านไปนานกว่าการฝึกอบรมเพื่อให้พนักงานใหม่เข้าใจ
  • (อาจ) ผลกระทบมากขึ้นต่อบันทึกธุรกรรมเมื่อมีการลบตารางหนึ่งตารางและแทรกหนึ่งรายการ
  • ไม่จำเป็นต้องกังวลเกี่ยวกับ " การต่ออายุบัตรประจำตัวประชาชนของรายการ ": ยังไม่ได้อนุมัติตารางมีคอลัมน์รหัสที่เป็นIDENTITYคอลัมน์และโต๊ะรับการอนุมัติมี ID คอลัมน์ที่เป็นไม่IDENTITY (มันไม่จำเป็นต้องมี) ดังนั้นค่า ID ยังคงสอดคล้องกันเมื่อมีการย้ายระเบียนระหว่างตาราง

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


เป็นตารางที่มีข้อมูลที่เคลื่อนไหวอย่างรวดเร็ว: บ่อยครั้งที่มีจำนวนแถวใหม่จำนวนมากซึ่งค่อนข้างบ่อยครั้งจะถูกลบแถว ฉันพยายามลบรายละเอียดทั้งหมด (เช่นการตัดสินใจทางธุรกิจการเข้ารหัสลูกค้า ฯลฯ ) เพื่อเน้นเฉพาะหัวข้อเดียว โดยทั่วไปเรามีตารางการออกแบบเก่าที่มีการตั้งค่าบิต และฉันรู้ 100% ว่าแถวที่ตั้งค่าสถานะเป็น 1 ไม่เคยถูกใช้ในตารางอื่น ๆ ดังนั้นฉันรู้สึกว่าพวกเขาเกิดขึ้นที่นั่นเท่านั้นและอาจถูกย้ายไปยังตารางที่แยกต่างหาก สแกนตารางเกือบทุกแบบสอบถามไปยังฐานข้อมูล ดังนั้นการลด "น้ำหนัก" อาจลด CPU / IO ops
Dima

3
ข้อดีอีกประการของตารางแยก: คุณสามารถมี FK ที่อ้างอิงเฉพาะตาราง "อนุมัติ"
ypercubeᵀᴹ

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