This question 围绕着我想知道的事情,但答案并没有完全解决它。
在使用通配符时,似乎一般'='比'like'快。这似乎是传统智慧。但是,假设我有一个包含有限数量的不同固定,硬编码,varchar标识符的列,并且我想选择与其中一个匹配的所有行:
select * from table where value like 'abc%'
和
select * from table where value = 'abcdefghijklmn'
'Like'应该只需要测试前三个字符以找到匹配,而'='必须比较整个字符串。在这种情况下,在我看来,“喜欢”会有优势,所有其他条件都相同。
这是一个普遍的学术问题,所以无论哪个数据库都不重要,但它是使用SQL Server 2005产生的。
答案 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切换到like
为StartsWith
。
答案 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;我明白了:
使用&#39; =&#39;在同一个查询中,花了大约0.1秒:
where login ='600009'
使用&#39;解释&#39;我明白了:
正如您所看到的,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和“=”作为一般可互换的。
正如你在许多帖子中看到的那样(上面和其他问题),如果它们相等,由于模式匹配(整理),类似的表现会慢一些