ฉันควรลงทุนเวลาเปลี่ยนประเภทคอลัมน์จาก CHAR (36) เป็น UUID หรือไม่


14

ฉันมีไม่กี่ล้านแถวในฐานข้อมูลของฉันแล้ว ฉันไม่รู้เกี่ยวกับชนิดข้อมูล PostgreSQL UUID เมื่อฉันออกแบบสคีมาของฉัน

หนึ่งในตารางมีแถว 16M (ประมาณ 3.5M ถึง 4 M ระเบียนต่อชาร์ด) เติบโตที่ประมาณ 500K ระเบียนต่อวัน ฉันยังคงมีความหรูหราในการทำให้ระบบการผลิตหยุดลงหากต้องการ ฉันจะไม่มีความหรูหรานี้ในหนึ่งหรือสองสัปดาห์

คำถามของฉันคือมันจะคุ้มค่าที่จะทำเช่นนั้น? ฉันสงสัยเกี่ยวกับประสิทธิภาพของ JOIN การใช้พื้นที่ดิสก์ (การถ่ายโอนข้อมูลแบบเต็ม gzip คือ 1.25 GiB) สิ่งต่าง ๆ ในลักษณะนั้น

สคีมาของตารางคือ:

# \d twitter_interactions
                Table "public.twitter_interactions"
         Column          |            Type             | Modifiers 
-------------------------+-----------------------------+-----------
 interaction_id          | character(36)               | not null
 status_text             | character varying(1024)     | not null
 screen_name             | character varying(40)       | not null
 twitter_user_id         | bigint                      | 
 replying_to_screen_name | character varying(40)       | 
 source                  | character varying(240)      | not null
 tweet_id                | bigint                      | not null
 created_at              | timestamp without time zone | not null
Indexes:
    "twitter_interactions_pkey" PRIMARY KEY, btree (interaction_id)
    "twitter_interactions_tweet_id_key" UNIQUE, btree (tweet_id)
    "index_twitter_interactions_on_created_at" btree (created_at)
    "index_twitter_interactions_on_screen_name" btree (screen_name)
Triggers:
    insert_twitter_interactions_trigger BEFORE INSERT ON twitter_interactions FOR EACH ROW EXECUTE PROCEDURE twitter_interactions_insert_trigger()
Number of child tables: 9 (Use \d+ to list them.)

คำตอบ:


13

ฉันจะพิจารณาเปลี่ยนเป็นประเภท UUID char(36)ใช้ 40 ไบต์uuidใช้เวลา 16 ดังนั้นคุณจะประหยัด 24 ไบต์ต่อแถวซึ่งสำหรับคุณจะเท่ากับ 12 MB ต่อวัน 4 GB หลังจากปี บวกดัชนี ขึ้นอยู่กับว่าคุณมีฮาร์ดแวร์อะไรบ้าง แต่ก็อาจเป็นได้ และมันจะเพิ่มขึ้นถ้าคุณมีโอกาสในการพัฒนามากขึ้นเช่นนี้

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

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


ฉันมีระบบแบบกระจาย: แหล่งข้อมูลหลายแหล่งสร้าง ID สำหรับการโต้ตอบดังนั้นฉันไม่สามารถใช้ BIGINT ธรรมดายกเว้นว่าฉันจอง N บิตสำหรับโหนด ID
François Beausoleil

3
@ FrançoisBeausoleilการจองบิต N สำหรับโหนด ID เท่ากับการใช้หมายเลข Nth ทุกตัวในลำดับ (และใช้งานง่าย) นอกจากนี้คุณอาจลองใช้คีย์ผสม
ไม่มีเหตุผล

1
การประสานงานหลายลำดับ (ด้วย ID โหนด) เป็นความยุ่งยากในการจัดการในทางปฏิบัติและมีแนวโน้มที่จะเกิดข้อผิดพลาดของมนุษย์ ฉันเห็นว่าไม่มีเหตุผลที่จะไม่ใช้ UUID ในสถานการณ์นี้โดยเฉพาะอย่างยิ่งบิตที่มีราคาถูกในปัจจุบัน (ทั้งหน่วยความจำและที่เก็บข้อมูล) อันที่จริงสถานการณ์นี้เป็นเหตุผลมาก UUIDs ถูกคิดค้นมานานหลายทศวรรษที่ผ่านมา: การใช้ข้อมูลร่วมกันในหมู่ระบบกระจายโดยไม่ต้องประสานงานส่วนกลาง
Basil Bourque

6

ฉันไม่ใช่คน postgres ด้วยจินตนาการใด ๆ แต่ขึ้นอยู่กับสิ่งที่ฉันรู้จาก SQL Server แถวยิ่งคุณสามารถพอดีกับหน้าข้อมูลประสิทธิภาพที่ดีขึ้นคุณจะมี (โดยทั่วไปการอ่านข้อมูลจากดิสก์ การดำเนินการที่แพงที่สุด) ดังนั้นการเปลี่ยนจากฟิลด์ที่มีความกว้าง36 ish 1ไบต์ไปเป็น 16 ไบต์GUIDดูเหมือนจะเป็นการประหยัดต้นทุนโดยตรง ยิ่งคุณอ่านน้อยลงเท่าไรคุณก็จะได้ผลลัพธ์เร็วขึ้นเท่านั้น แน่นอนทั้งหมดนี้ถือว่า GUID / UUID ตรงตามความต้องการทางธุรกิจของตาราง ถ้า UUID เป็นที่พอใจมันจะเป็นเรื่องใหญ่หรือไม่? นั่นจะเป็นการประหยัดพื้นที่เก็บข้อมูลของคุณอีก 8 ไบต์ต่อแถว

แก้ไข1

สำหรับข้อมูลตัวละครใน Postgres มีค่าใช้จ่ายในการจัดเก็บเพิ่มเติมสำหรับพวกเขา สตริงสั้น ๆ ที่ต่ำกว่า 127 ไบต์มีค่าใช้จ่าย 1 ไบต์ในขณะที่สิ่งใดอีกต่อไปมี 4 ไบต์ซึ่งเป็นวิธีที่ผู้ตอบที่สองมาด้วยค่า 40 ไบต์สำหรับเขตข้อมูล 36 ไบต์ แต่ยังมีตัวเลือกสำหรับการบีบอัดสตริงดังนั้นอาจจะไม่เสียค่าใช้จ่ายเต็ม 40 ฉันไม่สามารถบอกได้ว่าราคาสุดท้ายจะเป็นอย่างไร แต่ปัจจัยพื้นฐานยังคงอยู่: อะไรก็ตามที่มีมากกว่า 16 ไบต์จะเพิ่มต้นทุนการจัดเก็บ และใช้หน่วยความจำมากขึ้น

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


3

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


นั่นคือที่ได้รับ แต่ขอบคุณที่เตือนฉัน
François Beausoleil

3
เมื่อทำการเปลี่ยนแปลงครั้งใหญ่เช่นนี้ฉันพบว่าการเขียนทุกอย่างลงไป (ไม่ว่าจะจำง่ายแค่ไหนก็ตาม) มักจะจ่าย
mrdenny

3

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

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

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

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


ขอบคุณสำหรับการสนับสนุนที่เป็นประโยชน์และยินดีต้อนรับสู่เว็บไซต์ :)
แจ็คบอกว่าลอง topanswers.xyz

รูปแบบการเข้าถึงของฉันผ่านช่วงวันที่เข้าร่วมโดยใช้ screen_name หรือโดย UUID ไม่คาดว่าจะทำการสแกนหารหัสเฉพาะ ขอบคุณสำหรับคำตอบของคุณมีข้อมูลมาก
François Beausoleil
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.