ข้อดีและข้อเสียของคีย์ฐานข้อมูล GUID / UUID


222

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

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


1
Jeff มีโพสต์เกี่ยวกับเรื่องนี้ " คีย์หลัก: รหัสกับ GUID "
jfs

1
ยังสามารถใช้ Hi-Lo สำหรับลูกค้าระยะไกล: stackoverflow.com/questions/282099/whats-the-hi-lo-algorithm
Neil McGuigan


อัปเดตตำแหน่งสำหรับโพสต์ของ Jeff Atwood เกี่ยวกับ " คีย์หลัก: รหัสกับ GUID " ขอบคุณ @jfs สำหรับการอ้างอิง
Adam Katz

@jfs Link ได้เปลี่ยนเป็นblog.codinghorror.com/primary-keys-ids-versus-guids
cr0ss

คำตอบ:


229

ข้อดี:

  • สามารถสร้างพวกเขาออฟไลน์
  • ทำให้การจำลองแบบเล็กน้อย (ตรงข้ามกับ int ซึ่งทำให้ยากจริงๆ)
  • ORM มักจะชอบพวกเขา
  • แอพพลิเคชั่นที่ไม่เหมือนใคร ดังนั้นเราสามารถใช้ PK จาก CMS ของเรา (guid) ในแอปของเรา (เช่น guid) และรู้ว่าเราไม่เคยได้รับการปะทะกัน

ข้อเสีย:

  • การใช้พื้นที่มากขึ้น แต่พื้นที่ราคาถูก (เอ้อ)
  • ไม่สามารถสั่งซื้อด้วย ID เพื่อรับใบสั่งแทรก
  • สามารถดูน่าเกลียดใน URL แต่จริงๆแล้ว WTF คุณกำลังใส่คีย์ REAL DB ใน URL! (จุดนี้โต้แย้งในความคิดเห็นด้านล่าง)
  • ยากที่จะทำการดีบักด้วยตนเอง แต่ไม่ยาก

โดยส่วนตัวแล้วฉันใช้มันสำหรับ PK ส่วนใหญ่ในระบบที่มีขนาดพอเหมาะ แต่ฉันได้รับ "การฝึกอบรม" ในระบบที่ทำซ้ำทั่วทุกสถานที่ดังนั้นเราจึงมีมัน YMMV

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

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

อัปเดต: ดังนั้นสิ่งนี้ได้รับ +1 มากและฉันคิดว่าฉันควรชี้ให้เห็นข้อเสียใหญ่ของ GUID PK's: ดัชนีแบบกลุ่ม

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

ดังนั้นหากคุณต้องการเพิ่มประสิทธิภาพการทำงานอาจใช้ auto-inc INT และสร้าง GUID ถ้าคุณต้องการแบ่งปันกับคนอื่น (เช่นแสดงให้ผู้ใช้เห็นใน URL)


184
[WTF คุณกำลังวางคีย์ REAL DB ใน URL !?] ไม่แน่ใจว่าทำไมมันถึงรบกวนคุณ คุณจะใช้อะไรอีก ดู Stack Overflow ... มันมีค่าตัวตนใน URL ทั่วทุกสถานที่และใช้งานได้ดี การใช้คีย์ DB ใน URL ไม่ได้ป้องกันคุณจากการบังคับใช้ความปลอดภัย
Euro Micelli

20
ไม่มันไม่ได้ แต่สิ่งต่าง ๆ เช่น SEO มักจะดีกว่าถ้าไม่มีกุญแจอยู่ - โดยเฉพาะอย่างยิ่งตราบใดที่ GUID แน่นอนมันสามารถทำงานได้อย่างง่ายดายดังนั้นฉันคิดว่านั่นเป็นคำพูดที่กว้างเกินกว่าจะเป็นจริง
Nic Wise

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

26
ระลึกถึงสิ่งหนึ่งผู้คนมักเปลี่ยนหน้าคำถามชื่อฟอรัม สำหรับ SEO มันเป็นเรื่องที่ดีถ้ามี ID ขนาดเล็กใน URL ดังนั้นหากชื่อเรื่องมีการเปลี่ยนแปลงคุณยังคงรู้ว่าจะส่งต่อคนที่มาจาก URL เก่าอย่างไร example.com/35/old-and-bustedเพิ่งเป็นexample.com/35/new-hotnessและคุณเป็นแอพสามารถตรวจสอบชื่อและส่งต่อผู้ใช้ด้วย 301
Xeoncross

9
การจัดทำดัชนี GUID มีราคาแพงและช้าซึ่งทำให้ผู้สมัครที่ไม่ดีสำหรับคีย์หลัก
Matthew James Davis

14

@ Matt Sheppard:

สมมติว่าคุณมีโต๊ะลูกค้า แน่นอนว่าคุณไม่ต้องการให้ลูกค้าอยู่ในตารางมากกว่าหนึ่งครั้งมิฉะนั้นความสับสนจะเกิดขึ้นตลอดแผนกขายและโลจิสติกส์ของคุณ (โดยเฉพาะอย่างยิ่งถ้าหลายแถวเกี่ยวกับลูกค้ามีข้อมูลแตกต่างกัน)

ดังนั้นคุณมีตัวระบุลูกค้าที่ระบุลูกค้าโดยไม่ซ้ำกันและคุณต้องแน่ใจว่าลูกค้านั้นเป็นที่รู้จักตัวระบุ (ในใบแจ้งหนี้) เพื่อให้ลูกค้าและพนักงานบริการลูกค้ามีการอ้างอิงทั่วไปในกรณีที่พวกเขาต้องการสื่อสาร ในการรับประกันว่าไม่มีระเบียนลูกค้าที่ซ้ำซ้อนคุณเพิ่มข้อ จำกัด ที่ไม่ซ้ำกันลงในตารางโดยใช้คีย์หลักบนตัวระบุลูกค้าหรือผ่านข้อ จำกัด NOT NULL + UNIQUE ในคอลัมน์ตัวระบุลูกค้า

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

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

กล่าวอีกนัยหนึ่ง: อาจมีเหตุผลที่ดีในการเพิ่มคอลัมน์ GUID ลงในตาราง แต่โปรดอย่าหลงลืมสิ่งนี้เพื่อลดความทะเยอทะยานของคุณลงเพื่อความสอดคล้องภายในข้อมูลจริง (== ที่ไม่ใช่ GUID)


1
ได้ยินได้ยิน! รักหน้าเปรียบเทียบ SQL ของคุณ btw มีประโยชน์อย่างยิ่ง สิ่งเดียวที่ฉันพลาดคือการเปลี่ยนแปลง
Henrik Gustafsson

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

12

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


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

1
UUIDs เพียง 4 เท่าของจำนวนเต็ม ... (ถ้าฐานข้อมูลของคุณมีประเภท UUID ก)
Jasen

11

GUID อาจทำให้คุณมีปัญหามากในอนาคตหากใช้เป็น "ตัวถอดรหัส" การปล่อยให้ข้อมูลที่ซ้ำซ้อนเข้าสู่ตารางของคุณ หากคุณต้องการใช้ GUID โปรดพิจารณายังคงรักษาข้อ จำกัด UNIQUE ไว้ในคอลัมน์อื่น ๆ


11
นี่คือหัวใจของปัญหา: การแนะนำ GUID ทำให้แถวใดเป็นเอกลักษณ์ แต่ส่วนที่ไม่ใช่ของเทียมอาจมีข้อมูลที่ซ้ำซ้อน (ความจริงหลายรุ่น)
Troels Arvin

8
+1 เพื่อชดเชย ฉันเห็นสิ่งที่คุณหมายถึง แต่มันแสดงออกไม่ดี
Stefano Borini

11

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

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

มีปัญหาประสิทธิภาพบางอย่างเช่นการแตกแฟรกเมนต์ดัชนี แต่สิ่งเหล่านี้สามารถแก้ไขได้อย่างง่ายดาย (หวี guys โดย jimmy nillson: http://www.informit.com/articles/article.aspx?p=25862 )

แก้ไขรวมสองคำตอบของคำถามนี้

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


ฉันรู้เกี่ยวกับหวีนำและผู้ช่วยแก้ไขปัญหาการจัดทำดัชนี (ประสิทธิภาพ INSERT) " ข้อเสียเปรียบหลักจำเป็นต้องใช้พื้นที่เก็บข้อมูลเพิ่มขึ้นเล็กน้อย " สิ่งนี้จะกระทบกับประสิทธิภาพการทำงานเนื่องจากขนาดไฟล์ฐานข้อมูลขนาดใหญ่หรือไม่
Amit Joshi

8

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


6

คีย์หลัก-รหัสเมื่อเทียบกับ guids

ต้นทุนของ GUID เป็นคีย์หลัก (SQL Server 2000)

Myths, GUID vs. Autoincrement (MySQL 5)

นี่คือสิ่งที่คุณต้องการจริงๆ

ข้อดีของ UID

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

ข้อด้อยของ GUID

  • มันใหญ่กว่าค่าดัชนี 4 ไบต์แบบเดิมถึง 4 เท่า สิ่งนี้อาจมีประสิทธิภาพที่ร้ายแรงและความหมายของพื้นที่จัดเก็บหากคุณไม่ระวัง
  • ยุ่งยากในการแก้ปัญหา (โดยที่ userid = '{BAE7DF4-DDF-3RG-5TY3E3RF456AS10}')
  • GUID ที่สร้างขึ้นควรเรียงตามลำดับบางส่วนเพื่อประสิทธิภาพที่ดีที่สุด (เช่น newsequentialid () บน SQL 2005) และเพื่อให้สามารถใช้ดัชนีแบบคลัสเตอร์ได้

1

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

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

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

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