sql - 选择顶行时使用了错误的索引

标签 sql oracle optimization plsql indexing

我有一个简单的查询,它选择由其他索引列过滤的列之一排序的前 200 行。困惑是为什么PL/SQL Developer中的查询计划显示使用了这个索引只有当我选择所有行时,例如:

SELECT * FROM
(
 SELECT *
 FROM cr_proposalsearch ps
 WHERE UPPER(ps.customerpostcode) like 'MK3%'
 ORDER BY ps.ProposalNumber DESC
)
WHERE ROWNUM <= 200

计划显示它使用索引CR_PROPOSALSEARCH_I1,它是两列的索引:PROPOSALNUMBER & UPPER(CUSTOMERNAME),这需要 0.985s 执行:
query with ROWNUM

如果我摆脱了 ROWNUM 条件,计划就是我所期望的,它会在 中执行0.343s :
query without ROWNUM

哪里index XIF25CR_PROPOSALSEARCH is on CR_PROPOSALSEARCH (UPPER(CUSTOMERPOSTCODE));
怎么来的?

编辑 : 我收集了 cr_proposalsearch 的统计数据表和两个查询计划现在都显示它们使用 XIF25CR_PROPOSALSEARCH指数。

最佳答案

包括 ROWNUM 会更改优化器关于哪个是更有效路径的计算。

当您执行这样的 top-n 查询时,并不一定意味着 Oracle 将获取所有行,对它们进行完全排序,然后返回顶部的行。 COUNT STOPKEY执行计划中的操作表示 Oracle 只会执行底层操作,直到找到您要求的行数。

优化器计算出完整查询将获取和排序 77K 行。如果它使用这个计划进行 top-n 查询,它必须对这些行进行大量排序才能找到前 200 行(它不一定要对它们进行完全排序,因为它不关心确切的顺序)超过顶部的行数;但它必须查看所有这些行)。

top-n 查询的计划使用另一个索引来完全避免排序。它按顺序考虑每一行,检查它是否与谓词匹配,如果匹配则返回它。当它返回 200 行时,就完成了。它的计算表明,这对于获取少量行会更有效。 (当然,这可能不对;您还没有说明这些查询的相对性能是多少。)

如果优化器在您请求所有行时选择此计划,则它必须按降序读取整个索引,在检查谓词时按 ROWID 从表中获取每一行。这将导致大量额外的 I/O 并检查许多不会返回的行。所以在这种情况下,它决定使用 customerpostcode 上的索引。效率更高。

如果您逐渐增加要从 top-n 查询返回的行数,您可能会发现计划从第一个切换到第二个的临界点。仅从这两个计划的成本来看,我猜这可能是大约 1,200 行。

关于sql - 选择顶行时使用了错误的索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6911423/

相关文章:

mysql - 管理多值属性 SQL

sql - 物化 View 使用 HAVING 子句快速刷新?

sql - 计算整个表的哈希值的最快方法

oracle - HSQLDB - Oracle to_char(整数)抛出 "Unexpected Token : )"

javascript - 网站优化 - 页面加载时间和 DOM 操作

java - 自动生成的实体类出现 Netbeans @JoinColoumns 错误

java - 将 xml 模式导入 postgres 以自动创建一个表,然后用 xml 文件填充它?

sql - GridView - 过程或函数指定的参数太多

c++ - 加减一组数字以达到一个值

c - 为什么 GDB 在行之间不可预测地跳转并将变量打印为 "<value optimized out>"?