0

假设我想在表my_table中查找值5位于数组 column 的第一个位置的行my_array_column。为了准备表格,我执行了以下语句:

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特定位置的值?

4

3 回答 3

2

我想在表my_table中找到值5在数组列的第一个位置的行

对于该定义,部分索引将是最有效的:

CREATE INDEX my_table_my_array_special_idx ON my_table ((true))
WHERE my_array_column[1] = 5;

如果只有一小部分行符合条件,则部分索引相应较小。另外,实际的索引列只占用最小的空间(通常是 8 个字节)。而且,最重要的是,Postgres 13 或更高版本可以应用索引重复数据删除来使索引更小。

一旦索引被完全缓存,它的小尺寸并没有使它更快,但仍然如此。
而且大多数写入不必操作索引,这可能是最重要的好处,具体取决于工作负载。

哦,Postgres 收集部分索引的统计信息。因此,您可以期望查询规划器在涉及该索引时做出充分的选择。

有关的:

当查询重复相同条件时适用。

通常,除了声明的目的之外,您还有一些有用的索引字段但如果你不这样做,只需使用任何小的常量 -true在我的示例中,但任何小于 8 字节的内容都同样好。

次要免责声明:Postgres 数组中的“第一个位置”不一定有 index 1。如果可以使用非标准数组索引,请考虑:

...
WHERE (my_array_column[:])[1] = 5;

在索引查询中。

看:

于 2021-12-17T23:16:47.120 回答
1

如果您总是查看第一个位置,则常规 B-Tree 索引将执行以下操作:

create index on my_table ( (my_array_column[1]) );

如果您不知道位置,则确实需要 GIN 索引,但您需要使用gin 索引支持@>的运算符,例如运算符。但为此,您需要使用不同的查询:

select *
from my_table
where my_array_column @> array[5];

这将找到数组列包含值 5 的所有行。


但是您应该遵循手册中有关使用数组的建议:

数组不是集合;搜索特定的数组元素可能是数据库设计错误的标志。考虑使用一个单独的表,其中每个项目将是一个数组元素。这将更容易搜索,并且对于大量元素可能会更好地扩展。

于 2021-12-17T23:03:02.760 回答
1

您可以只索引第一个位置。您需要在 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,但在数组中的其他位置,这将不是很有效。它必须重新检查所有这些“错误匹配”以消除它们。所以如果你只关心第一个元素,我展示的第一个索引会更好。(当然,如果你只关心第一个元素,为什么要用数组开头呢?)

于 2021-12-17T23:45:17.740 回答