优化嵌套sql查询

Posted

技术标签:

【中文标题】优化嵌套sql查询【英文标题】:Optimize nested sql query 【发布时间】:2018-07-24 02:17:15 【问题描述】:

我正在尝试优化以下每 50 秒运行一次的查询以提高性能。

select * from event se1  
where id = (select min(id) from event se2 where
se1.sub_id=se2.sub_id and se2.state = 'PENDING' and se2.il_flag= true)  
and not exists (select id from event se2 where se1.sub_id=se2.sub_id
and se2.state in ('ACCEPTED', 'FAILED', 'INPROCESS'))

关于提出更好的查询以提高其性能的任何方向? (postgres 9.6)。感谢帮助。

事件表

Id              sub_id              state       idl_flag 
1                 23009            Pending        true
2                 23009            Accepted       true
3                 23009            Pending        true
4                 23009            Pending        true
5                 23010            Pending        true
6                 23010            Pending        true
7                 23011            Pending        true
8                 23012            Pending        true

上表应该返回

       5                 23010            Pending       true
       7                 23011            Pending       true

【问题讨论】:

看看Oracle SQL Developer 这个工具,结合Oracle Docs 的数据库SQL 调优指南Query Optimizer Concepts 应该会给你一个好的开始。 @Rushikumar:Oracle 的调优指南如何帮助 Postgres? 我并不完全清楚你的陈述应该达到什么目的。您能否edit 提出您的问题并添加一些sample data 和基于该数据的预期输出。 Formatted text 请no screen shots. @a_horse_with_no_name 好吧...有办法configure Oracle SQL Dev for PostgreSQL...和Oracel SQL Dev does support connection to PostgreSQL 没错,您可以使用 SQL Developer 连接到 Postgres 服务器。但这并不意味着调整查询的策略与 Oracle 相同。 Oracle 调优指南对 Postgres 几乎没用 【参考方案1】:

我提出了这个查询,欢迎任何进一步改进查询的建议。

select se1.* from event se1 join 
  (select sub_id,min(id) as id from event  where state='PENDING' and
           il_flag=false group by sub_id)se2 
   on se1.id=se2.id 
  left join (select sub_id from 
  event se3 where se3.state in ('ACCEPTED', 'FAILED', 'INPROCESS'))se4 
on se1.sub_id=se4.sub_id where se4.sub_id is null

【讨论】:

【参考方案2】:

您在回答中所做的事情与您在问题中所做的不同 - 原始答案中没有关于“错误”状态的特殊情况。

根据您最初的问题,我为您做了一些小技巧,它的运行速度并不比您原来的快,但我讨厌嵌套子查询。我已将其全部考虑到 CTE 中,因此您可以选择所需的状态,只是为了向您展示不同的方法。这可能只是个人喜好,但恕我直言,我的版本比原版更容易阅读!

SQL Fiddle - CTE Example

【讨论】:

【参考方案3】:

您可以使用事件表进行连接,但对这部分使用 is null 条件:

and not exists (select id from event se2 where se1.sub_id=se2.sub_id
and se2.state in ('ACCEPTED', 'FAILED', 'INPROCESS'))

请检查How to write "not in ()" sql query using join

但无论如何尽量避免使用嵌套查询。

【讨论】:

以上是关于优化嵌套sql查询的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JOINS 和嵌套 SELECT 优化此 SQL 查询?

优化多个嵌套选择的 SQL 查询

优化sql嵌套查询,使用CTE语法

如何优化这个嵌套的 SQL SELECT 查询

如何优化执行嵌套在 group-by 子句中的计数的 SQL 查询?

mysql SQL优化之嵌套查询-遁地龙卷风