SQL'就像'vs'='的性能

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

一般来说,当使用通配符时,'='比'like'更快。 这似乎是传统的看法。 但是,假设我有一个列包含有限数量的不同的固定,硬编码,varchar标识符,我想select匹配其中之一的所有行:

select * from table where value like 'abc%' 

 select * from table where value = 'abcdefghijklmn' 

“像”应该只需要testing前三个字符来查找匹配,而“=”必须比较整个string。 在这种情况下,在我看来,“喜欢”会有一个优势,其他所有的东西都是平等的。

这是作为一个普通的学术问题,所以不应该在哪个数据库中,但它是使用SQL Server 2005产生的。

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

从那里引用:

LIKE的索引使用规则大致如下:

  • 如果你的filter标准使用equals =并且该字段被索引,那么很有可能它将使用INDEX / CLUSTERED INDEX SEEK

  • 如果你的过滤标准使用了LIKE,没有通配符(就像你在Web报表中有一个参数可以有一个%,但是你使用完整的string),那么使用这个索引大概和#1一样。 增加的成本几乎没有。

  • 如果你的过滤标准使用了LIKE,但是在开始时使用了一个通配符(如Name0 LIKE'UTER'),那么使用该索引的可能性要小得多,但是它仍然可以至less在一个完整的或部分的范围内执行INDEX SCAN该指数。

  • 然而,如果你的过滤标准使用LIKE,但是以STRING FIRST开头,并且在后面的通配符(如Name0 LIKE'COMP%ER')那么SQL可能只使用INDEX SEEK来快速查找具有相同的第一行开始字符,然后通过这些行查看完全匹配。

(请记住,SQL引擎仍然可能不会按照您期望的方式使用索引,具体取决于您的查询中正在进行的操作以及要join的表。SQL引擎保留重写您的权利查询一点,以它认为是最有效的方式获取数据,可能包括INDEX SCAN而不是INDEX SEEK)

这是一个可衡量的差异。

运行以下命令:

 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倍左右。

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

你也应该记住,使用like ,一些SQL风格将忽略索引,这将杀死性能。 如果你不像你的例子那样使用“开始”模式,情况尤其如此。

你应该真的看看查询的执行计划,看看它在做什么,尽可能less的猜测。

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

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

如果value被索引,Daniel在他的评论中指出, =会导致索引查找,这是O(log N)性能。 LIKE将(很可能 – 取决于它的select性)导致对索引>= 'abc'< 'abd'的部分扫描,这将需要比=更多的努力。

请注意,我在这里说的是SQL Server,并不是所有的DBMS都会喜欢LIKE。

你问的是错误的问题。 在数据库中不是操作员performance的重要问题,总是expression式的合理性,以及总体查询的可维护性 。 运营商本身的绩效在很大程度上是无关紧要的。

那么,如何比较SARG可比性? LIKE ,当与不以常量开始的expression式(例如,当使用LIKE '%something' )一起使用时,定义为非SARGabale。 但是这样做=或者LIKE 'something%' SARGable? 不。与任何有关SQL性能的问题一样,答案不在于查询文本,而是在部署模式。 如果一个索引存在以满足它们,这些expression式可能是SARGable。

所以,真相被告知, =LIKE之间有小的差异。 但是,询问一个操作员还是其他操作员在SQL中是否“更快”,就像是问'快点什么,一辆红色的车还是一辆蓝色的车?'。 你应该问一些关于引擎大小和车辆重量的问题,而不是关于颜色……要处理有关优化关系表的问题,需要查看的地方是WHERE子句中的索引expression式 (以及其他子句,但通常从WHERE开始)。

一个使用mysql 5.5的个人示例:我有两个表之间的内部连接,300万行之一和10000行之一。

在下面的索引上使用类似的符号(没有通配符)时,大约需要30秒:

 where login like '12345678' 

使用'解释'我得到:

在这里输入图像描述

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

 where login ='600009' 

使用'解释'我得到:

在这里输入图像描述

正如你所看到的like ,索引查找完全取消了,所以查询花费了300多倍的时间。

也许你正在寻找全文search 。

与全文search相比,LIKE Transact-SQL谓词仅适用于字符模式。 此外,您不能使用LIKE谓词来查询格式化的二进制数据。 此外,针对大量非结构化文本数据的LIKE查询比针对相同数据的等效全文查询慢得多 。 针对数百万行文本数据的LIKE查询可能需要几分钟才能返回; 而对于相同的数据,全文查询可能只需要几秒或更less的时间,具体取决于返回的行数。

首先,

他们并不总是平等的

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

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

如果你正在处理string和只有字符variables,那么你可以谈论性能。 但是不要使用like和“=”作为一般可互换的。

正如你在许多post(以上和其他问题)中看到的那样,在相等的情况下,由于模式匹配(整理)