我一次又一次被告知,优化查询的最佳方法是删除where子句中的函数。函数引起全表扫描。因此,我的问题是,考虑到这三个查询,为什么具有where子句(图C)中的功能的查询性能最好-快两倍以上?
图表A-with中的文本大写,因此where子句中没有函数,但仍将select子句中的where子句
spring.cloud.config.allowOverride=true
图表B-with中的文本大写,并尽可能过滤掉
With Code As (
Select owner,name,Upper(text) As text,line From all_source
)
select * from Code
Where text Like '%UPPER(%'
And owner='COMMISSIONS'
展示C-否with子句和where子句中的函数
With Code As (
Select owner,name,Upper(text) As text,line From all_source
Where owner='COMMISSIONS'
)
select * from Code
Where text Like '%UPPER(%'
答案 0 :(得分:1)
TL; DR -由于缓存,您的第三个查询可能运行最快。从性能的角度来看,它并不比其他两个更好或更差。但这是最简单的,它是您应该使用的一种。
为什么具有where子句(图C)中的功能的那个最好?
在Oracle的优化程序处理完所有查询之后,您的所有三个查询基本相同。如果第三个运行得更快,则可能是因为在ALL_SOURCE
视图下的表中存在索引,因为您指定了owner = 'COMMISSIONS'
。使用索引访问的索引块和表块有资格存储在块缓冲区高速缓存中。您的第三个查询将从前两个查询中受益,前两个查询已经读取并缓存了所需的一些数据。 (证明?再次运行第一个查询)。
更重要的是:“从WHERE子句中删除函数”不是描述常规建议的确切方法。
现有的常规建议可以帮助新的Oracle开发人员了解索引的局限性。
取出您最喜欢的技术参考,然后转到背面的索引。使用它查找以“ so”开头的主题和每个主题的页码。索引非常有帮助,对吧?现在,使用索引查找以“ r”结尾的主题和页码(类似的Oracle函数为“ substr(topic,-1)='r'”)。该索引不再有用。 Oracle索引具有相同的局限性。
现在,您的技术参考文献的作者可以在背面创建第二个索引,该索引根据上一个字母组织所有主题。如果他们这样做了,那么该索引对于我上面给您的第二个练习非常有用。同样,Oracle可以创建“基于函数”的索引来回答基于该函数的查询(例如substr(topic,-1))。
但是,在没有预先存在的基于函数的索引的情况下,针对列函数的查询过滤不会从该列的索引中受益。这是一个概括(有一些例外,例如“覆盖”索引),但这是一个很好的概括。
但是,这些都与WHERE
子句中的函数无关。您的所有三个查询都将阻止Oracle使用TEXT
上的索引。通过使用视图或WHERE
子句来执行“ WITH
子句中的函数”来避免执行Oracle函数的局限性。
(此外:您在LIKE
列上使用TEXT
运算符的事实是索引无济于事的另一个重要原因-请参见Oracle Text功能以获取诸如{{ 1}}运算符)。