我有这个问题:
select top 100 id, email, amount from view_orders
where email LIKE '%test%' order by created_at desc
运行不到一秒钟。
现在我想参数化它:
declare @m nvarchar(200)
set @m = '%test%'
SELECT TOP 100 id, email, amount FROM view_orders
WHERE email LIKE @m ORDER BY created_at DESC
5分钟后,它仍在运行。对参数进行任何其他类型的测试(如果我将“like”替换为“=”),则会降低到第一个查询级别的性能。
我使用的是SQL Server 2008 R2。
我试过OPTION(RECOMPILE)
,它下降到6秒,但它仍然慢得多(非参数化查询是瞬时的)。因为这是我期望经常运行的查询,所以这是一个问题。
表的列是索引的,但视图不是,我不知道它是否会有所作为。
视图连接5个表:一个有3,154,333行(用户),一个有1,536,111行(订单),3个最多有几十行(订单类型等)。搜索在“用户”表(3M行)上完成。
硬编码值
参数:
我已使用SET STATISTICS IO ON
运行查询。结果如下(对不起,我不知道如何阅读):
硬编码值:
表'货币'。扫描计数1,逻辑读取201。
表'order_status'。扫描计数0,逻辑读取200。
表'付款'。扫描计数1,逻辑读取100。
表'礼物'。扫描计数202,逻辑读取404。
表'订单'。扫描计数95,逻辑读取683。
表'用户'。扫描计数1,逻辑读取7956。
参数:
表'货币'。扫描计数1,逻辑读取201。
表'order_status'。扫描计数1,逻辑读取201。
表'付款'。扫描计数1,逻辑读取100。
表'礼物'。扫描计数202,逻辑读取404。
表'用户'。扫描计数0,逻辑读取4353067。
表'订单'。扫描计数1,逻辑读取4357031。
此后我看到了“强制索引使用”提示:
SELECT TOP 100 id, email, amount
FROM view_orders with (nolock, index=ix_email)
WHERE email LIKE @m
ORDER BY created_at DESC
不确定它会起作用,我不再在这个地方工作了。
答案 0 :(得分:3)
这可能是一个参数嗅探问题。 更好的索引或全文搜索是可行的方法,但您可能能够获得可行的妥协。 尝试:
SELECT TOP 100 A, B, C FROM myview WHERE A LIKE '%' + @a + '%'
OPTION (OPTIMIZE FOR (@a = 'testvalue'));
(就像Sean Coetzee建议的那样,我不会在参数中传递通配符)
答案 1 :(得分:0)
向A列添加索引时,您将获胜。 有时索引建议可以由SQL Server管理工作室借用。粘贴查询并按“显示估计执行计划”按钮
答案 2 :(得分:0)
CREATE INDEX index_name ON myview (A);
CREATE INDEX index_name ON myview (B);
CREATE INDEX index_name ON myview (C);
declare @a nvarchar(200)
set @a = '%testvalue%'
SELECT TOP 100 A, B, C FROM myview WHERE A LIKE @a
答案 3 :(得分:0)
如果你尝试会发生什么:
set @a = 'test'
select top 100 A, B, C
from myview
where A like '%' + @a + '%'
我已尝试对某些虚拟数据进行测试,看起来可能更快。
答案 4 :(得分:0)
参数化版本的估计执行计划显然不正确。我不相信我已经看过两次100%估计费用的查询!因为成本应该总计100%。同样有趣的是,当你明显过滤用户桌上的某些东西时,它认为它需要从订单开始。
我将重建您在视图中引用的所有表的统计信息。
update statistics <tablename> with resample
为每个参与的表做其中一个。
您可以尝试直接运行sql(将粘贴视图主体复制到sql中)并参数化,而不是查看sql是否存在问题。
在一天结束时,即使你修好了它,它实际上只是一个止损距离。您有300万用户,每次运行查询时,sql必须通过所有300万条记录(在您的热门查询中进行75%扫描)才能找到所有可能的记录。获得的用户越多,查询得到的速度就越慢。非全文索引不能用于前面带有通配符的类似查询。
在这种情况下,您可以将sql索引视为书籍索引。您可以使用带有“部分”单词的书籍索引来快速找到任何内容吗?不,你必须扫描整个索引以找出所有可能性。
您应该在视图中考虑全文索引。