Bối cảnh
Khi lưu trữ một đoạn dữ liệu được tuần tự hóa (serialized) có độ dài không xác định trong cơ sở dữ liệu, nhiều người thiết kế trường đó dưới dạng VARCHAR(2000)
trong lược đồ bảng.
Nhưng nếu độ dài không xác định, tại sao không dùng kiểu dữ liệu TEXT
? Một số người nói: TEXT
làm giảm hiệu năng truy vấn.
Liệu điều đó có đúng không? Bài viết này sẽ phân tích vấn đề đó.
TEXT là gì?
TEXT là kiểu dữ liệu có độ dài biến đổi trong MySQL, bao gồm:
- TINYTEXT: 0 - 255 byte
- TEXT: 0 - 65.535 byte
- MEDIUMTEXT: 0 - 16.777.215 byte
- LONGTEXT: 0 - 4.294.967.295 byte
Chúng thường được sử dụng để lưu trữ lượng lớn dữ liệu văn bản.
Cách TEXT được lưu trữ
Mỗi giá trị kiểu BLOB
hoặc TEXT
được biểu diễn bên trong như một đối tượng được cấp phát riêng biệt, trong khi các kiểu dữ liệu khác được cấp phát vùng nhớ một lần cho mỗi cột khi bảng được mở.
Khi lưu trữ dữ liệu dạng chuỗi, InnoDB mã hóa các trường có độ dài cố định từ 768 byte trở lên thành các trường có độ dài biến đổi và lưu chúng vào trang tràn (overflow pages). Dữ liệu nhỏ hơn 768 byte sẽ được lưu trực tiếp trong dòng dữ liệu (data row).
👉 Vì vậy, khi sử dụng các kiểu chuỗi khác, nên tránh lưu dữ liệu từ 768 byte trở lên.
Giới hạn của TEXT
-
TEXT
không thể có giá trị mặc định (DEFAULT
). -
Khi đánh chỉ mục (
INDEX
) cho trườngTEXT
, phải chỉ định độ dài tiền tố (prefix length). -
Khi so sánh các giá trị chỉ mục, khoảng trắng ở cuối sẽ được tự động thêm vào. Điều này có thể gây lỗi khóa trùng lặp nếu sử dụng chỉ mục duy nhất.
-
Các trường
TEXT
có thể rất dài. Khi sắp xếp (sort), chỉ những byte đầu tiên trong giới hạnmax_sort_length
(mặc định là 1024) sẽ được dùng. Có thể thay đổi giá trị này như sau:
-- View max_sort_length
SELECT @@max_sort_length; -- Set max_sort_length
SET max_sort_length = 2048;
-
Khi xử lý với bảng tạm (temporary table), MySQL sẽ dùng bảng lưu trên đĩa thay vì bộ nhớ, vì bộ máy lưu trữ
MEMORY
không hỗ trợ kiểuTEXT
. -
Kích thước thực tế có thể truyền được của trường
TEXT
còn bị giới hạn bởi bộ đệm truyền thông (max_allowed_packet
). Có thể điều chỉnh như sau:
-- View max_allowed_packet
SELECT @@max_allowed_packet; -- Set max_allowed_packet
SET max_allowed_packet = 67108864;
Kết luận
Mặc dù TEXT
có thể dùng để lưu trữ lượng lớn dữ liệu văn bản, nhưng không nên sử dụng trong thiết kế bảng vì các lý do sau:
1. Vấn đề hiệu năng
TEXT
được biểu diễn dưới dạng đối tượng được cấp phát riêng, đòi hỏi thao tác và tài nguyên bổ sung khi lưu và truy xuất.- Nếu trường
TEXT
quá lớn, việc đọc nó sẽ làm tăng áp lực bộ nhớ, ảnh hưởng đến hiệu năng hệ thống. - Vì
TEXT
không được hỗ trợ bởi bộ máy MEMORY, nên khi dùng bảng tạm, dữ liệu phải đọc từ đĩa → chậm hơn.
2. Giới hạn về chỉ mục (index)
- Chỉ mục giúp cải thiện hiệu năng truy vấn, nhưng khi áp dụng cho
TEXT
, phải cẩn thận: - Chỉ mục duy nhất (
UNIQUE
) dễ bị lỗi trùng khóa do khoảng trắng ở cuối. - Chỉ mục toàn văn (
FULLTEXT
) cần nhiều tài nguyên và không gian để duy trì. Trường quá lớn có thể làm giảm hiệu năng truy vấn.
Gợi ý nếu buộc phải dùng TEXT:
- Tách các trường
TEXT
sang bảng riêng, liên kết với bảng chính bằng khóa chính (primary key). - Tránh đọc trường
TEXT
trừ khi cần thiết — ví dụ, không dùngSELECT *.
- Với dữ liệu lớn, hãy cân nhắc lưu trữ ngoài, ví dụ như OSS (Object Storage Service).