我在我的存储过程中使用了以下查询。当我使用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语句时查询输出花费的时间更少?
答案 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
我认为第二个查询可以更有效地使用索引。第一个和第二个查询是不同的,请查看实际执行计划,您将意识到它发生的原因。