Erw*_*ter 9 postgresql index size limits
我们一再看到尝试索引值超过最大大小的列失败。Postgres 10 有这样的错误信息:
Run Code Online (Sandbox Code Playgroud)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
Run Code Online (Sandbox Code Playgroud)
没有错误,列值确实测试了 10000 个字符的长度。
最近有没有变化或者这怎么可能?
Erw*_*ter 14
text默认情况下,数据类型允许(无损!)压缩和存储:
SELECT typstorage FROM pg_type WHERE typname = 'text'; -- 'x'
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)p: Value must always be stored plain. e: Value can be stored in a “secondary” relation (if relation has one, see pg_class.reltoastrelid). m: Value can be stored compressed inline. x: Value can be stored compressed inline or stored in “secondary” storage.请注意,也可以将 m 列移出到辅助存储,但只能作为最后的手段(首先移出 e 和 x 列)。
使用pg_column_size()而不是 进行测试length()。一定要测试实际的表列(应用压缩)而不仅仅是输入值。看:
CREATE TABLE tbl (id int, col text);
INSERT INTO tbl(id, col) VALUES
(1, rpad(md5('non_random'::text), 100, md5('non_random'::text)))
, (2, rpad(md5('non_random'::text), 1000, md5('non_random'::text)))
, (3, rpad(md5('non_random'::text), 10000, md5('non_random'::text)))
, (4, rpad(md5('non_random'::text), 100000, md5('non_random'::text)))
, (5, rpad(md5('non_random'::text), 500000, md5('non_random'::text)))
, (6, rpad(md5('non_random'::text), 1000000, md5('non_random'::text)));
SELECT id, left(col, 10) || ' ...' AS col
, length(col) AS char_length
, pg_column_size(col) AS compressed
, pg_column_size(col || '') AS uncompressed
FROM tbl ORDER BY id;
Run Code Online (Sandbox Code Playgroud)
SELECT typstorage FROM pg_type WHERE typname = 'text'; -- 'x'
Run Code Online (Sandbox Code Playgroud)
SELECT pg_column_size(rpad(md5('non_random'::text), 1000000, md5('non_random'::text)));
Run Code Online (Sandbox Code Playgroud)
p: Value must always be stored plain.
e: Value can be stored in a “secondary” relation (if relation has one, see pg_class.reltoastrelid).
m: Value can be stored compressed inline.
x: Value can be stored compressed inline or stored in “secondary” storage.
Run Code Online (Sandbox Code Playgroud)
db<>在这里摆弄
请注意如何使用 noop 表达式强制将值从其存储格式中解压缩:pg_column_size(col || '')。
第 5 行太大而无法容纳索引元组(即使使用压缩)并触发标题中的错误消息。
第 6 行会很大以适应索引页并触发相关错误消息:
错误:索引行需要 11504 字节,最大大小为 8191
生成的测试值rpad()具有重复模式,允许大规模压缩。即使很长的琴弦也很容易适应最大值。这样压缩后的大小。
有关的:
我进行了更广泛的测试,篡改了存储内部结构以验证我的理解。仅供测试使用!
dbfiddle 不允许对系统目录进行写访问。但查询是在那里尝试“在家”。
| 归档时间: |
|
| 查看次数: |
6817 次 |
| 最近记录: |