使这个查询更快

Posted

技术标签:

【中文标题】使这个查询更快【英文标题】:Making this query faster 【发布时间】:2021-01-20 19:28:06 【问题描述】:

因此,正如我之前提到的,我不处理通常需要帮助增强此查询的原始 SQL。目前,大约需要 3 秒。我想知道他们是否有办法让它变得更好。我删除了一些选择以使查询更小。

select row_number() over ()                      as id,
       scope.id                                  as sow_id,
       scope.*,
       task.*,
       po.entity_id                              as group_name
from t_scope_of_work as scope,
     (select * from audittaskimpl) as task
         Left join peopleassignments_potowners po ON task.taskid = po.task_id and po.entity_id like '%/%'
Where task.processinstanceid IN
      (select distinct processinstanceid from taskvariableimpl where value = scope.sownumber)
order by task.processinstanceid desc, task.createdon desc;
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|QUERY PLAN                                                                                                                                                                       |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|Sort  (cost=3037398.97..3037728.28 rows=131726 width=1981) (actual time=1714.744..1714.812 rows=648 loops=1)                                                                     |
|  Sort Key: task.processinstanceid DESC, task.createdon DESC                                                                                                                     |
|  Sort Method: quicksort  Memory: 884kB                                                                                                                                          |
|  Buffers: shared hit=930703                                                                                                                                                     |
|  ->  WindowAgg  (cost=0.55..2800174.53 rows=131726 width=1981) (actual time=6.919..1713.339 rows=648 loops=1)                                                                   |
|        Buffers: shared hit=930703                                                                                                                                               |
|        ->  Merge Right Join  (cost=0.55..2798527.96 rows=131726 width=1965) (actual time=6.905..1712.235 rows=648 loops=1)                                                      |
|              Merge Cond: (po.task_id = task.taskid)                                                                                                                             |
|              Buffers: shared hit=930703                                                                                                                                         |
|              ->  Index Only Scan using idx_paspot_taskentity on peopleassignments_potowners po  (cost=0.27..32.45 rows=462 width=28) (actual time=0.101..0.378 rows=446 loops=1)|
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

【问题讨论】:

您好,首先我会对其进行解释分析,以便您对数据库实际使用它的操作有一个合理的估计。 通过将 WHERE ... IN 替换为 INNER JOIN 是否会提高性能? dba.stackexchange.com 上的人可能也能提供帮助 不会有什么不同,但是:(select * from audittaskimpl) as task 可以简化为 audittaskimpl as task。并且请不要在 WHERE 子句和显式 JOIN 运算符中混合使用旧的、古老的和脆弱的隐式连接。对所有连接使用显式 JOIN edit您的问题并添加使用explain (analyze, buffers, format text)生成的execution plan(不是只是一个“简单”解释)为formatted text,并确保保留计划的缩进。粘贴文本,然后将``` 放在计划前一行和计划后一行。还请包括所有索引的完整 create index 语句。 【参考方案1】:

您的查询归结为:

select row_number() over ()                      as id,
       scope.id                                  as sow_id,
       scope.*,
       task.*,
       po.entity_id                              as group_name
from t_scope_of_work as scope
join audittaskimpl as task
  on task.processinstanceid IN  (select distinct tvi.processinstanceid 
                                   from taskvariableimpl tvi
                                  where tvi.value = scope.sownumber)
Left outer join peopleassignments_potowners po 
             ON po.task_id = task.taskid 
            and po.entity_id like '%/%'

order by task.processinstanceid desc, task.createdon desc;

如果没有解释,几乎不可能就该查询中的瓶颈所在提供建议。例如。您可能缺少一些索引,可能是因为数据太多而无法快速获得。

也就是说,我怀疑你需要distinct;事实上,可能值得尝试 EXISTS() 构造只是为了看看它给出了什么。 像这样的:

 select row_number() over ()                      as id,
       scope.id                                  as sow_id,
       scope.*,
       task.*,
       po.entity_id                              as group_name
from t_scope_of_work as scope
join audittaskimpl as task
  on exists ( select * 
                from taskvariableimpl tvi
               where tvi.value             = scope.sownumber
                 and tvi.processinstanceid = task.processinstanceid )
Left outer join peopleassignments_potowners po 
             ON po.task_id = task.taskid 
            and po.entity_id like '%/%'

order by task.processinstanceid desc, task.createdon desc;

警告:购买前请先尝试!事实证明这可能比您的原始查询更糟糕,我以前从未做过JOIN [..] ON EXISTS();再次,在没有正确了解您的表、卷、索引、数据布局的情况下(阅读:连接中有很多“命中”还是只有几条记录?)等等......我们在这里几乎是盲目地工作。

【讨论】:

这太棒了,不知道你是怎么做到的,但看起来从 2-3 秒到 300 毫秒。

以上是关于使这个查询更快的主要内容,如果未能解决你的问题,请参考以下文章

SQL查询性能调优--如何使查询更快

如何使用 CommonDataKinds.Phone 内部查询使此 ContactsContract.Contact 查询更快?

在 from 子句 *and* where 子句中添加连接条件使查询更快。为啥?

MYSQL who are my JOINS 似乎使查询更快?

使 mysql 查询更快,或提出替代方案

查询减慢网站速度,必须使它们执行得更快