【问题标题】:Where clause is slowing my query from 2 seconds to 24 secondsWhere 子句将我的查询从 2 秒减慢到 24 秒
【发布时间】:2013-06-21 07:28:54
【问题描述】:

我正在尝试编写一个简单的查询来计算一张大表的结果。

SELECT COUNT(*)
FROM DM.DM_CUSTOMER_SEG_BRIDGE_CORP_DW AL3
WHERE (AL3.REFERENCE_YEAR(+)   =2012)

以上查询大约需要 24 秒才能返回我的输出。如果我删除 where 子句并执行相同的查询,它会在 2 秒内给我结果。

请问这是什么原因。我对 SQL 查询比较陌生。

请帮忙

谢谢, 纳文

【问题讨论】:

    标签: sql oracle11g


    【解决方案1】:

    您可能需要在表上建立索引。通常,您需要在 where 子句中使用的任何列上建立索引

    至于 (+) 语法,我认为它是多余的(我不是 Oracle 专家),但请参阅 Difference between Oracle's plus (+) notation and ansi JOIN notation?

    【讨论】:

    • 如何检查该表和列是否存在索引?
    • 有很多免费工具可以查看数据库的结构。您也可以从命令提示符进行管理。
    • 或者您可以查看查询计划,例如 EXPLAIN PLAN FOR SELECT last_name FROM employees;
    • 在这种情况下不需要 (+) 语法,因为您没有加入任何表。
    【解决方案2】:

    原因可能看起来很微妙。但是 Oracle 可以通过多种方式处理这样的查询:

    SELECT COUNT(*)
    FROM DM.DM_CUSTOMER_SEG_BRIDGE_CORP_DW AL3
    

    一种方法是读取表中的所有行。因为这是一张大桌子,所以这不是最有效的方法。第二种方法是使用某种统计信息,其中行数在统计信息中。我认为 Oracle 从来没有这样做过,但这是可以想象的。

    最后一种方法是读取索引。通常,索引会比表小得多并且它可能已经在内存中。上面的查询将读取更少量的数据。 (Here 是一篇关于计算表中所有行的有趣文章。)

    当你引入where 子句时,

    WHERE (AL3.REFERENCE_YEAR(+)   =2012)
    

    Oracle 不能再扫描任何索引。它必须扫描reference_year 索引。问题是什么?如果它扫描一个索引,它仍然需要获取数据记录以获得reference_year 的值——这与扫描整个表是等效的(实际上更糟)。

    即使在reference_year 上有索引,也不能保证您使用该索引。问题在于所谓的选择性。相对于数据库中的行数,您正在获取的行数可能仍然很大(在这种情况下,10% 是“相当大的”)。 Oracle 优化可能会选择执行全表扫描而不是读取索引。

    【讨论】:

    • Oracle 支持仅索引扫描,如果reference_year 上有索引,它将不会从表中读取任何内容。 (假设这是完整的查询并且没有其他谓词。)
    猜你喜欢
    • 2013-10-15
    • 2017-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-24
    相关资源
    最近更新 更多