GUID ตามลำดับหรือใหญ่สำหรับตารางฐานข้อมูล 'ใหญ่' PK


14

ฉันรู้ว่าคำถามประเภทนี้เกิดขึ้นมากมาย แต่ฉันยังไม่ได้อ่านข้อโต้แย้งที่น่าสนใจใด ๆ เพื่อช่วยในการตัดสินใจ กรุณาทนกับฉัน!

ฉันมีฐานข้อมูลขนาดใหญ่ - มันเติบโตประมาณ 10,000,000 รายการต่อวัน ข้อมูลมีความสัมพันธ์และสำหรับเหตุผลด้านประสิทธิภาพฉันโหลดตารางด้วย BULK COPY ด้วยเหตุนี้ฉันจำเป็นต้องสร้างคีย์สำหรับแถวและไม่สามารถพึ่งพาคอลัมน์ตัวตน

เลขจำนวนเต็ม 64- บิต - ใหญ่ - กว้างพอสำหรับฉันที่จะใช้ แต่เพื่อรับประกันเอกลักษณ์ฉันต้องมีเครื่องกำเนิดส่วนกลางเพื่อสร้าง ID ของฉันให้ฉัน ขณะนี้ฉันมีบริการตัวสร้างซึ่งอนุญาตให้บริการสำรองหมายเลขลำดับ X และรับประกันว่าไม่มีการชนกัน อย่างไรก็ตามผลที่ตามมาก็คือบริการทั้งหมดที่ฉันเชื่อถือได้จากเครื่องกำเนิดไฟฟ้าส่วนกลางนี้และดังนั้นฉันจึงถูก จำกัด ในวิธีที่ฉันสามารถกระจายระบบของฉันและฉันไม่พอใจกับการพึ่งพาอื่น ๆ (เช่นต้องใช้การเข้าถึงเครือข่าย) โดยการออกแบบนี้ นี่เป็นปัญหาในบางโอกาส

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

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


2
คุณจะสร้าง "GUID ลำดับ" ได้อย่างไร

มันเป็นการใช้งานที่กำหนดเอง มันเป็นรูปแบบของ GUID ซึ่งมี 6 ไบต์แทนที่ด้วยไบต์ประทับเวลาและ 2 ไบต์ซึ่งแทนหมายเลขลำดับที่การประทับเวลาเหมือนกัน ไม่รับประกันว่าจะสร้างค่าตามลำดับที่สมบูรณ์แบบ แต่ก็ดีพอที่จะทำให้การแตกแฟรกเมนต์ดัชนีไม่ใช่ปัญหาสำหรับฉัน

คุณกำลังโหลดข้อมูลนี้จากหลาย ๆ แหล่งหรือไม่ ฉันยังสมมติว่าดัชนีที่คุณกังวลเกี่ยวกับการแตกแฟรกเมนต์คือดัชนีคลัสเตอร์?

2
หากคุณจะใช้ GUID ตามลำดับคุณควรดู NEWSEQUENTIALID () มันควรจะทำในสิ่งที่คุณต้องการ (เพิ่มขึ้นซ้ำซากจำเจ) และไม่ต้องพึ่งพารหัสที่กำหนดเอง

2
ดูที่ Jeremiah Peschka โพสต์เมื่อมีปัญหากับกุญแจอ่านดีและเขาจัดการกับการใช้งานเหล่านี้หลายครั้ง
billinkc

คำตอบ:


4

ฉันอยู่ในสถานการณ์เดียวกัน ขณะนี้ฉันกำลังใช้วิธีลำดับ GUID และไม่มีการกระจายตัวและการสร้างคีย์ง่าย

ฉันสังเกตเห็นสองข้อเสียเปรียบที่ทำให้ฉันเริ่มโยกย้ายไปที่ใหญ่:

  1. การใช้พื้นที่ มากกว่า 8 ไบต์ต่อดัชนี ทวีคูณด้วย 10 ดัชนีหรือมากกว่านั้นและคุณจะได้เปลืองเนื้อที่มาก
  2. ดัชนีColumnstoreไม่รองรับ GUID

(2) เป็นนักฆ่าสำหรับฉัน

ตอนนี้ฉันจะสร้างกุญแจของฉันเช่นนี้:

yyMMddHH1234567890

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

ฉันจะสร้างส่วนลำดับ bigint โดยใช้ไฮโลที่อัลกอริทึมที่ยืมตัวดีที่จะถูกกระจาย

หวังว่าการถ่ายโอนบางส่วนกับสถานการณ์ของคุณ ฉันแนะนำให้ใช้ bigint แน่นอน


1
ทำเครื่องหมายสิ่งนี้ว่า 'คำตอบ' เนื่องจากเป็นขนาดที่เหมาะสมที่สุด (และคุณรู้สึกซาบซึ้งกับสิ่งที่ฉันถาม ฉันคิดว่าฉันจะไปกับเครื่องมือสร้างลำดับที่ใช้ร่วมกัน (ซึ่งจะทำงานคล้ายกับคำแนะนำอัลกอริทึม HiLo ของคุณ) ฉันได้ทำงานกับระบบอื่นที่มีปัญหาเล็กน้อยฉันจะต้องทนกับการพึ่งพาพิเศษ โอ้ดี ขอบคุณ
Barguast

3

ด้วยประเภทINTเริ่มต้นที่ 1 คุณจะได้แถวที่เป็นไปได้มากกว่า 2 พันล้านแถวซึ่งน่าจะเพียงพอสำหรับกรณีส่วนใหญ่ ด้วยBIGINTคุณจะได้รับประมาณ922 ล้านล้าน (922 กับ 15 ศูนย์ - 922'000 พันล้าน) - เพียงพอสำหรับคุณ

หากคุณใช้การINT IDENTITYเริ่มต้นที่ 1 และคุณแทรกแถวทุกวินาทีคุณต้อง 66.5 ปีก่อนที่คุณจะถึงขีด จำกัด 2 พันล้าน ....

หากคุณใช้การBIGINT IDENTITYเริ่มต้นที่ 1 และคุณแทรกหนึ่งพันแถวทุกวินาทีคุณต้องมีความเชื่อที่เหลือเชื่อ292 ล้านปีก่อนที่คุณจะถึงขีด จำกัด 922 ล้านล้าน ....

การใช้ 10 ล้านแถวต่อวันนั้นจะทำให้คุณมีตัวเลขเพียงพอสำหรับประมาณ1'844'674'407'370วัน ( 1844 ล้านล้านวันหรือมากกว่า5 พันล้านปี ) ของข้อมูล - ดีพอสำหรับความต้องการของคุณ ?

อ่านข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้ (มีตัวเลือกทั้งหมดที่มี) ในMSDN หนังสือออนไลน์


1
อัตราการแทรก 10 ล้านแถวต่อวันจะทำให้หมดช่วง INT ใน 200 วัน
mceda

@mceda: ใช่ - ฉันอ้างสิทธิ์อย่างอื่นอีกหรือไม่ มันไม่หมดBIGINTช่วงที่เร็ว แต่ ....
marc_s

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

2
@Barguast: คุณไม่เพียงแค่แทรกข้อมูลของคุณลงในตารางการแสดงละคร (โดยไม่มีข้อมูลเฉพาะตัว) แล้วย้ายข้อมูลจากที่นั่นไปยังตารางข้อมูลจริงของคุณโดยใช้BIGINT IDENTITYหรือไม่
marc_s

@marc_s: ใช่การคำนวณที่ให้ไว้ไม่ตรงกับคำถาม: "ถ้าคุณใช้ INT IDENTITY เริ่มต้นที่ 1 และคุณแทรกแถวทุกวินาทีคุณต้อง 66.5 ปีก่อนที่คุณจะถึงขีด จำกัด 2 พันล้าน"
mceda

2

ฉันขอแนะนำให้คุณใช้ SEQUENCE ของประเภทข้อมูล BIGINT ใน SQL 2012 ซึ่งมีความยืดหยุ่นมากกว่า IDENTITY ด้วยตัวเลือกเช่นแคช / nocache คุณยังสามารถกำหนดช่วงลำดับสำหรับการดำเนินการแบทช์ของคุณเป็น sp_sequence_get_range


น่าเสียดายที่ SEQUENCE ไม่รองรับ Sql Azure
Timothy Lee Russell

2

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

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

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

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


0

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

ตัวบ่งชี้ที่ยึดตามการประทับเวลาไม่ควรเชื่อถือได้ - ขึ้นอยู่กับนาฬิการะบบซึ่งจะขึ้นอยู่กับหลาย ๆ อย่างตั้งแต่นาฬิกาฮาร์ดแวร์ไปจนถึงบริการซิงโครไนซ์เวลา

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