TEXT 和 BLOB 类型的使用注意事项
什么是 TEXT 和 BLOB
MySQL 中,TEXT 和 BLOB 是用于存储大量数据的字段类型。TEXT 系列用于存储字符串(字符数据),BLOB 系列用于存储二进制数据(图片、文件等)。它们各自有四个子类型,区别在于存储容量:
| 类型 | 最大长度 |
|---|---|
| TINYTEXT / TINYBLOB | 255 字节 |
| TEXT / BLOB | 65,535 字节(64KB) |
| MEDIUMTEXT / MEDIUMBLOB | 16,777,215 字节(16MB) |
| LONGTEXT / LONGBLOB | 4,294,967,295 字节(4GB) |
TEXT 以字符为单位,受字符集影响;BLOB 以字节为单位,与字符集无关。
使用注意事项
1. 行溢出存储
InnoDB 中,TEXT/BLOB 字段通常存储在行外。当记录较大时,InnoDB 会在聚簇索引中保留一个 768 字节的前缀指针,实际数据存储在单独的溢出页中。这意味着:
- SELECT 不查该字段时性能很好——不会读取溢出页
- 一旦 SELECT 中包含该字段,即使只取一行,也要多一次 IO 读溢出页
- 对于大字段频繁查询的场景,应考虑拆分到单独的表
2. 排序和索引限制
- TEXT/BLOB 字段不能作为主键
- 创建索引时必须指定前缀长度,比如
INDEX(column(100)),不能对全字段建索引 ORDER BY TEXT_COLUMN排序时,只使用max_sort_length指定的前缀长度(默认 1024 字节),超出部分被截断- 使用
DISTINCT或GROUP BY时也会受此限制
3. 临时表与磁盘
- 当查询需要对 TEXT/BLOB 字段排序或分组时,由于内存中的临时表无法容纳可变长度大字段,MySQL 会直接在磁盘上创建临时表
- 这极大降低了性能,应避免对大字段进行排序或分组
4. 内存占用
- 即使只查询 TEXT/BLOB 列的一小部分,MySQL 也可能读取整个值(取决于存储引擎和 buffer 大小)
- 频繁访问大字段会增加 buffer pool 压力,挤占其他热数据的缓存空间
5. 字符集导致的容量差异
TEXT 类型的”最大字符数”定义在字符为单字节(如 latin1)时等于字节数,但如果是 UTF-8(utf8mb4),一个字符最多占 4 字节,实际能存的字符数就少了。设计表结构时要留意这一点。
6. 默认值限制
- BLOB 和 TEXT 字段不能有默认值(MySQL 8.0.13 之前)
- MySQL 8.0.13+ 允许为 TEXT/BLOB 设置默认值,但仅限表达式默认值
7. 避免使用 BLOB 存文件
- 将大文件直接存 BLOB 会导致表体积膨胀、备份变慢、主从延迟增加
- 建议只在数据库中存文件路径或对象存储的 URL,文件本身存文件系统或 OSS
8. 行格式影响
- COMPACT 和 REDUNDANT 行格式:TEXT/BLOB 的前 768 字节存行内,剩余存溢出页
- DYNAMIC 行格式(默认):根据长度决定是否完全行外存储
- COMPRESSED 行格式:对溢出页进行压缩,节省空间但增加 CPU 开销
最佳实践
- 能不用就不用:能用 VARCHAR 解决的不要升级到 TEXT
- 放到单独表:如果业务上确实需要大字段,考虑垂直拆分到单独的扩展表
- 避免排序和分组:不要对 TEXT/BLOB 字段 ORDER BY 或 GROUP BY
- 只查询需要的字段:不要写
SELECT *,明确指定需要的列名 - 监控溢出页 IO:通过
SHOW ENGINE INNODB STATUS观察溢出页的读写情况 - 选择合适的子类型:够用即可,TEXT 够用就选 TEXT,别一上来就 LONGTEXT
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END


暂无评论内容