MySQL - varchar ความยาวและประสิทธิภาพ


19

VARCHARขนาดที่ประกาศออกมาเหมาะสมกับประสิทธิภาพหรือไม่? มีความแตกต่าง (ความเร็ว) ระหว่างVARCHAR(50)และVARCHAR(255)? หรือการกำหนดความยาวคือข้อ จำกัด ด้านตรรกะ / การออกแบบ?


คำตอบ:


31

นี่เป็นคำถามที่พบบ่อยมาก "ข้อสอบ / สัมภาษณ์" ฉันจะตอบให้ดีที่สุด:

ในรูปแบบแถวมาตรฐานสำหรับ InnoDB และ MyISAM (ไดนามิก / กะทัดรัด) a VARCHAR(50)และ a VARCHAR(255)จะเก็บข้อความสตริงในแบบเดียวกับ 1 ไบต์สำหรับความยาวและสตริงจริงที่มีระหว่าง 1 ถึง 4 ไบต์ต่ออักขระ (ขึ้นอยู่กับการเข้ารหัสและ อักขระจริงถูกเก็บไว้)

ในความเป็นจริงถ้าฉันจำได้อย่างถูกต้องฉันจำได้ว่ามีคนกำลังแก้ไขพจนานุกรมข้อมูลด้วยตัวแก้ไขเลขฐานสิบหกเพื่อเปลี่ยนสิ่งที่คล้ายกันเป็นVARCHAR(50)a VARCHAR(100)ดังนั้นจึงสามารถทำได้แบบไดนามิก (ปกติแล้วต้องมีการสร้างตารางใหม่) และนั่นก็เป็นไปได้เพราะข้อมูลจริงไม่ได้รับผลกระทบจากการเปลี่ยนแปลงนั้น

ไม่เป็นความจริงVARCHAR(256)เพราะต้องมีความยาว 2 ไบต์ (อย่างน้อย)

ดังนั้นวิธีการที่เราควรทำVARCHAR(255)ไม่ควรเรา? เลขที่มีสาเหตุหลายประการ

ในขณะที่ InnoDB อาจเก็บ varchar ในลักษณะที่เปลี่ยนแปลงซึ่งไม่เป็นความจริงสำหรับเอ็นจิ้นอื่น ๆ MyISAM มีรูปแบบขนาดแถวคงที่และตาราง MEMORY ถูกกำหนดขนาดเสมอ เราควรสนใจเครื่องยนต์อื่น ๆ เหล่านั้นหรือไม่ ใช่เราควรเพราะแม้ว่าเราจะไม่ได้ใช้งานโดยตรงตาราง MEMORY มักใช้สำหรับผลลัพธ์ระดับกลาง (ตารางชั่วคราวในหน่วยความจำ)และเนื่องจากไม่ทราบผลลัพธ์ล่วงหน้าตารางจึงต้องถูกสร้างขึ้นด้วยขนาดสูงสุด เป็นไปได้ - VARCHAR(255)ถ้าเป็นประเภทของเรา หากคุณคิดเกี่ยวกับพื้นที่ที่สูญเปล่าหากเราใช้การ'utf8' charsetเข้ารหัสของ MySQL MEMORY จะจอง 2 ไบต์สำหรับความยาว + 3 * 255 ไบต์ต่อแถว(สำหรับค่าที่อาจใช้เวลาเพียงไม่กี่ไบต์บน InnoDB) นั่นคือเกือบ 1GB ต่อ 1 ล้านตาราง - สำหรับ VARCHAR เท่านั้น ไม่เพียงแค่นี้ทำให้เกิดปัญหาหน่วยความจำที่ไม่จำเป็นมันอาจกระตุ้นการกระทำที่จะดำเนินการบนดิสก์อาจทำให้ช้าลงหลายพันครั้ง ทั้งหมดนี้เป็นเพราะการเลือกที่ไม่ดีของประเภทข้อมูลที่กำหนดไว้ (เป็นอิสระจากเนื้อหา)

มันมีผลบางอย่างกับ InnoDB เช่นกัน ขนาดดัชนีถูก จำกัด ไว้ที่ 3072 ไบต์และดัชนีคอลัมน์เดียวถึง 767 ไบต์ * ดังนั้นจึงมีความเป็นไปได้สูงมากที่คุณจะไม่สามารถสร้างดัชนีVARCHAR(255)ฟิลด์ได้อย่างสมบูรณ์ (สมมติว่าคุณใช้ utf8 หรือการเข้ารหัสความยาวตัวแปรอื่น ๆ )

นอกจากนี้สูงสุดแบบอินไลน์ขนาดแถว InnoDB เป็นครึ่งหน้า (ประมาณ 8000 ไบต์) และสาขาตัวแปรยาวเหมือนหยดหรือ varchar สามารถเก็บไว้ปิดหน้าถ้าพวกเขาไม่พอดีกับช่วงครึ่งปีหน้า ที่มีผลต่อประสิทธิภาพ (บางครั้งดีบางครั้งไม่ดีขึ้นอยู่กับการใช้งาน) ที่ไม่สามารถเพิกเฉยได้ สิ่งนี้ทำให้เกิดความแปลกประหลาดบางอย่างระหว่างรูปแบบ COMPACT และ DYNAMIC ดูตัวอย่าง: error 1118: ขนาดแถวใหญ่เกินไป utf8 innodb

สุดท้าย แต่ไม่ท้ายสุดตามที่ @ypercube เตือนฉันฉันอาจต้องใช้ความยาวมากกว่า 1 ไบต์แม้ว่าคุณจะใช้VARCHAR(255)เพราะคำจำกัดความเป็นตัวอักษรในขณะที่ความยาวจะจัดเก็บไบต์ ตัวอย่างเช่นREPEAT('ñ', 255)มีมากกว่า 2 ^ 255 ไบต์ใน utf8 ดังนั้นมันต้องใช้มากกว่า 1 ไบต์สำหรับการจัดเก็บความยาว:

mysql> SELECT LENGTH(REPEAT('ñ', 255));
+---------------------------+
| LENGTH(REPEAT('ñ', 255))  |
+---------------------------+
|                       510 |
+---------------------------+
1 row in set (0.02 sec)

mysql> SELECT CHAR_LENGTH(REPEAT('ñ', 255));
+--------------------------------+
| CHAR_LENGTH(REPEAT('ñ', 255))  |
+--------------------------------+
|                            255 |
+--------------------------------+
1 row in set (0.00 sec)

ดังนั้นคำแนะนำทั่วไปคือใช้ชนิดที่เล็กที่สุดเท่าที่จะเป็นไปได้เพราะอาจทำให้เกิดปัญหาด้านประสิทธิภาพหรือการจัดการเป็นอย่างอื่น A VARCHAR(100)ดีกว่าVARCHAR(255)(แม้ว่า a VARCHAR(20)จะดีกว่า) แม้ว่าคุณจะไม่ทราบความยาวที่แน่นอน พยายามที่จะอนุรักษ์เพราะถ้าตารางมีขนาดใหญ่เกินไปคุณสามารถเปลี่ยนคำนิยามได้ในภายหลัง

อัปเดต:เนื่องจากความนิยมในการขยายตัวของสตริงที่มีความยาวผันแปรตัวอย่างเช่นด้วยการใช้ emojis ทำให้ Oracle ได้รับการผลักดันเพื่อปรับปรุงประสิทธิภาพสำหรับกรณีเหล่านั้น ในรุ่น MySQL ล่าสุด (5.6, 5.7) InnoDB ได้รับการตั้งค่าให้เป็นเครื่องมือเริ่มต้นสำหรับทั้งตารางชั่วคราวที่แท้จริงและชัดเจนซึ่งหมายความว่าเขตข้อมูลที่มีความยาวผันแปรได้กลายเป็นพลเมืองชั้นหนึ่งแล้ว นั่นหมายความว่าอาจมีเหตุผลน้อยกว่าที่จะมีความยาวอักขระที่ จำกัด มาก (แต่ยังมีอยู่)

(*) การอัปเดตครั้งที่สอง : large_prefix_index เปิดใช้งานโดยค่าเริ่มต้นในเวอร์ชัน MySQL ล่าสุด (8.0) แต่ยังคงเป็นจริงสำหรับเวอร์ชันเก่าหรือหากคุณใช้รูปแบบไฟล์ / แถว lagacy innodb (นอกเหนือจากไดนามิกหรือบีบอัด) แต่ตอนนี้ โดยค่าเริ่มต้นดัชนีคอลัมน์เดียวสามารถมีขนาดได้ถึง 3072 ไบต์


การอัพเดทเล็กน้อย: MySQL-8.0.13 + ใช้TempTableตามค่าเริ่มต้นสำหรับตาราง temp ที่มีการจัดเก็บที่มีประสิทธิภาพสำหรับ varchars
danblack

0

ลืมเกี่ยวกับคำนำหน้า 1- เมื่อเทียบกับ 2 VARCHARsไบต์บน

  • มันส่งผลกระทบต่อประสิทธิภาพการทำงานโดยจำนวนจิ๋ว
  • มันเป็น "2" บ่อยกว่ากฎที่ชัดเจนว่า

คำถามเกี่ยวกับ 255 ถูกถามและตอบหลายครั้ง

  • หลายนานเกินไปจะนำไปสู่ความล้มเหลวของVARCHARsCREATE TABLE
  • ตารางชั่วคราวอาจจะเปลี่ยนเป็นMEMORYตารางที่มีกลายเป็นVARCHARs VARCHARตัวอย่างเช่นนี่หมายความว่าVARCHAR(255) CHARACTER SET utf8mb4ต้องการความยาวคงที่เท่ากับ 1,020 ไบต์ (สิ่งนี้จะล้มเหลวและมันจะเสื่อมสภาพในการใช้ MyISAM)

บรรทัดล่าง: อย่าใช้ 255 (หรือ 256) สุ่มสี่สุ่มห้า ทำสิ่งที่สมเหตุสมผลสำหรับสคีมา

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