sql - 为什么根据此条件更改 where 子句会如此大幅度地减少执行时间?

标签 sql oracle t-sql oracle11g

今天我遇到了 SQL 语句的问题,我可以通过添加其他条件来修复该问题,但我真的想知道为什么我的更改解决了该问题。

问题查询:

SELECT *
FROM
  (SELECT ah.*,
    com.location,
    ha.customer_number,
    d.name applicance_NAME,
    house.name house_NAME,
    dr.name RULE_NAME
FROM actionhistory ah
INNER JOIN community com
ON (t.city_id = com.city_id)
INNER JOIN house_address ha
ON (t.applicance_id   = ha.applicance_id
AND ha.status_cd = 'ACTIVE')
INNER JOIN applicance d
ON (t.applicance_id = d.applicance_id)
INNER JOIN house house
ON (house.house_id = t.house_id)
LEFT JOIN the_rule tr
ON (tr.the_rule_id = t.the_rule_id)
WHERE actionhistory_id    >= 'ACT100010000' 
ORDER BY actionhistory_id
)
WHERE rownum <= 30000;

“修复”

SELECT *
FROM
  (SELECT ah.*,
    com.location,
    ha.customer_number,
    d.name applicance_NAME,
    house.name house_NAME,
    dr.name RULE_NAME
FROM actionhistory ah
INNER JOIN community com
ON (t.city_id = com.city_id)
INNER JOIN house_address ha
ON (t.applicance_id   = ha.applicance_id
AND ha.status_cd = 'ACTIVE')
INNER JOIN applicance d
ON (t.applicance_id = d.applicance_id)
INNER JOIN house house
ON (house.house_id = t.house_id)
LEFT JOIN the_rule tr
ON (tr.the_rule_id = t.the_rule_id)
WHERE actionhistory_id    >= 'ACT100010000' and  actionhistory_id  <= 'ACT100030000'
ORDER BY actionhistory_id
)

所有 _id 列都是索引序列。 第一个查询的解释计划的成本为 372,第二个查询的解释计划成本为 14。它在 Oracle 11g 数据库上运行。

此外,如果where子句中的actionhistory_id小于ACT100000000,则原始查询立即返回。

最佳答案

这是因为 actionhistory_id 列上的索引造成的。

在第一个查询期间,Oracle 必须返回包含“ACT100010000”之后的记录索引的所有索引 block ,然后必须将索引与表匹配以获取所有记录,然后从表中提取 29999 条记录。结果集。

在第二个查询期间,Oracle 只需返回包含“ACT100010000”和“ACT100030000”之间记录的索引 block 。然后它从表中抓取索引 block 中表示的那些记录。与使用第一个查询相比,找到索引后抓取记录的步骤要少得多。

注意你的最后一行关于 id 是否小于 ACT100000000 - 在我看来,这些记录可能都在同一个内存块中(或在一组连续的 block 中)。

编辑:另请考虑贾斯汀所说的 - 我正在谈论实际性能,但他指出 id 作为 varchar 大大增加了潜在值(而不是数字),并且估计的计划可能会反射(reflect)的时间比实际时间更长,因为优化器在执行之前不知道完整的范围。为了进一步优化,考虑到他的观点,您可以在 id 列上放置一个基于函数的索引,或者可以将其设为组合键,其中 varchar 部分位于一列中,数字部分位于另一列中。

关于sql - 为什么根据此条件更改 where 子句会如此大幅度地减少执行时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9829638/

相关文章:

sql - T-SQL Order by 不适用于 MSSQL 中的 Cast

java - 具有行限制的 Oracle Select 查询

java - 如何使用Java调用Oracle数据库中IN和OUT参数的存储函数

java - 如何从 java 程序将当前日期插入 oracle 数据库?

sql-server - SSRS自定义排序一列ASC和DESC

sql - 如何使用 T-SQL 中的值列表更新表?

sql - 带有 ORDER 和 LIMIT 子句的极慢 PostgreSQL 查询

sql - 在这种情况下,在 SQL Server 中对三个 nchar 列进行索引的最有效方法是什么?

sql - 通过 IN SQL Server 查询仅查找单词中的大写字母

mysql - 为多个查询获取 rails ActiveRecord 而不是对象数组