【问题标题】:select from select, performance从选择中选择,性能
【发布时间】:2018-07-05 06:21:54
【问题描述】:

我想问,什么查询应该更高效?

select col1, col2 from 
    (select col1, col2 from table2) 
where col1 = 'something'

select col1, col2 from 
    (select col1, col2 from table2 
    where col1 = 'something') 
where col1 = 'something'

似乎第二个查询应该更有效,但在 sqldeveloper 中第一个查询花费的时间更少。为什么会这样?

【问题讨论】:

  • 两个查询都会失败
  • 请不要使用不适用于您的问题的标签
  • 您不必在第二个查询中按 Col1 过滤两次。 Col1 = 'something' 的行已在子查询中过滤。
  • 为什么你认为第二个查询应该更有效?您正在将另一个过滤器添加到组合中。还有一个过滤已经过滤的记录。在您给定的示例中,select col1, col2 from table2 where col1 = 'something' 将是更少的处理步骤。
  • @JohnConde - 您编辑了标签以删除 [sql-server][mysql],但留下了 [oracle]。你为什么会做出这样的选择?查看 OP 历史中的问题,他们似乎更有可能使用[mysql](Oracle SQL Developer 可以连接到 MySQL,并安装了正确的 JDBC jar)。

标签: sql oracle performance


【解决方案1】:

容易相互转换的查询通常同样有效。

Oracle 不必按照编写顺序运行查询。 Oracle 优化器可以像大多数程序员一样重新排列条件、删除括号、消除冗余条件以及执行其他查询转换。具体例子,谷歌“谓词推送”和“视图合并”。

除非您的示例有更多内容,否则这两个查询应该同时运行。

如果他们不这样做,那很可能是测试错误。由于缓存和服务器负载,测量查询性能可能很棘手。

如果缓存不能解释它,请查看完整的解释计划,包括“注释”部分。两个微不足道的查询运行方式不同的另一个原因是其中一个可能具有计划管理。例如,DBA 可能专门为一个查询添加了一个 SQL 配置文件来修复某些问题。并且更改单个空格可以使查询与该 SQL 配置文件不再适用的地方足够不同。

【讨论】:

  • "这很可能是一个测试错误"*。但愿如此。性能测试特别难做好。
【解决方案2】:

只是一个带有下表的小例子:

create table tab1(col1, col2) as
select level, case when mod(level, 2) = 0 then 'even' else 'odd' end
from dual
connect by level < 100000;

create table tab2(col1, col2) as
select level, case when mod(level, 2) = 0 then 'even' else 'odd' end
from dual
connect by level < 100000;

第一个查询

select col1, col2
from (
      select col1, col2
      from tab1
     )
where col2 = 'odd';

有计划:

----------------------------------
| Id  | Operation         | Name |
----------------------------------
|   0 | SELECT STATEMENT  |      |
|   1 |  TABLE ACCESS FULL| TAB1 |
----------------------------------

第二个查询

select col1, col2
from
    (
     select col1, col2
     from tab2
     where col2 = 'odd'
    )
where col2 = 'odd';

----------------------------------
| Id  | Operation         | Name |
----------------------------------
|   0 | SELECT STATEMENT  |      |
|   1 |  TABLE ACCESS FULL| TAB2 |
----------------------------------

两个查询具有相同的计划。

如果我添加一个索引:

create index tab1_idx on tab1(col2);
create index tab2_idx on tab2(col2);

查询仍然有相同的计划:

------------------------------------------------
| Id  | Operation                   | Name     |
------------------------------------------------
|   0 | SELECT STATEMENT            |          |
|   1 |  TABLE ACCESS BY INDEX ROWID| TAB1     |
|   2 |   INDEX RANGE SCAN          | TAB1_IDX |
------------------------------------------------

------------------------------------------------
| Id  | Operation                   | Name     |
------------------------------------------------
|   0 | SELECT STATEMENT            |          |
|   1 |  TABLE ACCESS BY INDEX ROWID| TAB2     |
|   2 |   INDEX RANGE SCAN          | TAB2_IDX |
------------------------------------------------

请注意,简单地运行两个查询可能不是检查其性能的好方法,因为 Oracle 可能会缓存第一个查询的结果,从而在第二个查询中运行得更快。

解释计划有助于理解查询的真正作用以及它如何扫描表和索引。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-03
    • 2016-12-12
    • 1970-01-01
    • 2012-02-08
    • 1970-01-01
    • 2014-08-19
    • 2012-01-31
    • 2010-11-27
    相关资源
    最近更新 更多