Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PostgreSQL中的查询优化_Postgresql - Fatal编程技术网

PostgreSQL中的查询优化

PostgreSQL中的查询优化,postgresql,Postgresql,如何优化此查询。。请您解释一下……您可以使用选择计数(1)…但除此之外,我认为它看起来不错。如果您真的很困难,您可以使用视图缓存查询的某些部分,或者在contact_id和list_id上放置索引(我假设您已经在id上有了索引)。这已经是一个非常简单的查询,如果统计信息是最新的,数据库将以最有效的方式运行 所以就查询本身而言,没什么可做的 在数据库管理方面,您可以添加索引-数据库中应该有针对所有连接条件以及where子句中最具选择性部分的索引(在普通联系人和联系人列表中列出\u id、联系人id

如何优化此查询。。请您解释一下……

您可以使用
选择计数(1)…
但除此之外,我认为它看起来不错。如果您真的很困难,您可以使用视图缓存查询的某些部分,或者在contact_id和list_id上放置索引(我假设您已经在id上有了索引)。

这已经是一个非常简单的查询,如果统计信息是最新的,数据库将以最有效的方式运行

所以就查询本身而言,没什么可做的

在数据库管理方面,您可以添加索引-数据库中应该有针对所有连接条件以及where子句中最具选择性部分的索引(在普通联系人和联系人列表中列出\u id、联系人id作为FK)。这是提高此查询性能(数量级)的最重要机会。正如SpliFF所指出的,您可能已经有了这些索引,所以请检查


此外,博士后有良好的指挥能力,你应该学习和使用。它将有助于优化查询。

因为您只想包含在联接表中设置了一些标志的行,所以我将该语句移动到join子句中:

SELECT count(*) 
FROM contacts_lists 
     JOIN plain_contacts 
          ON contacts_lists.contact_id = plain_contacts.contact_id 
     JOIN contacts 
          ON contacts.id = plain_contacts.contact_id 
WHERE plain_contacts.has_email 
      AND NOT contacts.email_bad 
      AND NOT contacts.email_unsub 
      AND contacts_lists.list_id =67339
我不确定这是否会对性能产生重大影响,但值得一试。为了获得最佳性能,您可能还应该在连接的表上设置索引,如下所示:

SELECT count(*) 
FROM contacts_lists 
     JOIN plain_contacts 
          ON contacts_lists.contact_id = plain_contacts.contact_id 
          AND NOT plain_contacts.has_email
     JOIN contacts 
          ON contacts.id = plain_contacts.contact_id 
          AND NOT contacts.email_unsub 
          AND NOT contacts.email_bad 
WHERE contacts_lists.list_id =67339

您最近是否在数据库上运行过ANALYZE?解释计划中的行数看起来有意义吗?(看起来您只运行了EXPLAIN。EXPLAIN ANALYSE提供了估计时间和实际时间。)

为清晰起见,请重新格式化查询计划:

plain_contacts: contact_id, has_email
contacts: id, email_unsub, email_bad
根据您的数据分布,两个部分索引可能会消除seq扫描:

QUERY PLAN Aggregate (cost=126377.96..126377.97 rows=1 width=0)
  -> Hash Join (cost=6014.51..126225.38 rows=61033 width=0)
     Hash Cond: (contacts_lists.contact_id = plain_contacts.contact_id)
    -> Hash Join (cost=3067.30..121828.63 rows=61033 width=8)
       Hash Cond: (contacts_lists.contact_id = contacts.id)
      -> Index Scan using index_contacts_lists_on_list_id_and_contact_id
         on contacts_lists (cost=0.00..116909.97 rows=61033 width=4)
         Index Cond: (list_id = 66996)
         -> Hash (cost=1721.41..1721.41 rows=84551 width=4)
         -> Seq Scan on contacts (cost=0.00..1721.41 rows=84551 width=4)
            Filter: ((NOT email_bad) AND (NOT email_unsub))
            -> Hash (cost=2474.97..2474.97 rows=37779 width=4)
            -> Seq Scan on plain_contacts (cost=0.00..2474.97 rows=37779 width=4)
               Filter: has_email
外键上可能缺少索引:

-- if many contacts have bad emails or are unsubscribed:
CREATE INDEX contacts_valid_email_idx ON contacts (id)
WHERE (NOT email_bad AND NOT email_unsub);

-- if many contacts have no email:
CREATE INDEX plain_contacts_valid_email_idx ON plain_contacts (id)
WHERE (has_email);
最后但并非最不重要的一点是,如果您从未分析过数据,则需要运行:

CREATE INDEX plain_contacts_contact_id_idx ON plain_contacts (contact_id);

如果所有这些都完成后仍然很慢,除了合并普通联系人和联系人表之外,您没有什么可以做的:尽管有上述索引,但获得上述查询计划意味着您的大多数/所有订阅者都订阅了该特定列表——在这种情况下,上述查询计划是您获得的最快的查询计划。

两者之间没有任何性能差异
count(*)
count(1)
哪个版本?你能证明吗?我怀疑有什么不同。我想我是在Postgres7.3的用户说明中发现的。这并不意味着它是正确的,很可能是一个很早以前的假设。7.x不再是一个参考。事实上,任何基于8.1之前版本的(性能)信息都是绝对删除的。你有联系人列表的索引吗?列表id?你也可以尝试在contacts.email\u bad(或email\u unsub)上建立索引。请向我们展示查询的执行计划(最好使用
EXPLAIN ANALYZE
)您对该查询有什么问题?每当您对PostgreSQL查询有问题时,请发布PostgreSQL版本并解释问题查询的分析。如果没有这些,您得到的任何响应都是纯粹的推测。查询计划聚合(cost=126377.96..126377.97行=1宽度=0)->散列连接(cost=6014.51..126225.38行=61033宽度=0)散列连接:(contacts_list.contact_id=plain_contacts.contact_id)->散列连接(cost=3067.30..121828.63行=61033宽度=8)Hash Cond:(contacts_lists.contact_id=contacts.id)->使用Index_contacts_lists_on_list_id_和contacts_list_id_进行索引扫描(cost=0.00..116909.97行=61033宽=4)Index Cond:(list_id=66996)->Hash(cost=1721.41..1721.41行=84551宽=4)->联系人上的顺序扫描(成本=0.00..1721.41行=84551宽度=4)过滤器:((非电子邮件坏)和(非电子邮件不明))->哈希(成本=2474.97..2474.97行=37779宽度=4)->普通联系人上的顺序扫描(成本=0.00..2474.97行=37779宽度=4)筛选器:我已经有了这两个索引。是否有其他方法优化此查询。如果有,请解释。您理论上感兴趣还是需要提高查询速度?选择计数(联系人列表。联系人id)从contacts_lists where contacts_lists.list_id=66996和contacts_lists.contact_id in(从contacts where(NOT contacts.email_bad和NOT contacts.email_unsub)中选择id)和id in(从plain_contacts where plain_contacts.has_email中选择plain)现在我更改了这样的查询。请你解释一下哪一个最好。谢谢你的回复。但它给出的结果与前面的相同。从contacts_list.list_id=66996的contacts_list中选择count(contacts_list.contact_id)和contacts_list.contact_id in(从contacts where(NOT contacts.email_bad和NOT contacts.email_unsub)中选择id)和id in(从plain_contacts中选择plain_contacts.contacts_id,其中plain_contacts.has有电子邮件))现在我像这样更改了查询。你能解释一下哪一个是最好的吗?这完全取决于你有哪些索引。好的是最快的,就这么简单。你的版本的优点是它可以更好地利用没有id列的索引,如果你有这样的索引(例如,只有email\u bad或email\u unsub上的索引),谢谢你的回复。谢谢回复。但这种真空分析是在postgresql 8.4中由自动真空守护进程自动完成的。id和联系人id已根据我们在我的应用程序中的选择进行了更改。拥有自动真空守护进程非常好,但如果您的数据发生任何重大变化,它不应阻止您定期运行真空分析。
VACUUM ANALYZE;