MySQL VARCHAR และ TEXT แตกต่างกันอย่างไร?


19

หลังจากเวอร์ชัน 5.0.3 (ซึ่งอนุญาตให้ VARCHAR เป็น 65,535 ไบต์และหยุดการตัดทอนช่องว่างต่อท้าย) มีความแตกต่างที่สำคัญระหว่างสองประเภทข้อมูลหรือไม่

ฉันกำลังอ่านรายการความแตกต่างและโน้ตสองข้อเท่านั้นคือ:

สำหรับดัชนีในคอลัมน์ BLOB และ TEXT คุณต้องระบุความยาวส่วนนำหน้าดัชนี สำหรับ CHAR และ VARCHAR ความยาวของคำนำหน้าเป็นทางเลือก ดูหัวข้อ 7.5.1“ ดัชนีคอลัมน์”

และ

คอลัมน์ BLOB และ TEXT ไม่สามารถมีค่าเริ่มต้นได้

ดังนั้นเนื่องจากข้อ จำกัด สองข้อนี้ในประเภทข้อมูล TEXT ทำไมคุณถึงใช้มากกว่า varchar (65535) มีผลการดำเนินงานที่แตกต่างกันอย่างใดอย่างหนึ่ง?


1
เมื่อคุณต้องการข้อมูลมากกว่า 65535 ตัวอักษร?
BlackICE

นี่เป็นฟอรัมที่ดีมากเกี่ยวกับการเปรียบเทียบระหว่าง varchar และข้อความ: http://forums.mysql.com/read.php?24,105964,105964
แบ่ง

เนื่องจากรายการมีการทำงานที่ดีในการจัดทำรายละเอียดที่ชัดเจนและเนื่องจากคุณมีรายการความแตกต่างที่แจกแจงอยู่แล้วฉันไม่แน่ใจว่านี่เป็นคำถามที่เราต้องการใน DBA มีเหตุผลที่รายการที่คุณอ้างถึงและเหตุผลที่คุณให้มาไม่ดีพอในกรณีนี้หรือไม่? มิฉะนั้นฉันจะไป VtC
jcolebrand

1
ฉันอัปเดตคำถามของฉันแล้ว แต่มีหนึ่งเหตุผลที่ชัดเจนที่ฉันไม่แน่ใจว่าเป็นเพราะประสิทธิภาพการทำงานของอีกด้านหนึ่ง ไม่แน่ใจว่ามีเหตุผลที่ไม่ชัดเจนอื่น ๆ หรือไม่
Derek Downey

ดังนั้นมันยุติธรรมที่สิ่งที่คุณถามคือลักษณะการทำงานของอีกคนหนึ่ง?
jcolebrand

คำตอบ:


13

แบ่งการเชื่อมโยงกับข้อมูลบางอย่างที่อธิบายถึงปัญหาพื้นฐาน (มีความแตกต่างด้านประสิทธิภาพ) แต่ก็ไม่ง่ายพอที่จะบอกว่าข้อมูลนั้นดีกว่าข้อมูลอื่นเสมอ (ไม่เช่นนั้นจะไม่มีเหตุผลที่จะมีทั้งคู่) นอกจากนี้ใน MyISM ขนาดสูงสุด 64k สำหรับ VARCHAR ไม่ใช่สำหรับแต่ละฟิลด์ - เป็นต่อเรคคอร์ด

โดยทั่วไปมี 4 วิธีในการจัดเก็บสตริงในบันทึกฐานข้อมูล:

  1. ความยาวคงที่
  2. สตริง C-style (ทำเครื่องหมายด้วย NULL หรืออักขระที่คล้ายกันที่ท้ายสตริง)
  3. สตริงสไตล์ Pascal (สองสามไบต์เพื่อระบุความยาวจากนั้นสตริง)
  4. พอยน์เตอร์ (เก็บสตริงที่อื่น)

MyISM ใช้บางอย่างที่คล้ายกับ # 3 สำหรับ VARCHAR และวิธีไฮบริดสำหรับ TEXT ที่เก็บจุดเริ่มต้นของสตริงในเรกคอร์ดจากนั้นพักสตริงที่อื่น InnoDB นั้นคล้ายคลึงกับ VARCHAR แต่จะเก็บฟิลด์ TEXT ทั้งหมดไว้นอกระเบียน

ด้วย 1 & 4 เนื้อหาในระเบียนจะมีความยาวเท่ากันเสมอดังนั้นจึงง่ายกว่าถ้าคุณไม่ต้องการสตริง แต่ต้องการสิ่งต่าง ๆ หลังจากนั้น ทั้ง # 2 และ # 3 ไม่เลวร้ายนักสำหรับสตริงสั้น ๆ ... # 2 ต้องมองหาเครื่องหมายในขณะที่ # 3 สามารถข้ามไปได้ ... ขณะที่สตริงยาวขึ้น # 2 แย่ลงสำหรับการใช้งานนี้โดยเฉพาะ กรณี.

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

จากนั้นมีข้อกำหนดด้านพื้นที่จัดเก็บ ... # 1 เป็นความยาวคงที่เสมอดังนั้นจึงอาจมีการขยายตัวหากสตริงส่วนใหญ่ไม่ใช่ความยาวสูงสุด # 2 มี 1 ไบต์พิเศษ # 3 โดยทั่วไปมี 2 ไบต์พิเศษหากความยาวสูงสุด = 255, 4 ไบต์พิเศษหากสูงสุด 64k # 4 มีความยาวตัวชี้รวมถึงกฎสำหรับ # 3 โดยทั่วไป

สำหรับการใช้งานเฉพาะภายใน MySQL 5.1, docs สำหรับ MyISM state :

  • สนับสนุน VARCHAR ชนิดที่แท้จริง; คอลัมน์ VARCHAR เริ่มต้นด้วยความยาวที่เก็บในหนึ่งหรือสองไบต์
  • ตารางที่มีคอลัมน์ VARCHAR อาจมีความยาวคงที่หรือไดนามิกแถว
  • ผลรวมของความยาวของคอลัมน์ VARCHAR และ CHAR ในตารางอาจสูงถึง 64KB

ในขณะที่สำหรับ InnoDB :

  • ส่วนความยาวผันแปรของส่วนหัวของบันทึกประกอบด้วยบิตเวกเตอร์สำหรับการระบุคอลัมน์ NULL หากจำนวนคอลัมน์ในดัชนีที่สามารถเป็น NULL คือ N บิตเวคเตอร์จะใช้พื้นที่ของ CEILING (N / 8) (ตัวอย่างเช่นหากมีที่ใดก็ได้จาก 9 ถึง 15 คอลัมน์ที่สามารถเป็น NULL ได้บิตเวกเตอร์ใช้สองไบต์) คอลัมน์ที่เป็น NULL จะไม่ใช้พื้นที่อื่นนอกเหนือจากบิตในเวกเตอร์นี้ ส่วนความยาวผันแปรของส่วนหัวยังมีความยาวของคอลัมน์ความยาวตัวแปร แต่ละความยาวใช้เวลาหนึ่งหรือสองไบต์ขึ้นอยู่กับความยาวสูงสุดของคอลัมน์ ถ้าคอลัมน์ทั้งหมดในดัชนีไม่เป็นโมฆะและมีความยาวคงที่ส่วนหัวของบันทึกจะไม่มีส่วนที่มีความยาวผันแปรได้
  • สำหรับแต่ละฟิลด์ที่มีความยาวตัวแปรที่ไม่ใช่ NULL ส่วนหัวของเรกคอร์ดจะมีความยาวของคอลัมน์ในหนึ่งหรือสองไบต์ สองไบต์จะต้องใช้เฉพาะในกรณีที่ส่วนหนึ่งของคอลัมน์ถูกเก็บไว้ภายนอกในหน้าล้นหรือความยาวสูงสุดเกิน 255 ไบต์และความยาวจริงเกิน 127 ไบต์ สำหรับคอลัมน์ที่จัดเก็บภายนอกความยาวสองไบต์ระบุความยาวของส่วนที่จัดเก็บภายในรวมทั้งตัวชี้ 20 ไบต์ไปยังส่วนที่จัดเก็บภายนอก ส่วนภายในเป็น 768 ไบต์ดังนั้นความยาวคือ 768 + 20 ตัวชี้ขนาด 20 ไบต์จะเก็บความยาวที่แท้จริงของคอลัมน์

...

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


กระทู้แบ่งการเชื่อมโยงระบุว่า MySQL เก็บ blobs และฟิลด์ข้อความ inline Forums.mysql.com/read.php?24,105964,267596#msg-267596
Michael Mior

1
Nitpick ... สำหรับวัตถุประสงค์ในทางปฏิบัติทั้งหมดไม่มีการ จำกัด 64KB ต่อแถวในแต่ละเครื่องยนต์ LONGTEXTและLONGBLOBเป็นกรณีในจุด สตริง C-style ไม่มีการใช้งานโดย MySQL (ที่ฉันรู้) InnoDB ใช้วิธี 'ไฮบริด' แต่มีความซับซ้อนมากขึ้นทั้งนี้ขึ้นอยู่กับขนาดของแถว row_format ฯลฯ การจัดเก็บสตริงในความยาว "คงที่" นั้นแทบจะไม่แนะนำเลยเว้นแต่จะเป็นความยาวคงที่จริง ๆ (country_code, zip_code เป็นต้น) . InnoDB มี 4 ROW_FORMATs; ข้อความกล่าวถึงเพียง 1 หรือ 2 ของพวกเขา
Rick James

2

เมื่อ SELECT ต้องการสร้างตารางชั่วคราว (เช่นเรียงลำดับผลลัพธ์) มันจะสร้างตาราง MEMORY หรือตาราง MyISAM MEMORY มีประสิทธิภาพมากกว่า มีข้อ จำกัด เกี่ยวกับ MEMORY - ข้อหนึ่งคือไม่อนุญาต TEXT และ BLOB ดังนั้นการเลือกอาจทำงานช้าลงด้วย TEXT กว่า VARCHAR

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