【发布时间】: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