索引key长度限制Oracle、MySQL、PostgreSQL

近期在推进一个从 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 = DYNAMICCOMPRESSED
    • 最大索引长度可提升到 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.6InnoDB767 字节
5.7InnoDB767 字节默认
5.7 +innodb_large_prefix=ON+ROW_FORMAT=DYNAMICInnoDB3072 字节需手动配置
8.0InnoDB3072 字节默认支持
任意版本MyISAM1000 字节

处理超长文本字段的方案

前缀索引(如 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)

Leave a Comment