类似查询的 oracle 索引
Posted
技术标签:
【中文标题】类似查询的 oracle 索引【英文标题】:oracle index for like query 【发布时间】:2017-01-18 20:16:27 【问题描述】:我在这里与客户愚蠢/固执的案件作斗争。我们有一个应用程序可以通过各种标准查找零售购物者。我们看到的最常见的变化是(部分)姓氏和(部分)邮政编码的某种组合。
当他们输入完整的邮政编码时,效果非常好。问题是他们有时会选择有效地输入邮政编码,例如'3%'
。
有什么奇迹可以克服我们客户的愚蠢吗?
ETA:这个特殊的操作涉及两个表:客户和地址。我是一名参与支持此应用程序的 DBA,而不是在开发方面。我没有能力更改代码(尽管我可以就此提出建议),但我在改进索引方面还有一些余地。
Customers 有 2200 万行;地址有 2300 万个。
“愚蠢”可能是一个刺耳的词,但我不明白为什么您会尝试通过诸如“3%”之类的邮政编码来查找客户。我的意思是,输入他们的完整邮政编码需要多少努力?
【问题讨论】:
客户傻了,有什么影响?申请中断?表现不佳?还有什么? 根据你的信仰,你可以祈祷,也可以认为奇迹不存在。此外,到目前为止,您所展示的内容并不能证明您的客户是愚蠢的,这是无可置疑的。最好把它排除在外。现在:如果您有适当的索引,请确保统计数据是最新的。此外,邮政编码的分布可能会出现偏差;您可能需要使用直方图。 对了,再看看你的标题:如果你有一个关于邮政编码的索引,优化器可以在带有like '3%'
等条件的查询中使用它——只要通配符在结尾。它无法将它用于诸如like '%3'
之类的条件 - 但您的情况不是。所以问题不在于索引;问题可能出在统计数据上,也可能是邮政编码分布极不均匀。
Oracle query using 'like' on indexed number column, poor performance的可能重复
@BobC:显然 web 层有 20 秒的超时时间,有时当条件不够选择性时,应用程序会超时而不是返回任何内容。
【参考方案1】:
困难在于
WHERE postal_code LIKE '3%'
AND last_name LIKE 'MC%'
通常只能从postal_code
上的索引或last_name
上的索引中受益。两者上的复合索引都没有帮助(除了前导列)。
将此视为一种可能的解决方案(假设您的表名是 RETAIL_RECORDS
:
alter table retail_records
add postal_code_first_1 VARCHAR2(2)
GENERATED ALWAYS AS ( substr(postal_code, 1,1) );
alter table retail_records
add last_name_first_1 VARCHAR2(2)
GENERATED ALWAYS AS ( substr(last_name, 1,1) );
create index retail_records_n1
on retail_records ( postal_code_first_1, last_name_first_1, postal_code );
create index retail_records_n2
on retail_records ( postal_code_first_1, last_name_first_1, last_name );
然后,在为您提供 postal_code 和/或 last_name 条件的情况下,还要在相应的 ...first_1
列中包含条件。
所以,
WHERE postal_code LIKE :p1
AND last_name LIKE :p2
AND postal_code_first_1 = SUBSTR(:p1,1,1)
AND last_name_first_2 = SUBSTR(:p2,1,2)
这将允许 Oracle 平均搜索 1/260 的数据。 (邮政编码为 1/10,首字母为 1/26)。好吧,以“M”开头的姓氏比以“Z”开头的姓氏多得多,所以这有点大方。但即使是高频组合(比如postal_code like '1%' and last_name like 'M%'
),它仍然不需要查看超过 1% 的行。
我预计,一旦您看到 Oracle 的基于成本的优化器实际在做什么,您就必须对此进行调整,但我认为这个想法的基本原则应该是合理的。
【讨论】:
我显然没有问得足够清楚。涉及两个表,客户和地址。问题是像“3%”这样的邮政编码搜索将返回来自地址的 300 万行,这些行需要针对某些客户子集进行连接……所有这些都取决于最终用户的心血来潮。 呃。这改变了一切。我会考虑将一些数据非规范化到其中一个表中。否则,表之间连接的FAST REFRESH ON COMMIT
物化视图将是一种危险但合理的方法。非常好的文章在这里:orastory.wordpress.com/2014/11/27/….以上是关于类似查询的 oracle 索引的主要内容,如果未能解决你的问题,请参考以下文章
oracle有没有类似sqlserver中include语句的覆盖索引?