error 1170是innodb引擎强制限制,text/blob列建索引必须指定前缀长度(如content(255)),且受字符集字节影响;前缀索引仅支持left like和等值查询,%开头模糊搜索无效;全文检索应使用fulltext或外置es。

ERROR 1170 是硬性限制,不是配置能绕过的
执行 CREATE INDEX idx ON t (content) 时直接报 ERROR 1170 (42000): BLOB/TEXT column 'content' used in key specification without a key length,这不是 MySQL 配置没开、也不是权限问题,而是 InnoDB 引擎层的强制约束。根本原因是 TEXT 类型数据不存于主记录页内,只留 20 字节指针指向溢出页;索引结构要求键值能被完整加载进内存页(默认 16KB),而 TEXT 值长度不可控,全量索引会导致 B+ 树节点大小失控、写入性能崩塌、磁盘空间爆炸。
前缀长度单位是字符数,但实际按字节算存储开销
对 TEXT 列建索引必须写成 INDEX(content(255)) 这种形式,其中 255 是字符数(不是字节)。但在 utf8mb4 字符集下,一个中文字符占 4 字节,所以 content(255) 实际可能占用 1020 字节——这已经接近 InnoDB 默认单列索引长度上限(767 字节)。如果启用了 innodb_large_prefix,上限可升至 3072 字节,否则容易触发 Specified key was too long 错误。
- 查当前表字符集:
SHOW CREATE TABLE t,确认CHARSET和COLLATE - 估算实际字节数:中文为主就按 ×4,英文混合按 ×2~3 粗估
- 联合索引中含 TEXT 前缀列,该列必须放在最后,否则部分版本会建索引失败或查询效率受损
前缀索引只对 LEFT LIKE 和等值匹配有效
WHERE content LIKE 'error%' 或 WHERE content = 'exact string' 能走前缀索引;但只要出现 % 开头,比如 LIKE '%500%'、LIKE '%timeout',索引完全失效,MySQL 只能全表扫描。这时候加索引不仅没用,还拖慢 INSERT/UPDATE、浪费磁盘空间。
- 用
EXPLAIN验证:key 列显示索引名,且rows显著下降才算生效 - 如果
Extra出现Using filesort或Using where,说明没走覆盖,可能得拆查询逻辑 - 区分度低的前缀(如日志字段前 20 字全是
{"level":"error")会让索引变成“假索引”,查出来一堆行再回表比对,IO 反而更高
真正需要模糊搜索或排序,别硬扛 TEXT + 前缀索引
如果你的业务要支持 WHERE content LIKE '%keyword%'、ORDER BY content 或精确去重,前缀索引从设计上就不满足。它既不能保证排序完整性,也无法支撑中间匹配。这时该考虑的是结构重构:
- 把长文本内容迁出主表,用关联表或冷表存储,主表只留摘要字段(如哈希、标题、分类标签)
- 改用
VARCHAR(16383)替代 TEXT(在 InnoDB 行长度允许范围内),再建完整索引 - 全文检索场景优先用
FULLTEXT索引,但注意它不支持=查询,也不能替代 B+ 树做范围或排序 - 高并发模糊搜索建议外置到 Elasticsearch 或专用检索服务,避免拖垮 OLTP 主库
前缀长度选不准、字符集算错字节、WHERE 条件没对齐最左前缀——这三个点最容易让索引形同虚设。别只看 CREATE INDEX 成功了就以为搞定了。











