【问题标题】:Speeding up a query with INNER JOIN使用 INNER JOIN 加速查询
【发布时间】:2017-04-24 01:36:19
【问题描述】:

我有一个查询需要很长时间才能执行。我已经等了大约 10 分钟,它仍然没有完成执行。

查询看起来像这样:

SELECT 
  one.ID, 
  two.NAME, 
  two.STATUS, 
  four.KEY, 
  four.VALUE, 
  count(one.ID) as num
FROM TABLE_ONE one, TABLE_TWO two, TABLE_THREE three, TABLE_FOUR four
WHERE one.STATE='RED'
  AND (two.STATUS='ON' OR two.STATUS='OFF')
  AND (
    four.KEY='FINAL'
    OR four.KEY='LIMIT'
    OR (
      four.KEY='MODE'
      AND (
        four.VALUE='T'
        OR four.VALUE='R')))
GROUP BY one.ID, two.NAME, two.STATUS, four.KEY, four.VALUE
ORDER BY group_name ASC;

我有另一个等效的查询,但执行速度非常快(执行大约需要 1 秒)。

这是那个查询:

SELECT 
  one.ID, 
  two.NAME, 
  two.STATUS, 
  four.KEY, 
  four.VALUE, 
  count(one.ID) as num
FROM TABLE_ONE one
INNER JOIN TABLE_TWO two
ON one.ID=two.ID
INNER JOIN TABLE_THREE three
ON two.ID=three.GROUP_ID
INNER JOIN TABLE_FOUR four
ON three.ID=four.ID
 WHERE one.STATE='RED'
  AND (two.STATUS='ON' OR two.STATUS='OFF')
  AND (
    four.KEY='FINAL'
    OR four.KEY='LIMIT'
    OR (
      four.KEY='MODE'
      AND (
        four.VALUE='T'
        OR four.VALUE='R')))
GROUP BY one.ID, two.NAME, two.STATUS, four.KEY, four.VALUE
ORDER BY group_name ASC;

我有点困惑,为什么带有 INNER JOIN 的查询执行得非常快(大约 1 秒),而没有的查询需要很长时间(等待大约 10 分钟但仍未完成执行)。

如果没有INNER JOIN,我可以对查询做些什么来加快执行时间?

我正在使用 ORACLE。

【问题讨论】:

  • 您应该查看执行计划(或“解释计划”)。我的猜测是inner join 版本正在使用索引来提高性能,而将连接条件与过滤条件混合在一起的版本出于某种原因不使用索引。或者其他一些在您查看执行计划时应该很明显的区别。

标签: sql performance join oracle11g inner-join


【解决方案1】:

在第一个查询中,表并没有真正连接到任何列上。结果称为cross join。两个表之间的交叉连接返回的行数等于第一个表中的行数乘以第二个表中的行数。

Inner join 基于给定的列集进行连接。

【讨论】:

    【解决方案2】:

    您的长期运行查询没有将一个表与另一个表关联的连接条件。因此,它正在创建每个表中所有记录的笛卡尔积。因此,如果每个表有 10 行,则在执行聚合函数之前会生成 10*10*10*10=10,000 个结果行。更大的桌子只会变得更糟。如果每个表有 1,000 行,您最终会生成 1,000,000,000,000 行。

    您更快的查询具有连接条件,可显着减少结果集中的行数,这就是它更高性能的原因。

    【讨论】:

      【解决方案3】:

      假设您有 N 个 ID 值。在第一个查询中,您将创建 N * N * N * N(或 N ^ 4)行。

      在第二个中,您将创建 N 行。

      大 O 表示法:

      O(N^4)
      

      O(N)
      

      现在您有了一个真实世界的影响示例。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-11-27
        • 1970-01-01
        • 1970-01-01
        • 2012-11-04
        • 2020-09-19
        • 1970-01-01
        • 2014-03-13
        • 2018-01-27
        相关资源
        最近更新 更多