近期在推进一个从 Oracle 迁移至 PostgreSQL 的项目时,我们遇到部分在 Oracle 中运行正常的索引无法在 PostgreSQL 中创建,系统报错:ERROR: index row size X exceeds maximum Y for index "index_name"。
经分析,这源于不同数据库对索引键(Index Key)长度的上限设计存在差异。为规避此类问题并助力迁移规划,我们特此整理了 Oracle, MySQL, PostgreSQL 三大主流数据库的索引键长度限制。
oracle

Note: oracle index key的最大长度btree 是block size 的80%, 如果rebuild online还是IOT 表的block size限制 40%, 如block size是8192bytes, 那可用不能超过80% 6398bytes, 达到上限后报错ORA-01450.
MySQL
mysql索引键的最大长度在InnoDB 是3072. MySQL 5.6以前是767 。
MySQL 5.7 启用 innodb_large_prefix(默认 OFF):
- 如果设置
innodb_large_prefix = ON+ROW_FORMAT = DYNAMIC或COMPRESSED:- 最大索引长度可提升到 3072 字节
MySQL 8.0:
- 默认启用大索引支持(large prefix)
- 单列/组合索引最大长度:3072 字节
- 行格式默认为
DYNAMIC - 无需手动设置
innodb_large_prefix
-- 查看 innodb_large_prefix(5.7 中重要)
SHOW VARIABLES LIKE 'innodb_large_prefix';
-- 查看默认行格式
SHOW VARIABLES LIKE 'innodb_default_row_format';
-- 查看 MySQL 版本
SELECT VERSION();
| MySQL 版本 | 存储引擎 | 默认最大索引长度 | 条件 |
| ≤ 5.6 | InnoDB | 767 字节 | 无 |
| 5.7 | InnoDB | 767 字节 | 默认 |
5.7 +innodb_large_prefix=ON+ROW_FORMAT=DYNAMIC | InnoDB | 3072 字节 | 需手动配置 |
| 8.0 | InnoDB | 3072 字节 | 默认支持 |
| 任意版本 | MyISAM | 1000 字节 | 无 |
处理超长文本字段的方案
前缀索引(如 INDEX(column(100)))或 哈希索引(应用层生成 hash 存储)
PostgreSQL
在 PostgreSQL 中,索引(Index)的最大长度 与 MySQL 不同,其限制机制也更加宽松和清晰,和oracle类似,但比oracle要小。PostgreSQL 的页大小(BLCKSZ)默认是 8192 字节(8KB),而索引项不能超过页大小的 1/3,即 8192 / 3 ≈ 2730,实际可用为 2712 字节(预留部分头部开销)。
超过此限制时,插入或更新会报错:
ERROR: index row size exceeds maximum for index "xxx"
HINT: Values larger than 1/3 of a buffer page cannot be indexed.
或
index row size xxx exceeds btree version 4 maximum 2704 for index.
而在highgo瀚高数据库中提示错误是
错误: 索引行大小 xxx 超过了索引 "xxx"的 btree 版本4的最大值2704.
-- 查看当前页面大小
SELECT current_setting('block_size');
处理超长文本字段的方案
| 表达式索引(前缀)、哈希字段、全文检索(GIN) |