การสร้างคีย์หลักรองในฐานข้อมูลสำหรับบางตาราง


22

ในบางตารางของฉันฉันต้องการเพิ่ม "second_primary_key" ซึ่งจะเป็น uuid หรือบางคีย์ยาวแบบสุ่ม ฉันต้องการเพราะบางตารางฉันไม่ต้องการให้จำนวนเต็มกับเว็บแอปพลิเคชันของฉัน นั่นคือในหน้า "/ ใบแจ้งหนี้" ฉันมีรายการใบแจ้งหนี้และลิงก์ไปยัง "/ ใบแจ้งหนี้ /: id" โดยที่: id เป็นจำนวนเต็ม ฉันไม่ต้องการให้ผู้ใช้ทราบจำนวนใบแจ้งหนี้ในระบบของฉันที่นั่นดังนั้นแทนที่จะเป็น "/ ใบแจ้งหนี้ / 123" ฉันต้องการใช้ "second_primary_key" เพื่อให้ URL เป็น "/ ใบแจ้งหนี้ / N_8Zk241vNa"

เช่นเดียวกันกับตารางอื่น ๆ ที่ฉันต้องการซ่อนรหัสจริง

ฉันสงสัยว่านี่เป็นเรื่องธรรมดาหรือไม่ วิธีที่ดีที่สุดในการใช้งานนี้คืออะไร

และเทคนิคนี้เรียกว่าอะไรหลังจากทั้งหมดเพื่อที่ฉันจะค้นหามัน?


20
ทำไมไม่กำจัดจำนวนเต็มทั้งหมด?
larsbe

4
คุณสามารถกำหนดคีย์ / ดัชนีที่ไม่ซ้ำกันได้มากเท่าที่คุณต้องการบนโต๊ะ
abuzittin gillifirca

2
บางทีคุณควรเรียกมันว่ารหัสผู้สมัครรอง "หลัก" แนะนำเพียงหนึ่งเดียว
Walter Mitty

4
"ปรมาจารย์ที่สอง" คือโอออกซ์โม่ คุณมีคีย์หลักและคุณสามารถมีคีย์รองได้
หยุดทำร้ายโมนิก้า

7
@RobbieDee มีเหตุผลที่ถูกต้องสำหรับการไม่มีฐานข้อมูลปกติ และการมีตัวเลือกหรือคีย์รองไม่ใช่ข้อมูลที่ซ้ำกัน
Machado

คำตอบ:


0

คุณสามารถเพิ่มคอลัมน์ UUID ได้ แต่คุณไม่จำเป็นต้อง (และไม่ควร) นี่เป็นข้อกังวลเกี่ยวกับเลเยอร์การนำเสนอ คุณคงไม่ฝันที่จะพูดเก็บค่าเงินไว้ที่ $ 1,999 และ 1999

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

เนื่องจากเรากำลังพูดถึงเพียงค่าเดียวอาจจะดูที่การเข้ารหัสแบบ 2 ทางเช่น AES หรือที่คล้ายกัน - ยิ่งมีน้ำหนักเบายิ่งดี

การแฮชอาจเป็นไปได้อีกอย่างหนึ่ง - ขึ้นอยู่กับว่าคุณต้องการรับหมายเลขใบแจ้งหนี้คืนเนื่องจากการแฮชเป็นวิธีหนึ่ง


48

การมี "คีย์หลักทางเลือก" เป็นแนวคิดที่รู้กันดีในการสร้างแบบจำลองฐานข้อมูลเชิงสัมพันธ์มันถูกเรียกว่า "คีย์สำรอง" หรือบางครั้งก็เป็น "คีย์รอง" ชุดของ "คีย์หลักที่เป็นไปได้" เรียกว่า "คีย์ตัวเลือก" ดูhttps://beginnersbook.com/2015/04/alternate-key-in-dbms/

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


11
ฉันยังได้เห็นคำศัพท์คีย์ธรรมชาติกับคีย์ตัวแทนที่ใช้เพื่ออธิบายสถานการณ์นี้
DanK

2
@Dari: คุณถามว่า "เทคนิคนี้เรียกว่าอะไร" - เป็นตัวอักษรหนา และหากถอดรหัส AES - บางทีอาจเป็นเรื่องที่สร้างคีย์ที่คุณกำลังมองหาใช้มันซึ่งไม่ขัดแย้งกับคำตอบของฉัน
Doc Brown

1
@Dari เพราะมันเพิ่มค่าใช้จ่ายที่ไม่จำเป็นอย่างสมบูรณ์ให้กับแอปของคุณ
Lamak

1
@ RobbieDee เราเข้าใจแล้วว่าคุณไม่ชอบคีย์สำรอง แต่นั่นไม่ได้หมายความว่ามันไร้ประโยชน์ ฉันชอบแนวทาง guid เพราะมันช่วยให้ปัญหาง่ายขึ้นมาก
T. Sar - Reinstate Monica

1
@RobbieDee เราไม่ได้ใช้ SQL Server เราใช้ MySql และมันเกิดขึ้นเพราะใครบางคนจะสร้างบางอย่างใน Prod สมมุติว่า ID 1234 บน Dev โดยธรรมชาติเราสร้างเอนทิตีมากกว่าที่เราทำใน prod 1234 ถูกนำไปใช้นานแล้วโดยเอนทิตี้ของการโยนทิ้งเพื่อทำการทดสอบ เมื่อเราต้องทดสอบเอนทิตีจากกระทุ้งเราต้องย้ายกลับไปที่ Dev - และคีย์หลักของมันถูกใช้งานไปแล้ว การโยกย้ายนั้นง่ายกว่ามากหากการอ้างอิงไปยังเอนทิตีนั้นมีพื้นฐานจาก guid แต่จำศีลทำงานได้ดีขึ้นมากเมื่อมีคีย์หลักอยู่ภายในหรือยาวดังนั้นเราจึงเก็บไว้ ผู้พัฒนาของฉันไม่ขี้เกียจหรือไม่รู้ - พวกเขามีประสบการณ์
corsiKa

9

ใบแจ้งหนี้ส่วนใหญ่มีหมายเลขใบแจ้งหนี้ซึ่งตามกฎการบัญชีส่วนใหญ่จะต้องเรียงตามลำดับหรือนักบัญชีอาจไม่ลงชื่อออกในปีหรือ IRS (หรือคล้ายกันในประเทศของคุณ) อาจต้องการทำการตรวจสอบอย่างเต็มรูปแบบบนแท็บของคุณ

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

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

อย่างไรก็ตามฉันจะล็อคใบแจ้งหนี้ที่อยู่เบื้องหลังหน้าจอเข้าสู่ระบบของผู้ใช้ดังนั้นทุกคนไม่สามารถขอได้ จากนั้นในการเข้าสู่ระบบของผู้ใช้พวกเขาสามารถใช้วิธีการ ajax เพื่อขอใบแจ้งหนี้คงค้างของพวกเขา ฯลฯ ซึ่งจะรักษาข้อมูลของคุณซ่อน URL โดย ajax (ไม่มีใครสามารถใส่ใจดูรายละเอียดว่าคำขอ ajax ถูกสร้างขึ้นมาอย่างไร) และคุณควบคุมวิธีการแสดงและนำเสนอข้อมูล


7
กลยุทธ์ทั่วไปที่ใช้ในการธนาคาร (พร้อมหมายเลขเช็ค) คือไม่เริ่มนับที่เพิ่มขึ้นที่ 1 แต่จะมีจำนวนที่มากกว่าด้วยเหตุผลที่แน่นอนนี้
DanK

ฉันคิดว่านั่นเป็นสาเหตุที่รหัสจะเป็นคีย์หลักเพิ่มเติมไม่ใช่การแทนที่คีย์หลักเก่า
อเล็กซานเดอร์

1
ฉันจะไม่เรียกมันว่าเป็นคีย์หลัก ฉันจะไปหากระสุนกระสุน UUID เป็นชื่อ แต่โดยเนื้อแท้แล้วมันเป็นเพียงอีกหนึ่งสนามที่จัดทำดัชนีไว้ในตาราง หมายเลขอ้างอิงใบแจ้งหนี้หมายเลขอะไรก็ตาม เป็นเขตข้อมูล แต่ไม่ใช่คีย์หลัก คีย์หลักจะต้องไม่ซ้ำกันและสามารถใช้ภายในสำหรับการทำแผนที่ความสัมพันธ์ หากเขตข้อมูลในการจัดทำดัชนีมันสามารถค้นหาได้อย่างรวดเร็วโดยที่แบบสอบถาม userXveryY.where ( 'INVOICE_NUMBER', 'foobarbaz10') ได้รับ ().
Tschallacka

1
คุณกำลังตอบคำถามทางเทคนิคโดยมีเหตุผลที่ไม่จำเป็นเนื่องจากมีลักษณะเฉพาะของสหรัฐอเมริกา (ต้องมีหมายเลขใบแจ้งหนี้ตามลำดับรายงานที่หอการค้า) IMO นี้ไม่ตอบคำถามได้ดี
RemcoGerlich

7

คุณอาจจะสามารถใช้แฮชิดสำหรับสิ่งนี้มันถูกออกแบบมาเพื่อแก้ไขสถานการณ์นี้

มันจะเข้ารหัสรหัสฐานข้อมูลของคุณลงในแฮชแบบสั้น ๆ (คล้ายกับ URL ของวิดีโอ YouTube) และคุณจะไม่ต้องเพิ่มคีย์รองลงในตารางของคุณ


2
ชื่อค่อนข้างเข้าใจผิดเนื่องจากไม่ใช่แฮช แต่เป็นฟังก์ชันที่สามารถย้อนกลับได้ แต่ดูเหมือนว่าจะเป็นทางออกที่สมบูรณ์แบบสำหรับปัญหา
โยเกิร์ตบ้า

2
@CrazyYoghurt จริง ... พวกเขาพูดถึงเหตุผลในการตั้งชื่อตามที่พวกเขาทำที่นี่: hashids.org/#why-hashids
Eric King

3

คุณสามารถสร้างคีย์พิเศษอื่นได้ แต่ไม่ควรทำ ไม่ใช่ด้วยเหตุผลที่กำหนด มีวิธีที่ง่ายกว่าในการซ่อนขนาดตาราง

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

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

โปรดทราบว่าด้วย AES คุณจะได้รับจำนวนเต็ม 128 บิตซึ่งหมายถึง 22 ตัวอักษรใน base64 อาจมากกว่าที่คุณต้องการ ตัวเลขที่มีขนาดบล็อก 64 เช่น DES หรือ 3DES ให้ 11 ตัวอักษรเช่นเดียวกับที่คุณต้องการ

ใช้ปุ่มที่แตกต่างกันสำหรับตารางที่แตกต่างกัน

หากสิ่งที่คุณต้องการซ่อนขนาดตารางคุณอาจใช้ลำดับทั่วไปสำหรับตารางทั้งหมด โปรดทราบว่ามันอาจเป็นคอขวดหากมีการแทรกบ่อยในตารางของคุณจำนวนมาก ด้วยบางสิ่งบางอย่างเช่นไฮเบอร์เนตและอัลกอริทึม Hi-Lo ปัญหานี้จะหายไป


ถูกต้อง - การจัดเก็บค่านี้เพื่อซ่อนค่าอื่นเป็นเพียงความผิด
Robbie Dee

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

ฉันจะสมัคร aes ที่นี่ได้อย่างไร
Dari

@Dari คุณสามารถนำ AES ไปใช้กับอะไรได้บ้าง? ไม่มีใครรู้ภาษาของคุณได้ โดยปกติแล้ว AES ทำงานกับ a byte[]คุณสามารถเขียนของคุณเป็นidสี่หรือแปดไบต์เพิ่มหมายเลขตารางที่ไม่ซ้ำกันและเข้ารหัส (อินพุตต้องมีขนาด 16 ไบต์) หากมีโหมดให้เลือก ECB นั้นถูกต้อง
maaartinus

@ แดนคืออะไร คุณอ้างว่า AES ไม่ปลอดภัยหรือไม่? ผู้โจมตีไม่สามารถทำอะไรได้ดีไปกว่าแอตทริบิวต์ที่เก็บไว้ ไม่มีอะไร +++ ฉันเดาว่าฉันไม่เข้าใจความคิดเห็นของคุณ
maaartinus

0

IMHO ไม่สามารถสร้างคีย์หลักสองแบบได้ แน่นอนคุณสามารถใส่ uuid นั้นใน DB เพื่อให้มันเป็น "นามแฝง" สำหรับคีย์หลักปัจจุบัน คุณสามารถวางดัชนีเหนือคอลัมน์นั้นด้วยข้อ จำกัด ที่ไม่ซ้ำกัน แต่คีย์หลักคือ (จากส่วนที่สำคัญ) หนึ่งเดียวภายในตารางเดียว อาจมีคีย์หลักผสม แต่นั่นไม่ใช่สิ่งที่คุณกำลังมองหา

ดังนั้นฉันขอแนะนำให้วางไว้ที่นั่น แต่มีเฉพาะกับดัชนี คุณสามารถสร้างองค์ประกอบการจัดการสำหรับการสืบค้นข้อมูลโดย PK เช่นเดียวกับคอลัมน์ที่ไม่ซ้ำกันอื่น ๆ เมื่อจัดการคำขอ "/ ใบแจ้งหนี้ / ... " เพียงตรวจสอบพารามิเตอร์ - ถ้าเป็นจำนวนเต็มให้ค้นหา ID หรือค้นหา uuid หรือคุณสามารถใช้การค้นหา uuid เป็นทางเลือกเมื่อการค้นหา ID ไม่พบอะไรเลย

และเกี่ยวกับการสร้าง uuids แบบ "สุ่ม": ทำไมไม่เช่น "รับ ID, เพิ่มค่าคงที่, แปลงเป็นเลขฐานสิบหก" ความผิดปกติของ ID จะให้เอกลักษณ์ของ uuid เลขฐานสิบหกนั้นยากต่อการอ่านสำหรับมนุษย์ทั่วไป + การเพิ่มค่าคงที่จะหลีกเลี่ยงการมี uuid เช่น 00000001


1
"ทำไมไม่ชอบ" ใช้ ID เพิ่มค่าคงที่แปลงเป็นเลขฐานสิบหก "- เพราะนั่นเป็นเรื่องง่ายที่จะคิดออก - ให้ฉัน URL และฉันจะได้ดูใบแจ้งหนี้อื่น ๆ ทั้งหมดในระบบ IMO ไม่มีปัญหา ว่าสิ่งนี้จริงแก้เพียงคนที่มันอาจสร้าง
CompuChip

" เมื่อจัดการคำขอสำหรับ '/ ใบแจ้งหนี้ / ...' เพียงแค่ตรวจสอบพารามิเตอร์ - ถ้ามันเป็นจำนวนเต็มค้นหารหัสมิฉะนั้นค้นหา uuid " จุดรวม (ตามที่ผมเข้าใจคำถาม) เพื่อป้องกันไม่ให้คนค้นหาโดยใช้ ID ( /invoices/123, /invoices/124, ... ) ดังนั้นคุณจะค้นหาด้วย UUID จาก URL เท่านั้น
TripeHound

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

@CompuChip ตามที่คุณคาดหวังคุณสนใจในคอมพิวเตอร์ :-) ดังนั้นคุณจึงจำเลขฐานสิบหกสำหรับการพบครั้งแรก แต่คำถามนั้นเขียนในลักษณะที่จะไม่แสดงหมายเลขใบแจ้งหนี้โดยตรงเพื่อให้ผู้อื่นทราบว่ามีใบแจ้งหนี้กี่ใบ เมื่อฉันแสดงเลขฐานสิบหกแก่ภรรยาแม่เพื่อนบ้าน ... พวกเขาจะไม่รู้ว่า "ข้อความแปลก ๆ " คืออะไร หากจะมีการแจ้งให้ทราบเกี่ยวกับปัญหาด้านความปลอดภัยตามหมายเลขใบแจ้งหนี้ภายใน Q ฉันจะแนะนำวิธีการแฮชที่ซับซ้อนสำหรับจุดประสงค์นั้น
Jarda

@TripeHound เขายังอาจสามารถค้นหาด้วย ID ภายในหรือภายในจุดเข้าใช้งานที่ จำกัด ...
Jarda

0

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

หรือคุณสามารถสร้างตารางการทำแผนที่ภาคผนวกซึ่งจะเก็บคีย์ทั้งสองเวอร์ชัน ตารางนี้จะทำหน้าที่เป็นพจนานุกรมในการค้นหาคีย์รอง

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


+1 ใช่เพิ่มสิ่งที่อาจเป็นคอลัมน์สตริงขนาดใหญ่ที่มีดัชนีแน่นอนไม่คุ้มค่าดำเนินการอื่น ๆ ที่แนะนำ การจัดเก็บค่าใช้จ่ายกันเมื่อดัชนีได้รับเพิ่มความเร็วในการแทรกเริ่มลดลง
Robbie Dee

0

อีกวิธีหนึ่งสำหรับกรณีการใช้งานเฉพาะของคุณคือแทนที่จะปรับเปลี่ยนฐานข้อมูลและแอปพลิเคชันคุณสามารถสร้างเส้นทางที่กำหนดเองไปยังใบแจ้งหนี้เพื่อให้ / Invoices /: f (id) โดยที่ f (id) เป็นหน้าที่ของ ID

เส้นทางที่กำหนดเองมีหน้าที่รับผิดชอบในการจับคู่คำร้องขอไปยังฝั่งแอ็คชันเซิร์ฟเวอร์ที่ถูกต้อง


0

มันเป็นแนวปฏิบัติที่ยอมรับได้อย่างสมบูรณ์หรือที่เรียกว่า 'Alternate Key' (AK) โดยทั่วไป AK เป็นดัชนีที่ไม่ซ้ำใครหรือข้อ จำกัด ที่ไม่ซ้ำกัน

คุณสามารถสร้างข้อ จำกัด กุญแจต่างประเทศตาม AK ของคุณ

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


0

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

เนื่องจากคำถามอยู่ในบริบทของใบแจ้งหนี้และตัวเลขจึงอาจคุ้มค่าที่จะศึกษาว่าอุตสาหกรรมบัญชีคาดหวังว่าจะมีหมายเลขใบแจ้งหนี้ให้ดูอย่างไร: http://smallbusiness.chron.com/assign-invoice-numbers-52422.html

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

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


0

ไปเลย

สิ่งนี้ไม่แตกต่างจากฟิลด์ "กระสุน" ที่บทความในบล็อกและสิ่งที่คล้ายกันมี - วิธีที่ไม่ซ้ำกันในการอ้างถึงบันทึกฐานข้อมูลแยกต่างหากจากคีย์หลักเหมาะสำหรับใช้ใน URL ฉันไม่เคยได้ยินใครโต้แย้ง

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