基于WHERE子句的SQL性能

时间:2017-01-12 11:42:52

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

我正在尝试重用查询,而不是创建多个方案。基本上我从大桌子上得到一个COUNT。

问题是:如果我使用

,我将在长期失去表现
SELECT COUNT(id) FROM [Documents] WHERE UploadDate > '1900/1/1' AND UploadDate < GETDATE()

而不是简单的

SELECT COUNT(id) FROM [Documents]

基本上2个查询会返回相同的内容,因为我想在这种情况下返回所有记录。但在某些其他情况下,日期对将使用不同的参数。

3 个答案:

答案 0 :(得分:0)

如果您想计算所有内容,然后计算符合条件的内容:

SELECT COUNT(id) as total_cnt,
       SUM(CASE WHEN UploadDate > '1900-01-01' AND UploadDate < GETDATE()
                THEN 1 ELSE 0
           END) as specific_cnt
FROM [Documents] d;

答案 1 :(得分:0)

如果您担心根据您在查询中指定的范围值而改变性能,由于参数嗅探,您可以在查询结尾处添加OPTION (RECOMPILE)

SELECT COUNT(id) 
FROM [Documents] 
WHERE UploadDate > '1900/1/1' AND UploadDate < GETDATE()
OPTION (RECOMIPLE)

如果您决定从'2011/1/1'开始检查,那么这将确保您新生成的计划是Optimizer可以在该时刻自行提出的最佳方案。示例

答案 2 :(得分:0)

如果您想根据某些参数进行计数,如果您在UploadDate上定义了索引,我认为不会有显着差异。如果您使用的是存储过程,则可能如下所示:

CREATE PROCEDURE dbo.GetCount
(
   @FromDate DATETIME2 = '1900-01-01',
   @ToDate DATETIME2 = '9999-12-31',
   -- other filters may come here
)
AS
BEGIN
   SELECT COUNT(id) 
   FROM [Documents] 
   WHERE UploadDate > @FromDate AND @ToDate < @ToDate
END
GO

-- get all
EXEC dbo.GetCount
-- get from date
EXEC dbo.GetCount @FromDate = '2015-03-01'
-- to date
EXEC dbo.GetCount @ToDate = '2016-03-01'
-- both
EXEC dbo.GetCount @FromDate = '2015-03-01', @ToDate = '2016-03-01'

您还可以尝试通过创建动态SQL 来获取要运行的最小SQL:

CREATE PROCEDURE dbo.GetCount
(
   @FromDate DATETIME2 = NULL,
   @ToDate DATETIME2 = NULL
   -- other filters may come here
)
AS
BEGIN
   DECLARE @SQL NVARCHAR(4000) = N'
       SELECT COUNT(id) FROM [Documents]
       WHERE 1 = 1 
   '
   IF (@FromDate IS NOT NULL) @SQL = @SQL + ' UploadDate > @FromDate'
   IF (@ToDate IS NOT NULL) @SQL = @SQL + ' UploadDate > @ToDate'

   EXECUTE sp_executesql @SQL, '@FromDate DATETIME2, @ToDate DATETIME2', @FromDate, @ToDate
END

这为左侧和/或右侧提供了开放间隔的灵活性。

如果您从应用程序层动态生成查询(例如LINQ2SQL),最好的选择是根据您的参数生成它。这将导致最短和最快的查询:

var query = DbContext.Documents;
if (fromDate.HasValue) query = query.Where(UploadDate > fromDate.Value);
if (toDate.HasValue) query = query.Where(UploadDate < toDate.Value);
int count = query.Count();

最后两个解决方案还允许轻松添加新过滤器。