1

假设我有一个包含 200000 条记录的 Person 表,它的 GUID 主键上有一个聚集索引。此 GUID 是使用 SQL Server (2008 R2) 提供的 NEWSEQUENTIALID() 构造生成的。此外,LastName (varchar(256)) 列上有一个常规索引。

对于每条记录,我生成了一个唯一的名称(Lastname_1 到 Lastname_200000),现在我正在处理一些查询,并且发现我的条件越严格,SQL Server 返回实际结果的速度就越慢。而且这种性能影响是相当严重的。

例如:

SELECT * FROM Person WHERE Lastname LIKE '%Lastname_123456%'

比慢得多

SELECT * FROM Person WHERE Lastname LIKE '%Lastname_123%'

响应时间是通过设置以下统计信息来衡量的:

SET STATISTICS TIME ON

我可以想象这是造成的

1)由于 LIKE 子句本身,由于它以 % 开头,因此无法在该特定列上使用 inde,

2) SQL 不得不更多地考虑我的“更大的问题”。

这有什么道理吗?有什么办法可以避免这种情况吗?

编辑:要为这个问题添加一些上下文,这是“免费搜索”用例的一部分。当用户输入完整的姓氏时,我非常希望系统能够快速运行。

我应该如何使这些案例执行?我应该避免 '%xxx%' 构造而去 'xxx%' 之类的构造吗?这确实增加了很多速度,但代价是用户的一些灵活性......

4

2 回答 2

1

你是正确的数字 2,因为第二个 LIKE 必须匹配字符串中的更多字符,当 SQL 找到一个不匹配的字符时停止搜索,因此它需要更少的字符串匹配迭代来找到一个更小的搜索字符串 - 即使你获得更多结果。

至于#1 - 如果可能,SQL 将使用索引进行 LIKE,但可能会进行索引扫描(可能是聚集索引),因为使用通配符无法进行查找。它还取决于索引中包含的内容 - 由于您正在选择所有列,因此很可能正在发生表扫描,因为您“可以”使用的索引没有覆盖您的查询(除非它使用聚集索引)

检查你的执行计划——你可能会看到一个表扫描

于 2012-06-25T10:43:40.483 回答
0

通常,SQL Server 不使用 LIKE 上的索引。

这篇文章可以帮助指导你

于 2012-06-25T11:17:25.943 回答