避免将函数应用于索引列



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

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

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

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

字段table.name不可为空。

如果我将函数应用于列,我将失去索引的好处。

啊,但是指数有什么好处?

请考虑以下两个值:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ

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

您发布的查询仅选择name.在评论中,您说name不可为空。在这种情况下,Oracle 使用索引会很有效,因为不需要读取表记录:索引有足够的信息来满足查询。

然而。

在那条评论中,您还说:

查询没那么简单

如果实际查询包含投影中的其他列,则数据库必须访问该表才能获取这些值。此时,索引读取的经验法则开始发挥作用:如果查询的结果集大于表中所有行的 1-2%,则执行全表扫描比使用索引更有效。因此,表中的记录数变得相关,尤其是length(name) > 12的记录比例。如果 99% 的记录具有短名称,则完全快速扫描索引可能仍然更有效。但如果只有90%的人使用该指数,那么对性能可能是致命的。

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

因此,虽然索引对您发布的问题中的玩具查询很有用,但它可能对您的实际查询没有帮助,并且确实可能导致次优访问路径。

是否根据查询复杂性逐案处理?

是的。答案总是,这取决于。这就是为什么数据库调优专业人员可以收取他们所做的巨额咨询费。如果您不提供整个查询,我们能做的最好的事情就是将您指向这篇文章,该帖子解释了提出性能调整问题并祝您好运。

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

您只需选择索引列,因此 Oracle 不需要访问该表,但可以完全从索引中获取结果。 如果要选择其他列,该索引中没有 Oracle 还需要读取首先在索引中找到该行的表行。

如果不添加更合适的索引或以其他方式更改数据库架构,就无法解决此问题。

最新更新