สตริงเป็นคีย์หลักในฐานข้อมูล SQL


178

ฉันไม่คุ้นเคยกับฐานข้อมูลและทฤษฎีเบื้องหลังการทำงานของพวกเขา มันช้าลงหรือไม่จากจุดยืนประสิทธิภาพ (การแทรก / อัพเดต / การสืบค้น) เพื่อใช้ Strings สำหรับคีย์หลักมากกว่าจำนวนเต็ม?

คำตอบ:


191

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


11
มันจะไม่ขึ้นอยู่กับฐานข้อมูลหรือไม่ ฉันคิดว่าสตริงที่มีการจัดทำดัชนีอย่างถูกต้องนั้นจะไม่ช้ากว่านี้ถ้าหากจากตัวเลข?
Ryan Guill

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

1
ยุติธรรมพอสมควร ฉันจะยอมรับว่าถ้าเป็นสตริงที่เหมาะสมนั่นคือสิ่งที่คุณควรใช้ ฉันจะบอกว่ามีบางครั้งสำหรับเขตข้อมูล GUID หรือ UUID ในฐานข้อมูลที่เขตข้อมูลการสร้างอัตโนมัติจะไม่ทำงาน
Ryan Guill

7
นอกจากนี้ยังทราบว่ามักจะมีความแตกต่างใหญ่มากระหว่าง CHAR และ VARCHAR เมื่อทำการเปรียบเทียบดัชนี
ทอม H

7
จำนวนความคิดเห็นของคำตอบนี้ทำให้ชัดเจนว่ามันไม่สมบูรณ์ การกล่าวถึงการจัดทำดัชนีจะเป็นคำตอบที่ได้รับการยอมรับขั้นต่ำ
Pedro Rolo

74

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


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

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

มีการสั่ง XID ซึ่งอาจช่วยถ้าคุณใช้สายอักขระ xid
Sinaesthetic

22

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


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

13

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

ฉันยังต้องการชี้ให้เห็นว่าสิ่งที่ดีที่สุดของโลกทั้งสองนั้นมักจะใช้คีย์ autoincrementing key (หรือในบางกรณีพิเศษ GUID) เป็น PK และวางดัชนีเฉพาะบนคีย์ธรรมชาติ คุณได้รับการเข้าร่วมที่เร็วขึ้นคุณไม่ได้รับการบันทึกที่ซ้ำกันและคุณไม่จำเป็นต้องอัปเดตระเบียนย่อยนับล้านเพราะชื่อ บริษัท เปลี่ยนไป


26
สตริงที่เป็นตัวเลือกที่ดีสำหรับ PKs ไม่มีการซ้ำซ้อน - ไม่เช่นนั้นจะไม่เป็นตัวเลือกที่ดีสำหรับ PK คิดถึงรหัส ICD-9, รหัสประเทศ, VIN #s การใช้ชื่อเป็นตัวอย่างของปัญหากับคีย์ธรรมชาตินั้นถูกเข้าใจผิดเพราะพวกเขาไม่ควรเป็นผู้สมัครในตอนแรก
Tom H

6
@Tom H: รหัส ISO County จะเปลี่ยนไป [ en.wikipedia.org/wiki/ISO_3166-1#Editions_and_changes ] เป็นคำตอบสำหรับคำถามที่เกี่ยวข้องกล่าวว่า [ stackoverflow.com/questions/925266/ … ] "สำหรับคีย์หลักตรวจสอบให้แน่ใจว่าเอกลักษณ์ของพวกเขาอยู่ภายใต้การควบคุมของคุณ"
Steve Schnepp

4
@SteveSchnepp: ใช่และ ISO เป็นหน่วยงานที่เชื่อถือได้สำหรับการจัดการการเปลี่ยนแปลงนั้น ในทางกลับกันเมื่อคุณจำเป็นต้องรวมลำดับเลขคณิตของการเพิ่มค่าจำนวนเต็มกับคนอื่นคุณจะต้องอยู่ด้วยตัวเอง;)
onedaywhen

1
ฉันจะยอมรับว่าชื่อ shoud ไม่ได้รับการพิจารณาว่าเป็นกุญแจสำคัญฉันได้เห็นว่าทุกครั้งที่พวกเขาอยู่
HLGEM

1
@onedaywhen ผสาน 2 ลำดับต่อเนื่องของการเพิ่มจำนวนเต็มที่จะกระทำได้อย่างง่ายดายผ่านทาง prefixing หรือ suffixing :)
สตีฟ Schnepp

6

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

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


5

มีตัวแปรมากเกินไป ขึ้นอยู่กับขนาดของตารางดัชนีลักษณะของโดเมนคีย์สตริง ...

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

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


มันไม่สมเหตุสมผลคุณหมายถึงอะไร?
HLGEM

@HLGEM: ถ้าฉันเข้าใจเขาเขียนเขาหมายถึงการซิงค์ข้อมูลที่สร้างขึ้นบนแล็ปท็อปที่มีฐานข้อมูลหลัก
Joel Coehoorn

ฉันหมายถึงฉันมีฐานข้อมูลแยกกันสองฐานโดยมีเอนทิตีเดียวกันมีเพียงหนึ่งฐานเท่านั้นที่ได้รับการปรับปรุงน้อยลงเพื่อจุดประสงค์ในการจัดเก็บข้อมูลแบบถาวร ถ้าฉันค้นหาองค์กร "California" ในฐานข้อมูล A ฉันต้องการให้มันเป็น "California" พื้นฐานในฐานข้อมูล B.
mainstringargargs

1
และมันเป็น 'like' การซิงค์เร็กคอร์ดที่สร้างขึ้นในแล็ปท็อปซึ่งเป็นปัญหาเดียวกัน: เรคคอร์ดที่สร้างในที่เดียวไม่ควรขัดแย้งกับเรคคอร์ดที่สร้างขึ้นในที่อื่น ทางออกหนึ่งที่เป็นไปได้ที่นี่คือปุ่ม Guid
Joel Coehoorn

5

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

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

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

โปรแกรมเมอร์และผู้ใช้แบบโต้ตอบที่ระบุคิวรีสามารถใช้คีย์ธรรมชาติเพื่อรับสิ่งที่ต้องการได้หรือไม่?

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


3

ดัชนีบ่งบอกถึงการเปรียบเทียบจำนวนมาก

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

แม้ว่าบางครั้งมันจะเร็วกว่าที่จะใช้สตริงเป็นคีย์หลักกว่าเพื่อเข้าร่วมเป็นพิเศษกับstring to numerical idตาราง


2

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

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


2

เหตุผลสองประการในการใช้จำนวนเต็มสำหรับคอลัมน์ PK:

  1. เราสามารถกำหนดตัวตนสำหรับฟิลด์จำนวนเต็มซึ่งเพิ่มขึ้นโดยอัตโนมัติ

  2. เมื่อเราสร้าง PKs db จะสร้างดัชนี (Cluster หรือ Non Cluster) ซึ่งเรียงลำดับข้อมูลก่อนที่จะถูกเก็บไว้ในตาราง โดยการใช้ข้อมูลประจำตัวบน PK เครื่องมือเพิ่มประสิทธิภาพไม่จำเป็นต้องตรวจสอบลำดับการจัดเรียงก่อนบันทึกเรกคอร์ด สิ่งนี้ช่วยปรับปรุงประสิทธิภาพการทำงานในตารางขนาดใหญ่


1

คุณมีเหตุผลอะไรที่มีสตริงเป็นคีย์หลัก

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

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

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


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

1
ตัวอย่างของการใช้สตริงเป็น PK อาจเป็นตารางการตั้งค่า เช่น settingNamePK, isUserEditable, isCustomerEditable ฯลฯ จากนั้นหากคุณต้องการแก้ไขพฤติกรรมการตั้งค่า "การตั้งค่า UPDATE SET SET ... WHERE settingNamePK = 'dailyWorkObligation'" นั้นยอดเยี่ยมกว่าการใช้ ID และเก็บตำแหน่งของ ID แน่นอนคุณสามารถมีจำนวนเต็ม PK และมีชื่อการตั้งค่าเป็นคีย์ที่ไม่ซ้ำกันอีกเช่นกัน
MeatPopsicle

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

สำหรับ devs อยากรู้อยากเห็นรถไฟที่นี่เป็นวิธีการที่จะระบุระยะเวลาในดัชนี โปรดทราบว่า SQLite ไม่รองรับความยาวดัชนี
เดนนิส

1

จากมุมมองประสิทธิภาพ - ใช่สตริง (PK) จะทำให้ประสิทธิภาพลดลงเมื่อเทียบกับประสิทธิภาพที่ทำได้โดยใช้จำนวนเต็ม (PK) โดยที่ PK ---> คีย์หลัก

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

ดังนั้นสำหรับการใช้งานที่เหมาะสม - เรามักจะรวมจำนวนเต็ม 1 หรือ 2 กับแอตทริบิวต์สตริง 1 หรือ 2 แต่อีกครั้งถ้าจำเป็นเท่านั้น


0

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

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


0

โดยค่าเริ่มต้น ASPNetUserIds เป็น 128 อักขระถ่านและประสิทธิภาพก็ดี

ถ้าคีย์HASจะไม่ซ้ำกันในตารางมันควรจะเป็นกุญแจสำคัญในการ นี่คือเหตุผล;

primary string key = แก้ไขความสัมพันธ์ของฐานข้อมูล, 1 สตริงคีย์ (หลัก), และ 1 สตริงดัชนี (The Primary)

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

ดังนั้นการใช้รหัสประจำตัว int = ความสัมพันธ์ของฐานข้อมูลที่ไม่ถูกต้อง, 1 int คีย์ (หลัก), 1 int ดัชนี (หลัก), น่าจะเป็นดัชนีสตริงที่ไม่ซ้ำกันและด้วยตนเองต้องตรวจสอบสตริงเดียวกันไม่มีอยู่ (เช่นเช็ค sql )

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

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