Quando eu quero usar este sql para verificar usando índice ou não:
explain SELECT id AS id, sub_source_id AS sub_source_id
FROM article
WHERE sub_source_id IN (
select sub_source_id
from sub_relation sr
where user_id =14
and sub_status = 1
) ORDER BY created_time DESC LIMIT 50
mostrar informações como esta:
Workers Planned: 2
-> Sort (cost=74344.09..74697.64 rows=141422 width=24)
Sort Key: article.created_time DESC
-> Hash Join (cost=77.11..69646.15 rows=141422 width=24)
Hash Cond: (article.sub_source_id = sr.sub_source_id)
-> Parallel Seq Scan on article (cost=0.00..67792.05 rows=675805 width=24)
-> Hash (cost=70.56..70.56 rows=524 width=8)
-> Seq Scan on sub_relation sr (cost=0.00..70.56 rows=524 width=8)
Filter: ((user_id = 14) AND (sub_status = 1))
Já criei multi-column index com column sub_source_id
and created_time
, porque o sql não usou esse article_sub_source_id_create_time_idx
índice? Esta é a estrutura da tabela:
-- public.article definition
-- Drop table
-- DROP TABLE public.article;
CREATE TABLE public.article (
id int8 NOT NULL GENERATED ALWAYS AS IDENTITY,
user_id int8 NOT NULL,
title varchar(512) NOT NULL,
author varchar(256) NOT NULL,
guid varchar(512) NOT NULL,
created_time int8 NOT NULL,
updated_time int8 NOT NULL,
link varchar(512) NULL,
pub_time timestamptz NULL,
sub_source_id int8 NOT NULL,
cover_image varchar(1024) NULL,
channel_reputation int4 NOT NULL DEFAULT 0,
editor_pick int4 NULL DEFAULT 0,
permanent_store int2 NOT NULL DEFAULT 0,
CONSTRAINT article_id_seq_pk PRIMARY KEY (id),
CONSTRAINT article_title_sub_source_id_key UNIQUE (title, sub_source_id)
);
CREATE INDEX article_sub_source_id_create_time_idx ON public.article USING btree (sub_source_id, created_time);
CREATE INDEX article_title_gin ON public.article USING gin (to_tsvector('english'::regconfig, (title)::text));
CREATE INDEX article_title_zh_gin ON public.article USING gin (to_tsvector('dolphinzhcfg'::regconfig, (title)::text));
quando removo a subconsulta e a substituo pelo id de sub fonte estática, a consulta externa pode usar o article_sub_source_id_create_time_idx
index.
O planejador pensa que você estará buscando 20% da tabela, antes que a classificação e o LIMIT sejam aplicados. (Está correto?). Usar um índice para fazer isso é provavelmente uma má ideia, a menos que possa usar uma varredura somente de índice ou possa usar uma varredura de índice de ordenação e, em seguida, parar mais cedo.
Para obter uma varredura apenas de índice, você precisaria que o índice tivesse todas as colunas usadas para essa tabela,
(sub_source_id, created_time, id)
.Para fazê-lo usar o índice para ordenação, created_time precisaria ser a primeira coluna no índice (ou pelo menos precisaria seguir apenas colunas testadas para igualdade simples, das quais essa consulta não tem nenhuma)