在 PostgreSQL 14.5 数据库上,有下表:
CREATE TABLE IF NOT EXISTS public."Points"
(
"Key" character varying(50) COLLATE pg_catalog."default" NOT NULL,
"ReferencedKeys" text[] COLLATE pg_catalog."default" NOT NULL,
"State" integer NOT NULL,
"OtherKey" text COLLATE pg_catalog."default",
CONSTRAINT "PK_Points" PRIMARY KEY ("Key")
)
CREATE INDEX IF NOT EXISTS "IX_Points_OtherKey"
ON public."Points" USING btree
("OtherKey" COLLATE pg_catalog."default" ASC NULLS LAST)
TABLESPACE pg_default;
CREATE INDEX IF NOT EXISTS "IX_Points_ReferencedKeys"
ON public."Points" USING gin
("ReferencedKeys" COLLATE pg_catalog."default")
TABLESPACE pg_default;
CREATE INDEX IF NOT EXISTS "IX_Points_State"
ON public."Points" USING btree
("State" ASC NULLS LAST)
TABLESPACE pg_default;
该表包含大约 2e7 条记录,其分布如下State
:
状态 | 数数 |
---|---|
2个 | 1900000 |
4个 | 200 |
有 4100 个不同的OtherKey
s。
现在的相关声明大约需要 10 秒:
UPDATE "Points" AS i
SET "State" = 0
WHERE i."OtherKey" = 'MyKeyId' AND i."State" NOT IN (0, 4, 3);
EXPLAIN
在 pgAdmin 中显示:
The blurred Key conditions refer to .OtherKey
根据我的直觉,我原以为 PostgreSQL 会选择索引,IX_Points_OtherKey
因为它更具选择性,但似乎并非如此。
所以如果有人能解释为什么 PostgreSQL 更喜欢索引IX_Points_State
以及我如何改进这个查询,我将非常感激。
谢谢你!
我不是 PostgreSQL 专家,但在我看来,PostgreSQL 确实在使用
IX_Points_OtherKey
Bitmax 索引扫描,在索引中搜索"OtherKey" = 'MyKeyId'
.然后它将检查选定的行以检查它们是否满足过滤
State
器,最后它将更新满足两个条件的那些行。Explain 输出必须从最内层的操作读取到最外层。
分贝小提琴