SQL Server 2008:使用已知的空结果优化查询性能

时间:2013-06-06 14:13:13

标签: sql sql-server performance sql-server-2008

我有一个应用程序,其中用户有一个掩码,该掩码针对SQL Server 2008数据库运行sql语句。此外,用户可以在掩码中设置参数。考虑一个带有一个参数的面具,这是一个带有2个选项的下拉菜单:“Planes”和“Cars”。

当用户选择“Cars”并点击“Execute”按钮时,我在掩码中配置的以下SQL语句将命中数据库。

SELECT cars.id, cars.name
FROM cars
WHERE 'Cars' = 'Cars'

UNION ALL

SELECT planes.id, planes.name
FROM planes
WHERE 'Planes' = 'Cars'

(这是一个非常简单的例子,因为我的应用程序中的查询复杂得多,有很多JOINS等等......)

即使我将第二部分粘贴到SQL Server Management工作室,设置一些参数并点击执行,查询将需要几秒钟才能完成...结果为空。

我现在的问题:我如何优化第二部分,以便SQL Server认识到在第二个SELECT语句中,确实无事可做?

编辑:

我的第二个(“死”)查询执行一段时间的原因如下:在查询内部有JOINS,以及WHERE子句中的Sub-SELECT。我们说

SELECT planes.id, planes.name
FROM planes
INNER JOIN very_complex_colour_view colours
     ON colours.id = planes.colour.id
WHERE 'Planes' = 'Cars' 

事实上,甚至“飞机”表本身也是一个复杂的视图。

2 个答案:

答案 0 :(得分:1)

根据参数,它从各个表中选择记录。 因此无需使用UNION ALL

使用IF ELSE构造 -

DECLARE @Input VARCHAR(20) = 'Cars'

IF (@Input = 'Cars')
BEGIN
  SELECT cars.id, cars.name
  FROM cars
END 
ELSE IF (@Input = 'Planes')
BEGIN
  SELECT planes.id, planes.name
  FROM planes  
END

这也有助于SQL Optimizer使用Parameter Sniffing技术并使用可提高查询性能的最佳执行计划。

更多关于Parameter Sniffing -

答案 1 :(得分:0)

当我在我的系统上运行以下查询时:

select *
from <really big table that is not in the cache>
where 'planes' = 'cars'

结果在第一次及以后的时间内立即返回约1秒钟。

我怀疑你的实际查询比这个例子更复杂。而且,简化就是消除了这个问题。即使我尝试使用连接进行上述操作,基本上也没有性能损失。

根据我看到的执行计划,SQL Server认识到常量始终为false。以下查询:

select *
from Published_prev2..table1 sv join
     Published_prev2..table2 sl
     on sv.id= sl.id
where 'planes' = 'cars'

为执行计划生成持续扫描。使用“cars = cars”的相同查询会生成一个更复杂的计划,该计划具有连接等等。