简体   繁体   English

PostgreSQL中的查询优化

[英]Query optimization in PostgreSQL

I have rather simple query with big total runtime. 我有相当简单的查询,总运行时间很大。 Can you advise me how can I optimize it? 您能建议我如何优化它吗?

Here is explain analyze: http://explain.depesz.com/s/9xC5 这里是解释分析: http : //explain.depesz.com/s/9xC5

query: 查询:

select wpis_id from spoleczniak_oznaczone
where etykieta_id in(
  select tag_id
  from spoleczniak_subskrypcje
  where postac_id = 376476
  );

spoleczniak_oznaczone: spoleczniak_oznaczone:

 Column    |  Type   |                             Modifiers
-------------+---------+--------------------------------------------------------------------
 id          | integer | not null default nextval('spoleczniak_oznaczone_id_seq'::regclass)
 etykieta_id | integer | not null
 wpis_id     | integer | not null
Indexes:
    "spoleczniak_oznaczone_pkey" PRIMARY KEY, btree (id)
    "spoleczniak_oznaczone_etykieta_id" btree (etykieta_id)
    "spoleczniak_oznaczone_wpis_id" btree (wpis_id)
Foreign-key constraints:
    "spoleczniak_oznaczone_etykieta_id_fkey" FOREIGN KEY (etykieta_id) REFERENCES    spoleczniak_etykiety(id) DEFERRABLE INITIALLY DEFERRED
    "spoleczniak_oznaczone_wpis_id_fkey" FOREIGN KEY (wpis_id) REFERENCES spoleczniak_tablica(id) DEFERRABLE INITIALLY DEFERRED

spoleczniak_subskrypcje: spoleczniak_subskrypcje:

  Column   |  Type   |                              Modifiers
-----------+---------+----------------------------------------------------------------------
 id        | integer | not null default nextval('spoleczniak_subskrypcje_id_seq'::regclass)
 postac_id | integer | not null
 tag_id    | integer | not null
Indexes:
    "spoleczniak_subskrypcje_pkey" PRIMARY KEY, btree (id)
    "spoleczniak_subskrypcje_postac_id" btree (postac_id)
    "spoleczniak_subskrypcje_postac_tag" btree (postac_id, tag_id)
    "spoleczniak_subskrypcje_tag_id" btree (tag_id)
Foreign-key constraints:
    "spoleczniak_subskrypcje_postac_id_fkey" FOREIGN KEY (postac_id) REFERENCES postac_postacie(id) DEFERRABLE INITIALLY DEFERRED
    "spoleczniak_subskrypcje_tag_id_fkey" FOREIGN KEY (tag_id) REFERENCES spoleczniak_etykiety(id) DEFERRABLE INITIALLY DEFERRED

From the Query Plan, most of the time seems to be involved in working out the IN part of the where clause. 在查询计划中,大部分时间似乎都与制定where子句的IN部分有关。 Proper indexes seem to be used. 似乎使用了正确的索引。

select o.wpis_id 
from spoleczniak_oznaczone o
inner join spoleczniak_subskrypcje s on s.tag_id = o.etykieta_id
where s.postac_id = 376476

...looks to be functionally the same but tries it in a different way and could generate a different query plan. ...看起来在功能上是相同的,但是以不同的方式尝试它,并且可能生成不同的查询计划。

Also, as @wildplasser says, make sure statistics are up-to-date, and indexes defragmented (don't know how to do those in PostgreSQL myself). 另外,如@wildplasser所说,确保统计信息是最新的,并且对索引进行了碎片整理(不知道如何在PostgreSQL中自己做)。

EDIT: as @a_horse_with_no_name says in the comment below, the query I've suggested can return duplicates where the original wouldn't. 编辑:正如@a​​_horse_with_no_name在下面的评论中所说,我建议的查询可以返回原本不会的重复项。 Without knowing your data I don't know whether it will or not. 在不知道您的数据的情况下,我不知道是否会。 That's a warning to bear in mind. 请记住这是一个警告。

Is there a reason you preferred using in and a subquery to: 您是否倾向于使用in和子查询来执行以下操作?

select wpis_id 
from spoleczniak_oznaczone, spoleczniak_subskrypcje
where etykieta_id = tag_id 
and postac_id = 376476

I would guess a simple join might be simpler for the query optimiser. 我想对于查询优化程序来说,简单的连接可能会更简单。

This should be equivalent (and in most cases will generate the same query plan) 应该是等效的(并且在大多数情况下将生成相同的查询计划)

SELECT so.wpis_id
FROM spoleczniak_oznaczone so
WHERE EXISTS (
  SELECT *
  FROM spoleczniak_subskrypcje ss
  WHERE ss.tag_id= so.etykieta_id
  AND so.postac_id = 376476
  );

Try replacing this index: 尝试替换此索引:

"spoleczniak_oznaczone_etykieta_id" btree (etykieta_id)

with an index on (etykieta_id, wpis_id) . (etykieta_id, wpis_id)上具有索引。 This way DB could perform index-only scan (without fetching whole rows from table which costs access time). 这样,DB可以执行仅索引扫描(无需从表中获取整行,这会花费访问时间)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM