【问题标题】:How bad is IN operator for SQL query perfomance?IN 运算符对 SQL 查询性能有多差?
【发布时间】:2011-09-21 10:24:57
【问题描述】:

我的 SQL 查询需要 9 个小时才能执行。见下文:

Select Field1, Field2
From A
Where Field3 IN (45 unique values here) 

当我将此查询拆分为 3 个完全相同的查询时,每个查询在 IN 子句中都有 15 个值,它们每个都需要 2 分钟来执行。 因此,我现在花费 6 分钟(3 个查询 * 2 分钟),而不是花费 9 小时。

谁能解释一下在IN 子句中只有值数量不同的相同查询如何花费不同的时间来运行?

【问题讨论】:

  • 您使用的是哪个数据库?您能否为这两种情况发布等效的执行计划?
  • 我使用 Oracle 数据库。不幸的是,我无法检索执行计划。 Field3 是一个 3 位数字。

标签: sql performance operator-keyword


【解决方案1】:

查询性能不佳可能是由许多不同的问题引起的,我什至不敢猜测这些都是您的问题,因为没有足够的信息:

  • 多个或不必要的连接
  • 连接表的行数
  • 没有索引或查询引擎未使用索引
  • 过时的表统计信息导致索引效率低下
  • 低效查询

话虽如此,您始终可以通过运行 EXPLAIN PLAN 更好地了解查询引擎是如何解释您的查询的。以下是有关如何为 Oracle 数据库执行此操作的信息,http://download.oracle.com/docs/cd/B10500_01/server.920/a96533/ex_plan.htm

【讨论】:

    【解决方案2】:

    首先,确保在表“A”中的“Field3”上有一个索引,如果可能的话,包括“Field1”、“Field2”(覆盖索引)。您没有说您正在运行哪个数据库,因此很难准确给出更好的建议。

    如果这仍然不能加快速度,请尝试创建一个临时表,然后将所有“IN”值,然后将该临时表“INNER JOIN”或“WHERE EXISTS”插入到您的表“A”中。

    【讨论】:

      【解决方案3】:
      • 您使用的是什么数据库引擎(Oracle、SQL Server、MySQL 等)?
      • 能否发布两个查询的查询计划?

      听起来您的数据库正在使用的优化器为第一个查询选择了一个非常糟糕的执行计划。假设您的数据库引擎使用某种基于成本的优化器(大多数大型供应商都这样做),这通常意味着优化器对返回多少行的猜测是非常不正确的。最有可能的是,无论指定 15 个还是 45 个唯一值,它的估计都是同样不正确的,但是碰巧三倍的错误估计会导致优化器相信不同的查询计划是合适的。通常,这意味着您提供给优化器的关于表 A 的统计信息不正确,需要修复。

      话虽如此,表A 有多大?如果您真的是从单个表中查询,那么优化器需要考虑的选项相对较少。它实际上只需要在对 A 进行全表扫描和在 Field3 上使用索引之间做出决定。即使它决定进行表扫描而不是在Field3 上使用索引,也不可能需要花费 9 小时来扫描单个表,除非在表 A 的测量值至少为数百的特殊情况下国标和硬件都比较行。

      【讨论】:

      • @user652061 - 好的。您可以发布两个查询的查询计划吗?您可以编辑原始问题以添加此信息。
      • 我使用 Oracle 数据库。不幸的是,我无法检索查询计划。所有的表都很大,有些有几百万行,几万行。我放了简化版的查询。实际上查询从 5 个表中查询了大约 20 个字段,并且有大约 15 个 WHERE 条件。我的主要惊讶和问题是,对于完全相同的查询,9 小时与 6 分钟的执行时间差异如此之大,而 IN 子句中的值数量差异不大。
      • @user652061 - 您是说您不知道如何检索查询计划(我们可以帮助您)?或者您无权检索或发布查询计划(我们无能为力)?如果没有查询计划,我们只能推测查询计划发生了变化,因为优化器的估计不准确。很难说明为什么优化器的估计可能不正确,或者如何为优化器提供更好的信息,以便它可以在不查看实际生成和估计的内容的情况下制定更好的计划。
      • 嗯,是的,我不知道如何检索查询计划,而且我的只读访问权限非常有限,所以即使我知道如何检索,我也不认为我可以检索查询计划: (
      • @user652061 - 你能发出命令“explain plan for >”吗?
      【解决方案4】:

      我能看到的两种可能性:

      1) Field3 = 10001 可能有十亿条记录,所以这会非常慢。并且可能没有其他值的记录,所以这会非常快。

      2) 问题可能是数据库用于运行查询的方法。例如,可能有一个截止点,它可能会从使用索引切换到全表扫描。优化器并不总是正确的。当它出错时,你必须绕着它跳舞。

      【讨论】:

      • 它不能是第一个选项,因为我使用相同的 Field3 值,只是它们被分为 3 个查询而不是一个。
      【解决方案5】:

      您尝试使用EXISTS 吗?

       Select Field1, Field2 From A Where
       EXISTS (SELECT NULL FROM B Where
       B.value = A.Value )
      

      【讨论】:

      • 我只能给你 1 票,否则我会给你 1 票:EXISTSIN 快得多,1 票给:SELECT NULL FROM 查询优化。
      • 'SELECT NULL' 不是为了优化。在“EXISTS”中,这些字段被忽略。
      • 那么,SELECT * FROM B ... 在执行查询时会提供相同的性能并在 db 中消耗相同的内存?
      • @VisruthCV See this answer.
      猜你喜欢
      • 2013-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-06
      • 1970-01-01
      • 1970-01-01
      • 2021-08-21
      • 2016-04-09
      相关资源
      最近更新 更多