使用LIKE'string'vs ='string'对Oracle的性能有何影响?

时间:2020-03-06 14:43:57  来源:igfitidea点击:

SELECT * FROM SOME_TABLE WHERE SOME_FIELD LIKE '%some_value%';

比这慢

SELECT * FROM SOME_TABLE WHERE SOME_FIELD = 'some_value';

但是呢?

SELECT * FROM SOME_TABLE WHERE SOME_FIELD LIKE 'some_value';

我的测试表明第二个和第三个示例完全相同。如果是这样,我的问题是,为什么要使用" ="?

解决方案

签出两者的解释计划。它们生成相同的执行计划,因此对于数据库而言,它们是同一件事。

我们将使用=来测试是否相等,而不是相似性。如果我们也要控制比较值,那么差别不大。如果这是被用户提交,那么"苹果"和"苹果%"会给你很大的不同结果。

你试过了吗?测试是唯一确定的方法。

顺便说一句,这些语句中没有一个肯定会返回相同的行。试用:

insert into some_table (some_field) values ('some_value');
insert into some_table (some_fieled) values ('1some_value2');
insert into some_table (some_field) values ('some1value');

SELECT * FROM SOME_TABLE WHERE SOME_FIELD LIKE '%some_value%';

SELECT * FROM SOME_TABLE WHERE SOME_FIELD = 'some_value';

SELECT * FROM SOME_TABLE WHERE SOME_FIELD LIKE 'some_value';

为了清楚起见并避免出现细微的错误,除非我们需要通配符功能,否则最好不要使用LIKE。 (显然,在进行临时查询时,可能还可以。)

像"%WHATEVER%"一样,必须进行完整的索引扫描。

如果没有%,那么它就像一个等号。

如果%在一端,则索引可以是范围扫描。

我不确定优化器如何处理绑定字段。

使用绑定变量时,有一个明显的区别,绑定变量应该在Oracle中用于数据仓库或者其他批量数据操作以外的其他任何操作。

以以下情况为例:

SELECT * FROM SOME_TABLE WHERE SOME_FIELD LIKE :b1

Oracle在执行之前不知道:b1的值为'%some_value%'或者'some_value'等,因此它将根据启发式方法估计结果的基数,并提出一个合适的计划可能适合或者可能不适合:b的各种值,例如'%A','%','A'等。

对于相等谓词,类似的问题也可能适用,但是,例如,基于列统计信息或者唯一约束的存在,可能导致的基数范围更容易估计。

因此,就我个人而言,我不会开始使用LIKE来代替=。优化器有时很容易被愚弄。

If that's true, my question is, why
  ever use "=" ?

一个更好的问题:如果是这样,为什么要使用" LIKE"来测试是否相等?我们不必再按Shift键,那么阅读脚本的每个人都会感到困惑。

如果没有$%等字符,则like的形式是相同的,因此,发现它具有相同的成本并不奇怪。

我发现David Aldridge的答案很有趣,因为应用程序应该使用绑定变量。使用`%foobar'这样的索引,我们将无法利用索引的顺序。如果查询是预编译的,将导致更多的索引或者表完全扫描。

此外,我发现这样做很危险,因为它可能导致SQL注入和奇怪的错误(例如,如果有一个名为john的用户,黑客可以创建一个名为"'joh $'`"的用户并尝试登录)

为什么要冒险? ''='`更清晰,没有任何问题。