避免将函数应用于索引列

时间:2019-04-18 20:34:27

标签: sql oracle performance query-optimization

我需要过滤出超过一定长度的数据,但是包含数据的列是索引列。如果我对列应用函数,则会失去索引的好处。

我不是数据库管理员,因此无法创建新索引或更改列。 我宁愿不删除事实之后的数据。

我知道几种过滤列的方法,但是所有方法都会使用某种功能。

select
table.name
from 
table
where
length(table.name)>12
;

字段table.name不能为空。

2 个答案:

答案 0 :(得分:1)

如果该列不为空,则Oracle可以使用全索引扫描来回答查询。它将需要读取索引中的每一行,以便仅查找长度大于12的那些行。如果索引小于表,则这比完整扫描要快。

您仅选择索引列,因此Oracle无需访问表,但可以完全从索引获取结果。如果要选择其他列,则该索引中将没有Oracle。Oracle还需要读取首先位于索引中的表行。

没有添加合适的索引或更改数据库架构的方法是无法解决的。

答案 1 :(得分:1)

  

如果我对列应用函数,则会失去索引的作用。

啊,但是索引的好处是什么?

考虑这两个值:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ

它们都超过12个字符吗?是。它们是否可能在索引中相邻?当然不是。因此,Oracle使用索引查找那些值的唯一方法是对索引执行完全快速扫描并评估每个条目的长度。现在Oracle可以做到,但这值得吗?

您发布的查询仅选择name。在注释中,您说name不可为空。在这种情况下,Oracle可以使用索引,因为无需读取表记录:索引具有足够的信息可以满足查询的需要。

但是。

在该评论中,您还说:

  

查询不是那么简单

如果您的实际查询在投影中包括其他列,则数据库确实必须访问表以获取这些值。此时,索引读取的经验法则开始了:如果查询的结果集大于表中所有行的1-2%,则执行全表扫描比使用索引更有效。因此,表中的记录数变得很重要,尤其是length(name) > 12中记录的比例。如果99%的记录都使用短名称,则对索引进行全快速扫描可能仍然更加有效。但是,如果仅使用90%的索引,可能会对性能造成致命影响。

同样,如果您的实际查询在WHERE子句中应用了其他条件,则执行全表扫描(因为数据库需要读取记录以评估那些过滤器)可能会更有效地使用不同的索引(如果有)是合适的。

因此,尽管索引对于您在问题中发布的玩具查询很有用,但它可能对您的实际查询没有帮助,实际上可能导致访问路径欠佳。

  

是否取决于查询的复杂性?

是的。答案总是,这取决于。这就是为什么数据库调优专业人士可以收取昂贵的顾问费。如果您没有提供完整的查询,我们可以做的最好的就是point you at this post which explains to ask performance tuning questions,并祝您好运。