【问题标题】:Query with LIKE, increasingly slow with a smaller resultset使用 LIKE 查询,结果集越小越慢
【发布时间】:2012-06-25 10:38:10
【问题描述】:

假设我有一个包含 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%' 之类的构造吗?这确实增加了很多速度,但代价是用户的一些灵活性......

【问题讨论】:

  • 请显示执行计划。也许不同的选择性估计意味着一个执行聚集索引扫描,另一个执行 NCI 扫描和键查找。
  • 你所有的名字都是按顺序生成的吗?
  • 就像在许多数据库中一样,是的。前缀或后缀可以使用索引,但不能使用那种索引,因为数据库只是不知道范围并且不能将其应用于索引。而且那是一根相当长的绳子,所以它也会在那里施加压力
  • @martin,执行计划看起来几乎一样。当我只使用“姓氏_”进行搜索时,会执行聚集索引扫描,速度非常快。当我将其更改为“Lastname_123”之类的内容时,将执行索引扫描 (52%) 和键查找 (42%)> DavidBrabant:是的,Lastname_1 到 Lastname_200000
  • @fuaaark - SET STATISTICS TIME ON 的完整输出包括 CPU 时间是多少?

标签: sql performance sql-server-2008-r2 sql-like


【解决方案1】:

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

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

检查您的执行计划 - 您可能会看到表扫描

【讨论】:

    【解决方案2】:

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

    This文章可以帮你指导

    【讨论】:

    • 正确,但没有回答关于两个特定查询性能的问题。
    猜你喜欢
    • 2012-07-25
    • 2023-03-12
    • 1970-01-01
    • 2022-01-12
    • 1970-01-01
    • 1970-01-01
    • 2016-03-03
    • 1970-01-01
    • 2020-12-29
    相关资源
    最近更新 更多