存储过程比SSMS中的查询慢

时间:2013-11-22 13:44:01

标签: sql sql-server stored-procedures

更新:我已解决了问题,请参阅下面的解决方案。

我的存储过程比SQL查询慢。两者都在测试中直接在SSMS中执行。我需要反馈为什么以及如何解决。我可以看到查询在DB中使用了不同的非聚集索引,我不知道为什么。

存储过程:

exec sp_executesql N'SELECT TOP 25 
[data_unit_id], [creation_date], [name], [parent_data_unit_id], [data_unit_identity_unique_name], [receiving_flow_status], [sending_flow_status], [target_connector], [closed], [nummer], [date], [receiver_endpoint], [receiver_name], [reference_document_id], [sender_endpoint], [sender_id], [sender_name], [receiver_email], [creditnote_total], [tax_number], [order_reference], [type], [responce_text] 
 FROM metadata 
 WHERE 
   (  (  creation_date >= @1 )  AND  (  closed = @2 AND  nummer LIKE @3 )  AND  creation_date <= @4 AND  creation_date >= @5 )  
 ORDER BY [creation_date] DESC 

',N'@1 bigint,@2 nvarchar(5),@3 nvarchar(4),@4 bigint,@5 bigint',@1=130288572000000000,@2=N'False',@3=N'%156',@4=130295155780753712,@5=130289107780753712

SQL查询:

SELECT TOP 25 
     [data_unit_id], [creation_date], [name], [parent_data_unit_id],   
     [data_unit_identity_unique_name], [receiving_flow_status], [sending_flow_status], 
     [target_connector], [closed], [nummer], [date], [receiver_endpoint], [receiver_name], 
     [reference_document_id], [sender_endpoint], [sender_id], [sender_name], [receiver_email], 
     [creditnote_total], [tax_number], [order_reference], [type], [responce_text] 
FROM metadata 
WHERE 
   ((creation_date >= 130288572000000000)
    AND (closed = 'False' AND nummer LIKE '%156')  
    AND creation_date <= 130295155780753712 
    AND creation_date >= 130289107780753712 
   )  
ORDER BY 
   [creation_date] DESC 

更新: 如果我将@ 3 = N'%678'更改为@ 3 = N'%78'并将此变量的数据类型大小更改为nvarchar(3),则搜索从> 30秒变为200毫秒。 DB中nummer的数据类型为nvarchar(300)。这是SQL:

exec sp_executesql N'SELECT TOP 25 
    [data_unit_id], [creation_date], [name], [parent_data_unit_id], [data_unit_identity_unique_name], [receiving_flow_status], [sending_flow_status], [target_connector], [closed], [nummer], [date], [receiver_endpoint], [receiver_name], [reference_document_id], [sender_endpoint], [sender_id], [sender_name], [receiver_email], [creditnote_total], [tax_number], [order_reference], [type], [responce_text] 
     FROM metadata 
     WHERE 
       (  (  creation_date >= @1 )  AND  (  closed = @2 AND  nummer LIKE @3 )  AND  creation_date <= @4 AND  creation_date >= @5 )  
     ORDER BY [creation_date] DESC 

    ',N'@1 bigint,@2 nvarchar(5),@3 nvarchar(3),@4 bigint,@5 bigint',@1=130288572000000000,@2=N'False',@3=N'%56',@4=130295155780753712,@5=130289107780753712

解决方案: 这是类似/冲突的索引的问题,解决方案是删除其中一个。我是如何解决的: 使用SSMS中的SQL查询可以查看执行计划以及使用的索引对象。缓慢的SP是否相同? 如果他们使用不同的索引,请尝试在SP中使用快速索引。示例如何强制使用特定索引:

SELECT *
FROM MyTable WITH (INDEX(IndexName))
WHERE MyIndexedColumn = 0

2 个答案:

答案 0 :(得分:3)

SQL可能会出现一个常被称为参数嗅探的问题。对此的一个解决方案是在过程中声明变量并将参数分配给它们:(我不知道为什么会这样,但我过去在这个方法上取得了一些成功。)

CREATE PROCEDURE [dbo].[SprocName]
@Parameter1     DATETIME,
@Parameter2         VARCHAR(30), .......

DECLARE @1 DATETIME
SET @1 = @Parameter1

DECLARE @2 VARCHAR(30)
SET @2 = @Parameter2

另一种方法是在查询结束时使用OPTION (RECOMPILE)

但是,这些并不适用于所有情况。如果它们不起作用,那么您最好查看执行计划并优化您的程序。


这是一个很好的读取参数嗅探。

http://www.brentozar.com/archive/2013/06/the-elephant-and-the-mouse-or-parameter-sniffing-in-sql-server/

答案 1 :(得分:2)

<强>解决方案: 这是类似/冲突的索引的问题,解决方案是删除其中一个。我是如何解决的: 使用SSMS中的SQL查询可以查看执行计划以及使用的索引对象。缓慢的SP是否相同? 如果他们使用不同的索引,请尝试在SP中使用快速索引。示例如何强制使用特定索引:

SELECT *
FROM MyTable WITH (INDEX(IndexName))
WHERE MyIndexedColumn = 0