การค้นหาดัชนีจะเร็วขึ้นอย่างเห็นได้ชัดด้วย char vs varchar หรือไม่เมื่อค่าทั้งหมดเป็น 36 ตัวอักษร


30

ฉันมีแบบแผนดั้งเดิม (ข้อจำกัดความรับผิดชอบ!) ที่ใช้รหัสที่สร้างโดยใช้แฮชสำหรับคีย์หลักสำหรับตารางทั้งหมด (มีจำนวนมาก) ตัวอย่างของ ID ดังกล่าวคือ:

922475bb-ad93-43ee-9487-d2671b886479

ไม่มีความหวังที่เป็นไปได้ในการเปลี่ยนวิธีการนี้อย่างไรก็ตามประสิทธิภาพของการเข้าถึงดัชนีนั้นไม่ดี การตั้งค่ากันมากมายเหตุผลนี้อาจจะมีสิ่งหนึ่งที่ผมสังเกตเห็นว่าดูเหมือนน้อยกว่าที่ดีที่สุด - แม้จะมีค่า ID ทั้งหมดในตารางมากทั้งหมดเป็นว่า 36 ตัวอักษรความยาวชนิดคอลัมน์varchar(36), ไม่ char(36)

การเปลี่ยนประเภทคอลัมน์เป็นความยาวคงที่จะchar(36)ให้ประโยชน์ด้านดัชนีอย่างมีนัยสำคัญหรือไม่นอกเหนือจากการเพิ่มจำนวนรายการต่อหน้าดัชนีเป็นต้น?

คือ postgres ทำงานเร็วกว่ามากเมื่อจัดการกับประเภทความยาวคงที่มากกว่าประเภทความยาวผันแปรหรือไม่

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

คำตอบ:


40

เลขที่ไม่ได้รับที่ทุกคน คู่มือระบุอย่างชัดเจน :

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

ฉันเน้นตัวหนา

char(n)เป็นชนิดที่ล้าสมัยและไร้ประโยชน์เป็นส่วนใหญ่ varchar(n)ติดกับ หากคุณไม่ต้องการบังคับใช้ความยาวvarcharหรือtextจะเร็วขึ้นเล็กน้อย คุณจะไม่สามารถวัดความแตกต่างได้

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

ที่เกี่ยวข้อง:

คุณไม่ได้ขอทางเลือกอื่นแต่ฉันจะพูดถึงสองอย่าง:

  1. COLLATION- ถ้าคุณกำลังเรียกใช้ฐานข้อมูลของคุณด้วย"C" เปรียบเทียบ การเรียงหน้านั้นมักถูกมองข้ามและอาจมีราคาแพง เนื่องจากสายอักขระของคุณดูเหมือนจะไม่มีความหมายในภาษาธรรมชาติจึงอาจไม่มีประเด็นในการติดตามCOLLATIONกฎ ที่เกี่ยวข้อง:

    การเปรียบเทียบประสิทธิภาพที่กว้างขวาง (รวมถึงอื่น ๆ ) ผลกระทบของCOLLATE "C"ประสิทธิภาพ:

  2. UUIDอย่างเห็นได้ชัด สตริงของคุณอย่างน่าสงสัยดูเหมือน UUID (ตัวเลขฐานสิบหก 32 หลักบวก 4 ตัวคั่น) มันจะมีประสิทธิภาพมากขึ้นในการจัดเก็บเหล่านี้เป็นuuidชนิดข้อมูลจริงซึ่งเร็วกว่าในหลายวิธีและมีเพียง 16ไบต์ - เมื่อเทียบกับ 37ไบต์ใน RAM สำหรับอย่างใดอย่างหนึ่งchar(36)หรือvarchar(36)(เก็บไว้โดยไม่มีตัวคั่นเพียง 32 กำหนดถ่าน) หรือ 33ไบต์บนดิสก์ แต่การขยายการจัดตำแหน่งจะส่งผลให้ 40ไบต์ในหลายกรณีเช่นกัน)COLLATIONจะไม่เกี่ยวข้องกับuuidชนิดข้อมูลเช่นกัน

    SELECT '922475bb-ad93-43ee-9487-d2671b886479'::uuid

    สิ่งนี้อาจเป็นประโยชน์ (บทสุดท้าย):

    ดูสิ่งนี้ด้วย:


หมายความว่าความยาวที่ จำกัด char / varchar (n) จะใช้ CPU รอบในการตรวจสอบข้อ จำกัด ในขณะที่ฟิลด์ข้อความที่มีความยาวผันแปรจะเก็บข้อความแยกต่างหากในวิธีที่เข้าถึงได้น้อยกว่าเมื่อเปรียบเทียบกับ char ผู้ชนะในสถานการณ์นี้ แม้มูลค่าการพิจารณาว่าจะมี 10 ล้านแถวพร้อมข้อความชิ้นหนึ่ง
PirateApp

1
@PirateApp: char(n)แทบไม่มีทางชนะในเรื่องใด ๆ อย่าใช้มัน ชนิดข้อมูลtextและvarchar(ไม่มีตัวปรับความยาว) สามารถทำงานร่วมกับไบนารีได้และแบ่งปันคุณสมบัติด้านประสิทธิภาพที่เหมือนกัน มีเหตุผลทางประวัติศาสตร์สำหรับทั้งคู่ที่จะอยู่ร่วมกันใน Postgres ภายในtextเป็นประเภท "ที่ต้องการ" ในหมู่สตริงประเภท (ซึ่งอาจมีผลต่อความละเอียดของประเภทฟังก์ชั่น) รอบการทำงานของ CPU สำหรับการบังคับใช้varchar(n)แทบจะไม่สำคัญ ใช้ข้อ จำกัด ความยาวเมื่อคุณต้องการมัน ในกรณีที่มือuuidเป็นผู้ชนะที่แท้จริง
Erwin Brandstetter
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.