我有一个 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
当我在管理工作室中执行此查询时,执行大约需要 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%'))
在这个问题中提到了它作为解决方案,但它没有任何区别。
任何帮助,将不胜感激。