是否可以在 PostgreSQL 中索引数组列的位置?
Posted
技术标签:
【中文标题】是否可以在 PostgreSQL 中索引数组列的位置?【英文标题】:Is it possible to index the position of an array column in PostgreSQL? 【发布时间】:2021-12-17 22:59:47 【问题描述】:假设我想在表my_table
中查找在数组列my_array_column
的第一个位置具有值5
的行。为了准备表格,我执行了以下语句:
CREATE TABLE my_table (
id serial primary key,
my_array_column integer[]
);
CREATE INDEX my_table_my_array_column_index on "my_table" USING GIN ("my_array_column");
SET enable_seqscan TO off;
INSERT INTO my_table (my_array_column) VALUES ('5,7,10');
现在,查询可能如下所示:
select * from my_table where my_array_column[1] = 5;
这可行,但它不使用创建的 GIN 索引。是否可以通过索引在特定位置搜索值5
?
【问题讨论】:
【参考方案1】:我想在表
my_table
中查找在数组列的第一个位置具有值5
的行
partial index 对于该定义最有效:
CREATE INDEX my_table_my_array_special_idx ON my_table ((true))
WHERE my_array_column[1] = 5;
如果只有一小部分行符合条件,则部分索引会相应地更小。另外,实际的索引列只占用最小的空间(通常是 8 个字节)。而且,最重要的是,Postgres 13 或更高版本可以应用 index deduplication 来使索引更小。
一旦索引被完全缓存,它的小尺寸并没有使它更快,但仍然。 而且大多数写入不必操作索引,这可能是最重要的好处,具体取决于工作负载。
哦,Postgres 会收集部分索引的统计信息。因此,当涉及到该索引时,您可以期望查询规划器做出充分的选择。
相关:
PostgreSQL partial index unused when created on a table with existing data Index that is not used, yet influences query当查询重复相同条件时适用。
通常,您有一些有用的索引字段在您声明的目的的顶部。但如果你不这样做,只需使用任何小的常量 - 在我的示例中为 true
,但任何
次要免责声明:Postgres 数组中的“第一个位置”不一定有索引 1
。如果可以使用非标准数组索引,请考虑:
...
WHERE (my_array_column[:])[1] = 5;
在索引和查询中。
见:
Normalize array subscripts for 1-dimensional array so they start with 1【讨论】:
【参考方案2】:您可以只索引第一个位置。您需要在 create 语句中使用一组额外的括号来执行此操作:
create index on my_table ((my_array_column[1]));
或者你可以扩充你的查询来使用你的 gin 索引,理论上一个数组不能有第一个元素是 5,除非至少一个元素是 5。
select * from my_table where my_array_column[1] = 5 and my_array_column @> ARRAY[5];
当然,如果您的许多数组包含 5,但在数组中的其他位置,这将不是很有效。它必须重新检查所有这些“错误匹配”以消除它们。所以如果你只关心第一个元素,我展示的第一个索引会更好。 (当然,如果只关心第一个元素,为什么要用数组开头呢?)
【讨论】:
【参考方案3】:如果您总是查看第一个位置,则常规 B-Tree 索引会这样做:
create index on my_table ( (my_array_column[1]) );
如果您不知道位置,则确实需要 GIN 索引,但您需要使用 is supported 通过 gin 索引的运算符,例如@>
运算符。但为此,您需要使用不同的查询:
select *
from my_table
where my_array_column @> array[5];
这将找到数组列包含值 5 的所有行。
但是你应该参考手册中关于数组使用的建议:
数组不是集合;搜索特定的数组元素可能是数据库设计错误的标志。考虑使用一个单独的表,其中每个项目将是一个数组元素。这将更容易搜索,并且对于大量元素可能会更好地扩展。
【讨论】:
这似乎是一个语法错误:[42601] ERROR: syntax error at or near ")"
@plenox 抱歉,您需要用括号将表达式括起来以上是关于是否可以在 PostgreSQL 中索引数组列的位置?的主要内容,如果未能解决你的问题,请参考以下文章