SQL'喜欢'vs'='表现

时间:2011-05-26 16:55:36

标签: sql performance

This question 围绕着我想知道的事情,但答案并没有完全解决它。

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

select * from table where value like 'abc%'

select * from table where value = 'abcdefghijklmn'

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

这是一个普遍的学术问题,所以无论哪个数据库都不重要,但它是使用SQL Server 2005产生的。

9 个答案:

答案 0 :(得分:54)

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

从那里引用:

  

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

     
      
  • 如果您的过滤条件使用equals =   并且该字段被索引,然后是大多数   可能会使用INDEX / CLUSTERED   INDEX SEEK

  •   
  • 如果您的过滤条件使用LIKE,   没有通配符(如果你有一个   可能在Web报告中的参数   有%,但你改为使用完整   字符串),它与#1差不多   使用索引。成本增加   几乎没什么。

  •   
  • 如果您的过滤条件使用LIKE,但是   一开始就带有通配符(如   在Name0 LIKE'%UTER')它更少   可能会使用索引,但它仍然   至少可以执行INDEX扫描   索引的全部或部分范围。

  •   
  • 但是,如果您的过滤条件使用了   喜欢,但从STRING FIRST开始   并且在那之后的某处有通配符   (如在Name0 LIKE'COMP%ER'中),然后是SQL   可以快速使用INDEX SEEK   找到首先具有相同的行   开始字符,然后看   通过这些行进行完全匹配。

  •   
     

(还要记住,SQL引擎   仍然可能不会使用索引的方式   你期待,取决于什么   否则你的查询正在进行中   你加入的是什么表。该   SQL引擎保留权利   稍微重写你的查询以获得   数据以其认为最多的方式   高效,可能包括   INDEX SCAN而不是INDEX SEEK)

答案 1 :(得分:36)

这是一个可衡量的差异。

运行以下命令:

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)

然后:

SET SHOWPLAN_XML ON

然后:

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

SELECT * FROM #TempTester WHERE value = 'abcdefghij'

生成的执行计划向您显示第一项操作(LIKE比较)的成本约为 10倍=比较贵。

如果您可以使用=比较,请执行此操作。

答案 2 :(得分:13)

你还应该记住,当使用like时,一些sql风格会忽略索引,这会破坏性能。如果您不像示例那样使用“开头”模式,则尤其如此。

你应该真正查看查询的执行计划,看看它在做什么,尽量少猜。

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

答案 3 :(得分:7)

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

如果value被编入索引,正如Daniel在其评论中指出的那样,=将导致索引查找,即O(log N)性能。 LIKE(很可能 - 取决于它的选择性)会导致索引>= 'abc'< 'abd'的部分扫描,这需要比=更多的努力。

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

答案 4 :(得分:5)

你问的是错误的问题。在数据库中,重要的不是运算符性能,始终是表达式的SARGability和整个查询的coverability。运营商本身的表现在很大程度上是无关紧要的。

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

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

答案 5 :(得分:4)

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

在下面的索引上使用like(没有通配符)时,花了大约30秒:

where login like '12345678'

使用&#39;解释&#39;我明白了:

enter image description here

使用&#39; =&#39;在同一个查询中,花了大约0.1秒:

where login ='600009'

使用&#39;解释&#39;我明白了:

enter image description here

正如您所看到的,like完全取消了索引搜索,因此查询花费了300倍的时间。

答案 6 :(得分:0)

也许您正在关注Full Text Search

  

与全文搜索相比,LIKE Transact-SQL谓词可以使用   只有字符模式。此外,您不能使用LIKE谓词   查询格式化二进制数据此外,对一个大的LIKE查询   非结构化文本数据的数量远远低于等效数据   针对相同数据的全文查询。对数百万人的LIKE查询   文本数据行可能需要几分钟才能返回;而全文   对于相同的数据,查询只需几秒或更短时间,具体取决于   关于返回的行数。

答案 7 :(得分:0)

=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

答案 8 :(得分:-1)

首先,

他们并不总是平等

    select 'Hello' from dual where 'Hello  ' like 'Hello';

    select 'Hello' from dual where 'Hello  ' =  'Hello';

当事情并不总是平等的时候,谈论他们的表现并不相关。

如果您正在处理字符串而只处理char变量,那么您可以谈论性能。但是不要使用like和“=”作为一般可互换的。

正如你在许多帖子中看到的那样(上面和其他问题),如果它们相等,由于模式匹配(整理),类似的表现会慢一些