Em um banco de dados PostgreSQL 14.5, existe a seguinte tabela:
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;
A tabela contém aproximadamente 2e7 registros com a seguinte distribuição de State
:
Estado | Contar |
---|---|
2 | 1900000 |
4 | 200 |
Existem 4100 OtherKey
programas diferentes.
Agora a declaração relevante que leva cerca de 10 s:
UPDATE "Points" AS i
SET "State" = 0
WHERE i."OtherKey" = 'MyKeyId' AND i."State" NOT IN (0, 4, 3);
EXPLAIN
em pgAdmin mostra isso:
As condições da chave
borrada referem-se a .OtherKey
Pela minha intuição, eu teria pensado que o PostgreSQL escolheria o índice IX_Points_OtherKey
por ser mais seletivo, o que não parece ser o caso.
Então, eu realmente apreciaria se alguém pudesse explicar por que o PostgreSQL prefere o índice IX_Points_State
e como eu poderia melhorar essa consulta.
Obrigado!
Não sou especialista em PostgreSQL, mas parece-me que o PostgreSQL está realmente usando
IX_Points_OtherKey
um Bitmax Index Scan, procurando no índice"OtherKey" = 'MyKeyId'
.Em seguida, ele verificará as linhas selecionadas para verificar se elas satisfazem o
State
filtro e, finalmente, atualizará as linhas que atendem a ambas as condições.A saída de explicação deve ser lida da maioria das operações internas para a externa.
Db violino