2017-02-21 69 views
0

我有一个大的Oracle表与索引DATE_TIME场:“DISCONNECT_DATE”如何使用Oracle索引字段的查询

当我使用下面的where子句我的查询运行速度快:

DISCONNECT_DATE > TO_DATE('01-DEC-2016', 'DD-MON-YYYY') AND 
DISCONNECT_DATE < TO_DATE('01-JAN-2017', 'DD-MON-YYYY') 

当我用下面的where子句我的查询运行(很)缓缓道:

extract(month from disconnect_date) = '12' and 
extract(year from disconnect_date) = '2016' 

他们都或多或少相当于他们的意图。为什么前者工作,后者不工作? (我不认为我在SQL SERVER这个问题)

(我用的PL SQL Developer来编写查询)

+0

我猜Oracle无法自动将您的第二个选项转换为第一个选项,因此它会进行全面扫描。这需要一个特殊情况来进行优化。 PS。除非你改变> => = –

+0

我很困惑。你是说在SQL Server中这两个版本运行速度非常快吗?我对SQL Server一无所知,但我会觉得非常惊讶。 (除非你已经在SQL Server中有基于函数的索引,就像Gordon在答案中所展示的那样)。 – mathguy

回答

4

的问题是使用索引。首先,所有功能都在“常量”一侧,而不是“列”一侧。因此,Oracle很容易看到可以应用索引。

虽然索引的逻辑不理解extract(),所以索引没有被使用。如果你想使用结构,你可以在函数调用创建一个索引:

create index idx_t_ddyear_ddmonth on t(extract(month from disconnect_date), extract(year from disconnect_date)); 

注:extract()没有返回一个数字的字符串,所以你应该摆脱单引号的。混合数据类型也会混淆优化器。

+0

你是什么意思是“常量”与“列”之间的差异。您是否有过一个例子,其中一方或另一方对Oracle产生了影响?我一直认为它没有任何区别。 –

+0

@WW - 左侧与右侧不一样;您可以交换条件,以便“列”引用位于操作符的右侧(也可以更改操作符,以便在需要时保持逻辑相同)。这是指直接或通过操作(如函数调用,这是此处的问题)来自列的数据,与非基于列的表达式进行比较。无论哪一方都在。 [阅读详情](https://docs.oracle.com/database/121/SQLRF/sql_elements002.htm#SQLRF00214),注意第二个项目符号点以及关于管理隐式数据类型转换的规则部分: –

+0

@WW - 请密切注意Gordon在最后一段中所说的内容(关于正确匹配表达式的数据类型)。他是100%正确的 - 我敢打赌,由于对数据类型的疏忽,因为使用围绕列值的函数(比如'extract()),所以更多的效率丢失了(全球所有查询运行在全球所有数据库上) '在你的例子中)。奖金++给戈登花时间表达这一点! – mathguy