9

我知道这是一个常见问题,并且我已经阅读了其他几篇文章和论文,但我找不到一个考虑到索引字段和两个查询可以返回的记录量的文章。

我的问题真的很简单。这里推荐使用类似 SQL 的语法编写这两者中的哪一个(就性能而言)。

第一个查询:

Select *
from someTable s
where s.someTable_id in
                    (Select someTable_id 
                     from otherTable o
                     where o.indexedField = 123)

第二个查询:

Select *
from someTable
where someTable_id in
                  (Select someTable_id 
                   from otherTable o
                   where o.someIndexedField = s.someIndexedField
                   and o.anotherIndexedField = 123)

我的理解是,第二个查询将查询外部查询将返回的每个元组的数据库,其中第一个查询将首先评估内部选择,然后将过滤器应用于外部查询。

现在考虑到 someIndexedField 字段已编入索引,第二个查询可能会超快地查询数据库,但如果我们有数千或数百万条记录,使用第一个查询不是更快吗?

注意:在 Oracle 数据库中。

4

2 回答 2

5

在 MySQL 中,如果嵌套选择在同一个表上,查询的执行时间可能会很长。

提高 MySQL 性能的一个好方法是为嵌套选择创建一个临时表,并将主选择应用于该表。

例如:

Select *
from someTable s1
where s1.someTable_id in
                    (Select someTable_id 
                     from someTable s2
                     where s2.Field = 123);

可以通过以下方式获得更好的性能:

create temporary table 'temp_table' as (
  Select someTable_id 
  from someTable s2
  where s2.Field = 123
);

Select *
from someTable s1
where s1.someTable_id in
                    (Select someTable_id 
                     from tempTable s2);

我不确定大量数据的性能。

于 2014-05-11T09:34:32.870 回答
2

关于第一个查询:

第一个查询将首先评估内部选择,然后将过滤器应用于外部查询。

那不是那么简单。

在 SQL 中,大多数情况下不可能知道先执行什么,然后再执行什么。

因为 SQL - 声明性语言。

您的“嵌套选择” - 只是视觉上的,而不是技术上的。

示例 1 - 在“someTable”中有 10 行,在“otherTable”中有 10000 行。

在大多数情况下,数据库优化器将首先读取“someTable”,然后检查 otherTable 是否匹配。为此它可能会或可能不会根据情况使用索引,我在这种情况下填写 - 它将使用“indexedField”索引。

示例 2 - 在“someTable”中有 10000 行,在“otherTable”中有 10 行。

在大多数情况下,数据库优化器会从内存中的“otherTable”读取所有行,按 123 过滤它们,然后会在 someTable PK(someTable_id) 索引中找到匹配项。结果 - “otherTable”中不会使用任何索引。

关于第二个查询:

这和第一次完全不同。所以,我不知道如何比较它们:

  • 首先查询通过一对链接两个表:s.someTable_id = o.someTable_id
  • 第二个查询通过两对链接两个表:s.someTable_id = o.someTable_id AND o.someIndexedField = s.someIndexedField。

链接两个表的常见做法是您的第一个查询。但是, o.someTable_id 应该被索引。

所以常见的规则是:

  • 所有 PK - 都应该被编入索引(默认情况下它们被编入索引)
  • 所有用于过滤的列(如在 WHERE 部分中使用的)都应该被索引
  • 用于提供表之间匹配的所有列(包括 IN、JOIN 等) - 也在过滤,所以 - 应该被索引。
  • DB Engine 将自行选择最佳顺序操作(或并行)。在大多数情况下,您无法确定这一点。
  • 使用 Oracle EXPLAIN PLAN(大多数数据库都存在类似的)来比较对真实数据的不同查询的执行计划。
于 2013-07-04T20:57:52.317 回答