具有前导通配符的参数化查询的SQL Server性能

Ste*_*sky 6 sql-server parameterized sql-server-2008

我有一个SQL 2008 R2数据库,其中一个表中有大约200万行,并且在使用参数化SQL时,我在努力处理特定查询的性能.

在表格中,有一个包含名称的字段:

[PatientsName] nvarchar NULL,

该领域还有一个简单的索引:


CREATE NONCLUSTERED INDEX [IX_Study_PatientsName] ON [dbo].[Study] 
(
    [PatientsName] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, FILLFACTOR = 90) ON [INDEXES]
GO
Run Code Online (Sandbox Code Playgroud)

当我在管理工作室中执行此查询时,执行大约需要4秒:


declare @StudyPatientsName nvarchar(64)
set @StudyPatientsName= '%Jones%'

SELECT COUNT(*) FROM Study WHERE Study.PatientsName like @StudyPatientsName

但是,当我执行此查询时:


SELECT COUNT(*) FROM Study WHERE Study.PatientsName like '%Jones%'

执行需要花费半秒多一点的时间.

查看执行计划,没有参数化的查询使用上面提到的索引进行索引扫描,这显然是有效的.参数化查询使用索引,但对索引执行范围搜索.

部分问题是拥有领先的通配符.当我删除前导通配符时,两个查询都会在几分之一秒内返回.不幸的是,我确实需要支持领先的通配符.

我们有一个自行开发的ORM,可以在问题产生的地方进行参数化查询.这些查询是基于用户的输入完成的,因此参数化查询有助于避免像SQL注入攻击这样的事情.我想知道是否有办法制作参数化查询功能以及非参数化查询?

我做了一些研究,研究了不同的方法来给查询优化器提供提示,试图强制优化器重做每个查询的查询计划,但还没有找到任何改进性能的方法.我试过这个查询:


SELECT COUNT(*) FROM Study WHERE Study.PatientsName like @StudyPatientsName
OPTION ( OPTIMIZE FOR (@StudyPatientsName = '%Jones%'))
Run Code Online (Sandbox Code Playgroud)

这个问题中被提到作为解决方案,但它没有任何区别.

任何帮助,将不胜感激.

Mar*_*ith 4

看来您想强制扫描。有一个FORCESEEK提示,但我看不到任何类似的FORCESCAN提示。不过这应该可以做到。

SELECT COUNT(*) 
FROM Study 
WHERE Study.PatientsName + '' like @StudyPatientsName
Run Code Online (Sandbox Code Playgroud)

尽管也许您可以对您的数据尝试以下操作,看看效果如何。

SELECT COUNT(*) 
FROM Study 
WHERE Study.PatientsName  like @StudyPatientsName
option (recompile)
Run Code Online (Sandbox Code Playgroud)