SQL'喜欢'vs'='表现

mic*_*ica 75 sql performance

这个问题 围绕着我想知道的问题,但答案并没有完全解决它.

看起来通常使用通配符时'='比'喜欢'更快.这似乎是传统智慧.但是,假设我有一个包含有限数量的不同固定,硬编码,varchar标识符的列,并且我想选择与其中一个匹配的所有行:

select * from table where value like 'abc%'
Run Code Online (Sandbox Code Playgroud)

select * from table where value = 'abcdefghijklmn'
Run Code Online (Sandbox Code Playgroud)

'like'应该只需要测试前三个字符以找到匹配,而'='必须比较整个字符串.在这种情况下,在我看来,"喜欢"会有优势,所有其他条件都相同.

这是一个普遍的学术问题,所以无论哪个DB都无关紧要,但它使用的是SQL Server 2005.

Bon*_*nyT 58

http://myitforum.com/cs2/blogs/jnelson/archive/2007/11/16/108354.aspx

从那里引用:

使用LIKE进行索引使用的规则很像:

  • 如果您的过滤条件使用equals =并且字段已编入索引,则很可能会使用INDEX/CLUSTERED INDEX SEEK

  • 如果您的过滤条件使用LIKE,但没有通配符(例如,如果您在Web报表中有一个参数,但COULD有%,而您使用完整的字符串),那么使用索引的可能性大约为#1.增加的成本几乎为零.

  • 如果您的过滤条件使用LIKE,但在开头使用通配符(如在Name0 LIKE'%UTER'中),则使用索引的可能性要小得多,但它仍然可能至少在完整或部分范围内执行INDEX SCAN指数.

  • 但是,如果你的过滤条件使用LIKE,但是以STRING FIRST开头并且在那之后某处有通配符(如在Name0 LIKE'COMP%ER'中),那么SQL可能只是使用INDEX SEEK来快速查找具有相同的行起始字符,然后查看这些行以获得完全匹配.

(还要记住,SQL引擎仍然可能不会按照您期望的方式使用索引,具体取决于查询中的其他内容以及您要加入的表.SQL引擎保留重写您的权限的权利.稍微查询以获得它认为最有效的方式获取数据,并且可能包括INDEX SCAN而不是INDEX SEEK)


JNK*_*JNK 39

这是一个可衡量的差异.

运行以下命令:

Create Table #TempTester (id int, col1 varchar(20), value varchar(20))
go

INSERT INTO #TempTester (id, col1, value)
VALUES
(1, 'this is #1', 'abcdefghij')
GO

INSERT INTO #TempTester (id, col1, value)
VALUES
(2, 'this is #2', 'foob'),
(3, 'this is #3', 'abdefghic'),
(4, 'this is #4', 'other'),
(5, 'this is #5', 'zyx'),
(6, 'this is #6', 'zyx'),
(7, 'this is #7', 'zyx'),
(8, 'this is #8', 'klm'),
(9, 'this is #9', 'klm'),
(10, 'this is #10', 'zyx')
GO 10000

CREATE CLUSTERED INDEX ixId ON #TempTester(id)CREATE CLUSTERED INDEX ixId ON #TempTester(id)

CREATE NONCLUSTERED INDEX ixTesting ON #TempTester(value)
Run Code Online (Sandbox Code Playgroud)

然后:

SET SHOWPLAN_XML ON

然后:

SELECT * FROM #TempTester WHERE value LIKE 'abc%'

SELECT * FROM #TempTester WHERE value = 'abcdefghij'
Run Code Online (Sandbox Code Playgroud)

由此产生的执行计划向您显示第一次操作(LIKE比较)的成本比比较成本高出约10倍=.

如果您可以使用=比较,请这样做.

  • +1实际测试它.仅仅看一下展会计划可能并不能说明整个故事.我将进行一些自己的测试,如果发现任何意外情况,我会告诉所有人. (2认同)

Bli*_*ndy 13

您还应该记住,在使用时like,一些sql flavor会忽略索引,这会破坏性能.如果您不像您的示例那样使用"开头"模式,则尤其如此.

您应该真正查看查询的执行计划,看看它在做什么,尽可能少地猜测.

这就是说,"以"开头"模式可以在sql server中进行优化.它使用表的索引.出于这个原因,EF 4.0切换到likeStartsWith.

  • 当类似模式是查询的一部分并且通配符正在跟踪时,没有任何关系数据库可以忽略索引.如果您绑定值并且数据库支持与查询准备分开的绑定,那么这可能是一个不同的故事. (2认同)

Wil*_*l A 7

如果value未编入索引,则两者都会导致表扫描.这种情况下的性能差异可以忽略不计.

如果value被索引,正如Daniel在他的评论中指出的那样,=将导致索引查找,即O(log N)性能.该LIKE会(最有可能的-这取决于它是如何选择性的)结果在指数的部分扫描>= 'abc'< 'abd'这将需要比付出更多的努力=.

请注意,我在这里谈论SQL Server - 并非所有DBMS都会对LIKE很好.


Ari*_*ris 6

使用 mysql 5.5 的个人示例:我在 2 个表之间进行了内部连接,其中一个是 300 万行,另一个是 1 万行。

在索引上使用类似如下(无通配符)时,大约需要 30 秒:

where login like '12345678'
Run Code Online (Sandbox Code Playgroud)

使用“解释”我得到:

在此处输入图片说明

在同一个查询上使用 '=' 时,大约需要 0.1 秒:

where login ='12345678'
Run Code Online (Sandbox Code Playgroud)

使用“解释”我得到:

在此处输入图片说明

如您所见,like完全取消了索引查找,因此查询花费了 300 倍以上的时间。


Rem*_*anu 5

你问的是错误的问题.在数据库中并不重要的是运算符性能,始终是表达式的SARGability,以及整体查询的可覆盖性.运营商本身的表现在很大程度上是无关紧要的

那么,SARGability 如何做LIKE=比较呢?LIKE当与不以常量开头的表达式(例如,在使用时LIKE '%something')一起使用时,根据定义非SARGabale.但这是做成=还是LIKE 'something%'SARGable?否.与任何有关SQL性能的问题一样,答案不在于文本查询,而在于部署了架构.如果存在满足它们的索引,这些表达式可能是SARGable .

所以,说实话,=和之间存在细微差别LIKE.但是询问一个操作员或其他操作员在SQL中是否"更快"就像问"什么更快,一辆红色汽车还是一辆蓝色汽车?".您应该询问有关引擎大小和车辆重量的问题,而不是关于颜色...要解决有关优化关系表的问题,要查看的地方是您的索引和WHERE子句中的表达式(以及其他子句,但通常从WHERE开始).


小智 5

=LIKE即使没有通配符,也比 快得多。我在MySQL上进行了测试,数据为11GB,记录超过1亿条,f_time列已建立索引。

SELECT * FROM XXXXX WHERE f_time = '1621442261' 
#took 0.00sec and return 330 records

SELECT * FROM XXXXX WHERE f_time LIKE '1621442261' 
#took 44.71sec and return 330 records
Run Code Online (Sandbox Code Playgroud)