การออกแบบตารางแบบใดที่เหมาะกับประสิทธิภาพมากที่สุด


16

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

นี่คือสิ่งที่ฉันรู้

  • บริษัท มีบัญชีมากกว่า 2.5 ล้านบัญชี
  • ในบรรดาเหล่านี้พวกเขาทำงานเฉลี่ย 200,000 ต่อเดือน (การเปลี่ยนแปลงที่มีระดับพนักงานซึ่งปัจจุบันอยู่ในระดับต่ำ)
  • พวกเขามีประเภทค่าใช้จ่ายที่แตกต่างกัน 13 แบบที่พวกเขาต้องการติดตามและพวกเขาได้เตือนว่าพวกเขาอาจเพิ่มมากขึ้นในอนาคต
  • พวกเขาต้องการค่าใช้จ่ายในการติดตามรายวัน
  • ค่าใช้จ่ายจะไม่แยกระหว่างสินค้าคงคลังทั้งหมด พวกเขาจะแยกตาม # ของบัญชีที่ทำงานต่อเดือน (200,000) หรือผู้ใช้สามารถป้อนตัวระบุบัญชีเพื่อใช้ค่าใช้จ่ายกับกลุ่มบัญชีหรือพวกเขาสามารถระบุบัญชีที่จะใช้ค่าใช้จ่าย

ความคิดแรกของฉันคือฐานข้อมูลปกติ:

หมายเลขบัญชี
วันที่
CostTypeId
จำนวน

ปัญหาของฉันคือสิ่งนี้ทำคณิตศาสตร์ ตารางนี้จะใหญ่ขึ้นอย่างรวดเร็ว สมมติว่ามีการคิดค่าใช้จ่ายทั้งหมด 13 ประเภทสำหรับบัญชีที่ทำงานทั้งหมดสำหรับเดือนปัจจุบันนั่น200k * 13 * N days in monthคือที่ ๆ ประมาณ 75-80 ล้านระเบียนต่อเดือนหรือใกล้เคียงกับหนึ่งพันล้านรายการต่อปี

ความคิดที่สองของฉันคือการทำให้เป็นปกติเล็กน้อย

หมายเลขบัญชี
วันที่
ค่าใช้จ่ายทั้งหมด
CostType1
CostType2
CostType3
CostType4
CostType5
CostType6
CostType7
CostType8
CostType9
CostType10
CostType11
CostType12
CostType13

วิธีนี้มีความผิดปกติมากขึ้นและสามารถสร้างได้มากถึง 6 ล้านแผ่นต่อเดือน ( 200k * N days in month) หรือประมาณ 72 ล้านต่อปี มันน้อยกว่าวิธีแรกมากอย่างไรก็ตามหาก บริษัท ตัดสินใจเลือกประเภทต้นทุนใหม่ในอนาคตจำเป็นต้องเพิ่มคอลัมน์ฐานข้อมูลอื่น

จากสองวิธีที่คุณชอบ ทำไม? มีทางเลือกอื่นที่คุณสามารถคิดได้ว่าจะจัดการกับสิ่งนี้ดีกว่าหรือไม่?

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

ฐานข้อมูลคือ SQL Server 2005


รับแผ่นดิสก์อีกแผ่น ดิสก์ราคาถูก คุณสามารถมี 2TB สำหรับค่าใช้จ่ายในการประชุมเพื่อโต้แย้งเกี่ยวกับเรื่องนี้

คำตอบ:


9

บันทึกเป็นพันล้านต่อปีนั้นไม่มากนัก

ด้วยการแบ่ง (อาจมีต่อประเภทต้นทุน) และการเก็บถาวรสามารถจัดการได้

จำนวนรายการข้อมูลที่จะจัดเก็บยังคงเป็น200k * 13 * N ในฐานะคอลัมน์คุณจะได้รับแถวน้อยลงต่อหน้าและจะใช้พื้นที่มากกว่าแถว คุณอาจได้รับหาก "CostType1" ไม่ใช่ประเภทข้อมูลความยาวคงที่ แต่เป็นระยะขอบ

"จูบ" ตามที่พวกเขาพูด


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

6

ในขณะที่การออกแบบของคุณสามารถสร้างความแตกต่างในเวลากลางคืนหรือกลางวันได้ในกรณีนี้ฉันจะเน้นที่ดัชนีมากขึ้นรวมถึงครอบคลุมดัชนีตามต้องการ ฉันจะดูเครื่องมือบางอย่างที่ SQL Server ให้คุณจัดการกับตารางที่มีขนาดใหญ่มากเช่นการแบ่งตาราง

คิดแบบนี้แม้ว่าจะมีระเบียน 80,000 ล้านรายการในตารางที่มีการจัดทำดัชนีที่เหมาะสม แต่สิ่งที่คุณสนใจจริง ๆ ณ จุดใดก็ตามจะถูกจัดกลุ่มเข้าด้วยกันบนดิสก์ เนื่องจากวิธีการจัดระเบียบข้อมูลในเซิร์ฟเวอร์ SQL ข้อมูลที่แยกตามขอบเขตดัชนีอาจอยู่ในตารางอื่นเนื่องจากไม่จำเป็นต้องอ่านทั้งตารางเพื่อให้ได้ตามที่ต้องการ

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


4

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

ตัวอย่างเช่นค่าใช้จ่ายทั้งหมดในการให้บริการตู้ ATM แบ่งออกเป็นบัญชีที่ใช้ตู้เอทีเอ็มตามจำนวนการใช้งานที่สัมพันธ์กัน ดังนั้นหากมีการใช้จ่าย $ 1m ในการให้บริการตู้เอทีเอ็มและมีลูกค้าเพียง 5 รายเท่านั้นที่ใช้มันหนึ่งครั้งและลูกค้าหนึ่งคนใช้มัน 5 ครั้งจากนั้นลูกค้ารายหนึ่งเสียค่าใช้จ่าย $ 0.5 ล้านธนาคารและลูกค้าคนอื่น ๆ ไดรเวอร์อื่น ๆ อาจมีความซับซ้อนมากขึ้น

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


SPARSE - นี่เป็นจุดที่ดีมากที่สร้างความแตกต่าง หากเบาบางคุณจะประหยัดพื้นที่ด้วยการทำให้เป็นมาตรฐาน มิฉะนั้นจะไม่ แต่พื้นที่ดิสก์มีราคาถูกดังนั้นโดยส่วนตัวแล้วฉันลงคะแนนเพื่อความยืดหยุ่นสูงสุด (ปกติ)

3

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


2

ฉันจะไปกับตัวเลือก 1 แล้วถ้าความเร็วในการรายงานกลายเป็นปัญหาไปตามถนนฉันก็จะเพิ่มตารางที่ 2 และเติมลงในฐานข้อมูลการรายงานในกระบวนการอัตโนมัติข้ามคืน / offpeak

นอกจากนี้คุณยังสามารถพิจารณาปรับโครงสร้างตาราง 2 รายวันให้เป็นรายสัปดาห์รายเดือนรายไตรมาสไตรมาสละครั้งหากมีการรับประกัน

แต่อย่างที่ฉันบอกฉันก็เลือกที่จะเก็บข้อมูล 'ดิบ' ในรูปแบบที่เหมาะสม


0

เมื่อพิจารณาถึงปริมาณที่คุณพูดถึงฉันจะเลือกตัวเลือกที่สอง แต่ไม่มี TotalCost คุณสามารถพูดได้ว่ายังคงเป็นมาตรฐาน


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

AccountDate
-----------
AccountId  
Date  
AcDtID (surrogate key)

Costs
-------
AcDtID
CostTypeId  
Amount  

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


ฉันTotalCostอยู่ที่นั่นเพราะสรุปรายงานส่วนใหญ่และฉันคิดว่าการสืบค้นค่าเดียวจะเร็วกว่าการเพิ่ม 13 ค่าที่แตกต่างกัน

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

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

จากนั้นการอัปเดตแต่ละรายการจะต้องมีการอัปเดต 2 รายการและฟิลด์ TotalCost จะเพิ่มความเสี่ยงของความไม่สอดคล้องกัน

การพึ่งพาทางสกรรมกริยา แต่ไม่จำเป็นต้องเป็นความเสี่ยงของความไม่สอดคล้องกัน - ข้อ จำกัด การตรวจสอบ () สามารถรับประกันได้ว่า TotalCost จะเป็นผลรวมของต้นทุนเสมอ
Mike Sherrill 'Cat Recall'

0

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

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