mysql禁止对blob/text字段建普通索引是因全量索引会导致b+树失衡、性能崩塌;有效前缀索引需基于字节长度(utf8mb4下中文占4字节)、选择性≥0.95且经explain验证,而like '%xxx'时前缀索引完全失效,大体积数据应外置存储或压缩。

为什么直接对BLOB/TEXT建索引会报错 ERROR 1170
MySQL 明确禁止对未指定长度的 BLOB 或 TEXT 字段创建普通索引,执行 CREATE INDEX idx ON tbl(content) 时必然触发 ERROR 1170 (42000): BLOB/TEXT column 'content' used in key specification without a key length。这不是配置问题,而是引擎层硬性限制:这类字段可能极大,全量索引会导致 B+ 树结构失衡、写入性能崩塌、磁盘空间爆炸。
前缀索引怎么设才真正有效(不是摆设)
前缀索引只对 WHERE content LIKE 'xxx%' 和 WHERE content = 'exact_value' 有效,且效果完全取决于你选的字节数——不是字符数,是字节。UTF8MB4 下一个中文占 4 字节,content(100) 最多覆盖 25 个汉字。
- 先看数据分布:
SELECT LEFT(content, 200) AS p, COUNT(*) FROM tbl GROUP BY p ORDER BY COUNT(*) DESC LIMIT 5,确认开头是否大量重复(比如全是{"id":或/code>) - 算选择性:
SELECT COUNT(DISTINCT LEFT(content, 80)) / COUNT(*) AS sel FROM tbl,目标值 ≥ 0.95;再试 60、100,找到选择性提升明显放缓的拐点 - 最终长度建议比拐点值多留 10–20 字节缓冲,例如
sel_80 = 0.92、sel_100 = 0.94,就用content(120) -
EXPLAIN必须验证:key列显示索引名,且rows显著下降;如果Extra还有Using filesort或Using where,说明没走覆盖,得拆查询
LIKE '%xxx' 或中间匹配时,前缀索引完全失效
只要 LIKE 模式以 % 开头(如 '%error' 或 '%500%'),B-tree 索引(包括前缀索引)彻底不可用,MySQL 只能全表扫描。此时加索引不仅无效,还徒增写入开销和磁盘占用。
- 若需搜索内容中任意位置的关键词,优先提取关键字段:比如日志里固定有
error_code:,就用生成列ADD COLUMN error_code VARCHAR(10) AS (SUBSTRING_INDEX(SUBSTRING_INDEX(content, 'error_code:', -1), '\n', 1)) STORED,再对error_code建索引 - 全文检索场景改用
FULLTEXT(content)+MATCH() AGAINST(),但注意ft_min_word_len默认为 4,短词搜不到 - 精确等值匹配需求(如判断某段文本是否已存在),用哈希生成列:
ADD COLUMN content_sha CHAR(64) AS (SHA2(content, 256)) STORED,再建INDEX idx_sha ON tbl(content_sha),查询写成WHERE content_sha = SHA2('target', 256) AND content = 'target'
什么时候该放弃索引,直接换存储方式
索引只是缓解手段,不是万能解药。当 BLOB 存的是图片、PDF、视频,或 TEXT 平均长度超 1MB,索引已无意义——IO 和内存开销远大于索引收益。
- 超过 1MB 的二进制文件,一律外置:表中只存
file_path VARCHAR(512),文件落地 OSS/S3/本地目录,Web 层直读流 - 纯文本但体积大(如 HTML、JSON 日志),优先用
MEDIUMTEXT替代MEDIUMBLOB,支持字符集校验、前缀索引、ORDER BY - 必须事务内写入的审计日志类场景,入库前压缩:
INSERT INTO log(msg) VALUES (COMPRESS('raw')),字段类型改用MEDIUMBLOB(COMPRESS()输出略大于原文),读取时用UNCOMPRESS()或应用层解压
真正容易被忽略的点是:前缀索引不解决 SELECT 大字段本身的 IO 压力。哪怕索引命中,SELECT content 仍会把整段数据从溢出页加载进 Buffer Pool。所以“查得快”不等于“返回快”,字段拆分和查询瘦身永远比调索引参数更治本。











