VARCHAR
ขนาดที่ประกาศออกมาเหมาะสมกับประสิทธิภาพหรือไม่? มีความแตกต่าง (ความเร็ว) ระหว่างVARCHAR(50)
และVARCHAR(255)
? หรือการกำหนดความยาวคือข้อ จำกัด ด้านตรรกะ / การออกแบบ?
VARCHAR
ขนาดที่ประกาศออกมาเหมาะสมกับประสิทธิภาพหรือไม่? มีความแตกต่าง (ความเร็ว) ระหว่างVARCHAR(50)
และVARCHAR(255)
? หรือการกำหนดความยาวคือข้อ จำกัด ด้านตรรกะ / การออกแบบ?
คำตอบ:
นี่เป็นคำถามที่พบบ่อยมาก "ข้อสอบ / สัมภาษณ์" ฉันจะตอบให้ดีที่สุด:
ในรูปแบบแถวมาตรฐานสำหรับ 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 ไบต์
ลืมเกี่ยวกับคำนำหน้า 1- เมื่อเทียบกับ 2 VARCHARs
ไบต์บน
คำถามเกี่ยวกับ 255 ถูกถามและตอบหลายครั้ง
VARCHARs
CREATE TABLE
MEMORY
ตารางที่มีกลายเป็นVARCHARs
VARCHAR
ตัวอย่างเช่นนี่หมายความว่าVARCHAR(255) CHARACTER SET utf8mb4
ต้องการความยาวคงที่เท่ากับ 1,020 ไบต์ (สิ่งนี้จะล้มเหลวและมันจะเสื่อมสภาพในการใช้ MyISAM)บรรทัดล่าง: อย่าใช้ 255 (หรือ 256) สุ่มสี่สุ่มห้า ทำสิ่งที่สมเหตุสมผลสำหรับสคีมา