ความสำคัญของความยาว varchar ในตาราง MySQL


113

ฉันมีตาราง MySQL ที่แทรกแถวแบบไดนามิก เนื่องจากฉันไม่สามารถมั่นใจได้ถึงความยาวของสตริงและไม่ต้องการให้ตัดออกฉันจึงสร้างมันเป็น varchar (200) ซึ่งโดยทั่วไปแล้วจะใหญ่กว่าที่ฉันต้องการมาก มีประสิทธิภาพที่ยอดเยี่ยมในการให้ฟิลด์ varchar ยาวเกินความจำเป็นหรือไม่?


ตารางที่มีVARCHAR(255) utf8mb4คอลัมน์เดียวที่จัดทำดัชนีโดยมีแถว ~ 150k วัดได้ 11.5MB ตารางที่มีVARCHAR(48) utf8mb4คอลัมน์ที่จัดทำดัชนีซึ่งมีข้อมูลเดียวกัน (ความยาวสูงสุด 46 ตัวอักษร) ใช้ 4.5MB ไม่ได้มีความแตกต่างอย่างมากในการสืบค้น แต่มีการจัดทำดัชนี แต่จะรวมกับแบบสอบถาม I / O และสิ่งต่างๆเช่นการสำรองฐานข้อมูล
Code4R7

คำตอบ:


59

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


9
ไม่ตรงกับความจริง ดูคำตอบของBill Karwin
hejdav

5
ฉันคิดว่าคำตอบเช่นควรได้รับการสนับสนุนจากเอกสารเกณฑ์มาตรฐานหรือสิ่งที่คล้ายกัน
Gokhan Sari

301

มีผลกระทบด้านประสิทธิภาพที่เป็นไปได้อย่างหนึ่ง: ใน MySQL ตารางชั่วคราวและMEMORYตารางจะจัดเก็บVARCHARคอลัมน์เป็นคอลัมน์ที่มีความยาวคงที่ซึ่งมีความยาวสูงสุด หากคุณออกแบบVARCHARคอลัมน์ให้ใหญ่กว่าขนาดสูงสุดที่คุณต้องการคุณจะใช้หน่วยความจำมากกว่าที่คุณต้องการ สิ่งนี้ส่งผลต่อประสิทธิภาพของแคชความเร็วในการจัดเรียง ฯลฯ


33
+1. ฉันยังดูเหมือนไดรเวอร์ JDBC บางตัวที่จัดสรรพื้นที่เพียงพอสำหรับขนาดสูงสุดเมื่อตั้งค่าบัฟเฟอร์เพื่อดึงข้อมูลแถว ไม่จำเป็นต้องพูดสิ่งนี้ทำให้เกิดความกังวลและกัดฟันอย่างมากเมื่อตัวตลกบางคนเพิ่งทำ varchar (50000) ในกรณีที่มีคนนามสกุลใหญ่จริงๆ :-)
paxdiablo

21
+1. นี่เป็นผลกระทบที่สำคัญและฉันเชื่อว่านี่คือคำตอบที่แท้จริงของคำถามนี้
Emre Yazici

6
คำตอบนี้และคำตอบที่ยอมรับมีความจำเป็นในการทำความเข้าใจคำตอบที่ถูกต้องสำหรับ OP
kd8azz

2
ในความเป็นจริงเมื่อMEMORYตารางดังกล่าวมีขนาดใหญ่เกินไปมันจะถูกเขียนลงในดิสก์ทำให้ประสิทธิภาพการทำงานลดลงอย่างมาก
Timo

1
คำตอบนี้สามารถทำได้ด้วยการระบุว่าเครื่องมือจัดเก็บข้อมูลใดเป็นจริง (ฉันทราบว่าdev.mysql.com/doc/refman/8.0/en/…ระบุว่าตารางชั่วคราวมักจะเป็น InnoDB เหมือน MySQL 8 สิ่งนั้นเปลี่ยนแปลงอะไรหรือไม่) และมีลิงก์ไปยังเอกสารที่สำรองข้อมูลการอ้างสิทธิ์ จากสิ่งที่ฉันได้เห็นจากผลลัพธ์ของคุณใน Stack Exchange ฉันเชื่อว่าคุณคิดถูกเมื่อคุณเขียนสิ่งนี้ แต่อาจมีการเปลี่ยนแปลงและลิงก์ทั้งสองจะเป็นตัวอย่างที่ดีสำหรับผู้อื่นและช่วยสอนพวกเราที่เหลือให้ค้นหา ข้อมูลประเภทนี้สำหรับตัวเราเอง
Mark Amery

14

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

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

สำหรับข้อมูลเพิ่มเติมในการเปรียบเทียบประเภทข้อมูล MySQL CHAR กับ VARCHAR โปรดดูที่ลิงค์นี้


1
ทุกคนที่สนใจในพื้นที่เก็บข้อมูล MySQL (เกี่ยวกับ CHAR และ VARCHAR) ควรอ่านลิงก์ที่กล่าวถึงในคำตอบนี้ ขอบคุณ!
Pascal

14

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

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

คุณต้องถามตัวเองว่าอาจเกิดการแทรกซึมกี่ครั้งต่อปี? ความยาวเฉลี่ยคืออะไร? ฉันต้องการอักขระมากกว่า 200 ตัวจริง ๆ หรือฉันสามารถจับได้ในส่วนหน้าของแอปพลิเคชันของฉันแม้จะแจ้งให้ผู้ใช้ทราบเกี่ยวกับความยาวสูงสุด ฉันสามารถแบ่งตารางออกเป็นตารางแคบ ๆ เพื่อการจัดทำดัชนีและการสแกนที่รวดเร็วและอีกตารางหนึ่งสำหรับเก็บข้อมูลเพิ่มเติมที่ไม่จำเป็นในการขยายขนาดได้หรือไม่ ฉันสามารถพิมพ์ข้อมูล varchar ที่เป็นไปได้เป็นหมวดหมู่และแยกข้อมูลบางส่วนออกเป็นคอลัมน์เล็ก ๆ น้อย ๆ อาจจะเป็น int หรือ bool-type และทำให้คอลัมน์ varchar แคบลงด้วยวิธีนี้ได้หรือไม่

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


+1 สำหรับรายการตัวเลือกการออกแบบและการสำรวจผลกระทบ มีประโยชน์มากสำหรับคำถามของฉันเช่นกัน stackoverflow.com/q/12083089/181638
Assad Ebrahim

5
มีผลกระทบด้านประสิทธิภาพจริงหรือไม่จากการตั้งค่าความยาวสูงสุดที่สูงหรือประสิทธิภาพถูกกำหนดโดยขนาดจริง?
poolie

5

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


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

1
อย่างที่บอกมันมีผลต่อประสิทธิภาพ นอกจากนี้ที่เก็บข้อมูลบนดิสก์ก็ไม่ฟรีเช่นกัน คอลัมน์ที่กว้างขึ้นหมายถึงการอ่าน / เขียนดิสก์มากขึ้น (และการเข้าถึงดิสก์คือ slooooooow) และดัชนีที่กว้างขึ้นซึ่งจะช่วยลดประโยชน์ ทั้งสองสิ่งส่งผลเสียต่อประสิทธิภาพการทำงาน อาจเป็นเรื่องเล็กน้อยในฐานข้อมูลขนาดเล็ก แต่ในระดับกิกะไบต์ / เทราไบต์นั้นจะมีความสำคัญอย่างที่คุณพูด สำหรับโต๊ะลงทะเบียน 100 โต๊ะก็ไม่สำคัญ
Alejandro

5

บางท่านเข้าใจผิดคิดว่าvarchar(200)ขนาดตารางบนดิสก์มากกว่าขนาดvarchar(20). กรณีนี้ไม่ได้. เฉพาะเมื่อคุณไปเกิน 255 ตัวอักษร mysql จะใช้ไบต์พิเศษเพื่อกำหนดความยาวของvarcharข้อมูลฟิลด์


9
ไม่ใช่สำหรับตารางชั่วคราวและMEMORYตาราง
Lightness Races ใน Orbit

4
ทุกครั้งที่แบบสอบถามที่คุณเลือกใช้ตารางชั่วคราว (จัดกลุ่มและเรียงลำดับตามการดำเนินการเหนือสิ่งอื่นใด) มันจะแปลง varchar (200) เป็นถ่าน (200) และประสิทธิภาพจะลดลง
Jamie

1

อาจมี Hit ด้านประสิทธิภาพ แต่โดยปกติจะไม่อยู่ในระดับที่ผู้ใช้ส่วนใหญ่สังเกตเห็น

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

varchar ส่งผลให้ประสิทธิภาพถูกโจมตีเนื่องจากการกระจายตัวของข้อมูลหรือไม่

ยิ่งไปกว่านั้นถ่าน VS varchar

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


0

การเป็น varchar แทนที่จะเป็นเพียง char ขนาดจะขึ้นอยู่กับช่องภายในเพื่อระบุความยาวจริงและสตริงเอง ดังนั้นการใช้ varchar (200) จึงไม่แตกต่างจากการใช้ varchar (150) มากนักยกเว้นว่าคุณมีศักยภาพในการจัดเก็บได้มากกว่า

และคุณควรพิจารณาว่าจะเกิดอะไรขึ้นกับการอัปเดตเมื่อแถวเติบโตขึ้น แต่ถ้ามันหายากคุณควรจะสบายดี


0

ตามชื่อประเภทข้อมูลแนะนำว่านี่คือ VARCHAR เช่นการจัดเก็บข้อมูลตัวอักษรตัวแปร mysql เอ็นจินเองจัดสรรหน่วยความจำที่ใช้ตามข้อมูลที่จัดเก็บดังนั้นจึงไม่มีการตีประสิทธิภาพตามความรู้ของฉัน


0

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

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

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

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

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

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

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

นอกจากนี้ควรพิจารณาชุดอักขระที่มีความยาวและประสิทธิภาพ ความยาวหมายถึงสิ่งนี้แทนที่จะเป็นไบต์ หากใช้ utf8 เช่น (ไม่ใช่ MB4) ดังนั้น varchar (255) จะเป็น varbinary (3 * 255) จริงๆ เป็นการยากที่จะทราบว่าสิ่งต่างๆเช่นนี้จะเกิดขึ้นจริงได้อย่างไรโดยไม่ต้องทำการทดสอบและดูรหัสต้นฉบับ / เอกสาร ด้วยเหตุนี้จึงมีขอบเขตสำหรับความยาวที่มากเกินไปที่จะส่งผลกระทบที่สูงเกินคาดโดยไม่คาดคิด สิ่งนี้ไม่ได้ใช้กับประสิทธิภาพเท่านั้น หากวันหนึ่งคุณจำเป็นต้องเปลี่ยนชุดอักขระของคอลัมน์ varchar ให้ใหญ่ขึ้นคุณอาจจบลงด้วยการกดขีด จำกัด บางอย่างโดยไม่มีการไล่เบี้ยหากคุณอนุญาตให้มีสตริงที่ยาวโดยไม่จำเป็นซึ่งสามารถหลีกเลี่ยงได้ นี่เป็นปัญหาเฉพาะที่ค่อนข้างเฉพาะ แต่มันก็เกิดขึ้น

หากปรากฎว่า MAX (LENGTH (คอลัมน์)) อยู่ที่ <64 เสมอ (เช่นหากมีการตัดสินใจว่าจะมีการ จำกัด อินพุตที่ไม่ตรงกับคำจำกัดความของคอลัมน์) แต่คุณมี varchar (255) แสดงว่ามี เป็นโอกาสดีที่คุณจะใช้พื้นที่มากกว่าที่จำเป็นถึงสี่เท่าในบางสถานการณ์

ซึ่งอาจรวมถึง:

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

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

เมื่อคุณทำไม่ได้หากคุณต้องการทำบางสิ่งเช่น varchar (255) สำหรับกรณีที่มีข้อสงสัยฉันขอแนะนำให้ทำตามหลักวิทยาศาสตร์ ซึ่งอาจประกอบด้วยการทำซ้ำตารางลดขนาดของคอลัมน์ var จากนั้นคัดลอกข้อมูลจากต้นฉบับและดูขนาดของข้อมูลดัชนี / แถว (จัดทำดัชนีคอลัมน์ด้วยและลองเป็นคีย์หลักด้วย อาจทำงานแตกต่างกันใน InnoDB เนื่องจากแถวเรียงลำดับตามคีย์หลัก) อย่างน้อยที่สุดวิธีนี้คุณจะรู้ว่าคุณมีผลกระทบต่อ IO ซึ่งมีแนวโน้มที่จะเป็นปัญหาคอขวดที่อ่อนไหวที่สุดอย่างหนึ่ง การทดสอบการใช้หน่วยความจำนั้นยากกว่าและยากที่จะทดสอบอย่างละเอียดถี่ถ้วน ฉันอยากจะแนะนำให้ทดสอบกรณีที่เลวร้ายที่สุดที่อาจเกิดขึ้น (การสืบค้นที่มีผลลัพธ์ระดับกลางจำนวนมากในหน่วยความจำตรวจสอบด้วยคำอธิบายสำหรับตารางอุณหภูมิขนาดใหญ่ ฯลฯ )

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

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