当我在存储过程中使用if else语句时,为什么查询需要更多时间来执行?

时间:2016-02-02 06:41:02

标签: sql sql-server sql-server-2012

我在我的存储过程中使用了以下查询。当我使用if else语句时,存储过程查询需要更多时间来执行。当我删除if else语句查询花费更少的时间来返回结果。

If @P_Make = 'ALL' Or IsNull(@P_Make, '') = ''
Begin
    Set @P_Make = '%';
End
Else
Begin
    Set @P_Make = @P_Make + '%';
End 
If @P_Model = 'ALL' Or IsNull(@P_Model, '') = ''
Begin
    Set @P_Model = '%';
End
Else
Begin
    Set @P_Model = @P_Model + '%';
End     
If @P_Location = 'ALL' Or IsNull(@P_Location, '') = ''
Begin
    Set @P_Location = '%';
End
Else
Begin
    Set @P_Location = @P_Location + '%';
End
If @P_City = 'ALL' Or IsNull(@P_City, '') = ''
Begin
    Set @P_City = '%';
End
Else
Begin
    Set @P_City = @P_City + '%';
End
If @P_Category = 'ALL' Or IsNull(@P_Category, '') = ''
Begin
    Set @P_Category = '%';
End
Else
Begin
   Set @P_Category = Case When @P_Category = 'Bikes & Scooters' Then '2W%'
                             When @P_Category = '3 Wheelers' Then '3W%'
                             When @P_Category = 'Cars & SUVs' Then '4W%'
                             When @P_Category = 'Trucks' Then 'CV%'
                             When @P_Category = 'Farm Equipments' Then 'FE%'
                             When @P_Category = 'Industrial Equipments' Then 'IE%'
                             When @P_Category = 'Construction Equipments' Then 'CE%'
                             Else @P_Category + '%'
                        End
    End
If @P_Service = 'ALL' Or IsNull(@P_Service, '') = ''
Begin
    Set @P_Service = ''
End

Select Count(C.Sal_Pk_Id) 
From dbo.Auction (NoLock) A
Inner Join dbo.PLACE (NoLock) B On A.Auc_Place_Fk_Id = B.Place_Pk_Id
Inner Join dbo.SALES_DETAILS (NoLock) C On A.Auc_Code = C.Sal_Auc_Code
Inner Join dbo.AUCTIONSERVICES (NoLock) D On C.Sal_Regno = D.Auc_Service_Regno And C.Sal_Auc_Code = D.Auc_Service_Auctioncode
Inner Join dbo.LOT (NoLock) E On C.Sal_Lot_No = E.Lot_Lot_No And C.Sal_Auc_Code = E.Lot_Auc_Code 
Inner Join dbo.INVENTORY (NoLock) F On C.Sal_Regno = F.Inv_H_Reg_No
Where C.[Status] = 'L' And E.Lot_Sold_Status = 'S'
And IsNull(B.Place_City, '') Like @P_City And IsNull(B.Place_State, '') Like @P_Location
And IsNull(F.Inv_H_Category, '') Like @P_Category And IsNull(F.Inv_H_Mfg_Name, '') Like @P_Make
And IsNull(F.Inv_H_Model, '') Like @P_Model

不使用if else语句查询:

Select Count(C.Sal_Pk_Id) 
From dbo.Auction (NoLock) A
Inner Join dbo.PLACE (NoLock) B On A.Auc_Place_Fk_Id = B.Place_Pk_Id
Inner Join dbo.SALES_DETAILS (NoLock) C On A.Auc_Code = C.Sal_Auc_Code
Inner Join dbo.AUCTIONSERVICES (NoLock) D On C.Sal_Regno = D.Auc_Service_Regno And C.Sal_Auc_Code = D.Auc_Service_Auctioncode
Inner Join dbo.LOT (NoLock) E On C.Sal_Lot_No = E.Lot_Lot_No And C.Sal_Auc_Code = E.Lot_Auc_Code 
Inner Join dbo.INVENTORY (NoLock) F On C.Sal_Regno = F.Inv_H_Reg_No
Where C.[Status] = 'L' And E.Lot_Sold_Status = 'S'
And (@P_City = '' Or IsNull(B.Place_City, '') = @P_City)
And (@P_Location= '' Or IsNull(B.Place_State, '') = @P_Location)
And (@P_Category = '' Or IsNull(F.Inv_H_Category, '') = @P_Category)
And (@P_Make = '' Or IsNull(F.Inv_H_Mfg_Name, '') = @P_Make)
And (@P_Model = '' Or IsNull(F.Inv_H_Model, '') = @P_Model)

为什么在我删除存储过程中的if else语句时查询输出花费的时间更少?

2 个答案:

答案 0 :(得分:3)

有两个主要原因 - like和执行计划。

like '%something'是你可以过滤的最慢的东西 - 它意味着逐行,读取列中的整个数据并进行比较。它不能使用任何索引搜索,只能扫描。

其次,根据调用过程的第一种方式,您只能获得一个执行计划。这几乎可以保证,对于任何其他输入数据,性能都会受到影响。在您的第二个示例中,虽然计划再次是次优的并且取决于初始输入,但它并不完全忽略所有可能的过滤器 - 它只是根据统计数据进行优化。

动态过滤器不是以前没有人试图解决的问题。向最好的人学习:http://www.sommarskog.se/dyn-search.html

答案 1 :(得分:2)

我认为没有if的查询更快,因为它没有Like运算符

Where C.[Status] = 'L' And E.Lot_Sold_Status = 'S'
And IsNull(B.Place_City, '') Like @P_City And IsNull(B.Place_State, '') Like @P_Location
And IsNull(F.Inv_H_Category, '') Like @P_Category And IsNull(F.Inv_H_Mfg_Name, '') Like @P_Make
And IsNull(F.Inv_H_Model, '') Like @P_Model

我认为第二个查询可以更有效地使用索引。第一个和第二个查询是不同的,请查看实际执行计划,您将意识到它发生的原因。