我们一再看到尝试索引值超过最大大小的列失败。Postgres 10 有这样的错误信息:
ERROR: index row size xxxx exceeds maximum 2712 for index "foo_idx" HINT: Values larger than 1/3 of a buffer page cannot be indexed. Consider a function index of an MD5 hash of the value, or use full text indexing.
例子:
等等。
现在,a_horse_with_no_name 演示了一个具有更大text
值(10000 个字符)的案例,它似乎仍然适用UNIQUE
于 Postgres 9.6 中的索引。引用他的测试用例:
create table tbl (col text);
create unique index on tbl (col);
insert into tbl
values (rpad(md5(random()::text), 10000, md5(random()::text)));
select length(val) from x; -- 10000
没有错误,并且列值确实测试了 10000 个字符的长度。
最近是否发生了变化,或者这怎么可能?
简短的回答:压缩。
默认情况下,数据类型
text
允许(无损!)压缩和存储:手册关于
pg_type.typstorage
:用
pg_column_size()
代替 进行测试length()
。确保测试实际表列(应用压缩)而不仅仅是输入值。看:db<>在这里摆弄
请注意如何使用 noop 表达式强制将值从其存储格式中解压缩:
pg_column_size(col || '')
。第 5 行太大而无法容纳索引元组(即使有压缩)并触发标题中的错误消息。
第 6 行会太大,甚至无法容纳索引页面并触发相关的错误消息:
生成的测试值
rpad()
具有重复模式,可以进行大规模压缩。即使是很长的琴弦也很容易适应最大值。这样压缩后的大小。有关的:
长答案
我进行了更广泛的测试,篡改了存储内部结构以验证我的理解。仅用于测试目的!
dbfiddle 不允许对系统目录进行写访问。但是查询是为了“在家”尝试。