Sql server 哪个T-SQL跳转查询更好?
2015年12月17日-更新 我问这个问题已经有一段时间了,但还没有真正得到答案,所以我想我会发布我的团队最终使用的解决方案 我们最初使用动态SQL选项来获取智能排序。虽然这感觉真的很脏。我们最终提出了以下实施方案:Sql server 哪个T-SQL跳转查询更好?,sql-server,performance,tsql,sql-server-2008-r2,pagination,Sql Server,Performance,Tsql,Sql Server 2008 R2,Pagination,2015年12月17日-更新 我问这个问题已经有一段时间了,但还没有真正得到答案,所以我想我会发布我的团队最终使用的解决方案 我们最初使用动态SQL选项来获取智能排序。虽然这感觉真的很脏。我们最终提出了以下实施方案: --Params DECLARE @pageSize INT , @pageIndex INT , @sortBy varchar(30) , @sortDirection varchar(4); SET @pageIndex = 1; SET
--Params
DECLARE
@pageSize INT
, @pageIndex INT
, @sortBy varchar(30)
, @sortDirection varchar(4);
SET @pageIndex = 1;
SET @pageSize = 10;
SET @sortBy = 'PolicyCode';
SET @sortDirection = 'ASC';
--Vars
DECLARE @start INT,
@end INT;
--Page 1-n
SET @pageIndex = 1;
SET @pageSize = 10;
SET @start = (@pageSize * @pageIndex) - (@pageSize - 1);
SET @end = (@pageSize * @pageIndex);
;WITH PolicyCTE AS (
SELECT p.PolicyId, p.PolicyTypeId, p.PolicyCode, p.PolicyDesc, p.EffectiveDate, p.ExpirationDate
FROM Policy p INNER JOIN PolicyOrg po ON p.PolicyId = po.PolicyId
)
, PagedResultsCTE AS (
SELECT
[PolicyId]
, [PolicyTypeId]
, [PolicyCode]
, [PolicyDesc]
, [EffectiveDate]
, [ExpirationDate]
, CASE
WHEN @sortBy = 'PolicyTypeId' AND @sortDirection = 'ASC' THEN ROW_NUMBER() OVER (ORDER BY [PolicyTypeId] ASC)
WHEN @sortBy = 'PolicyTypeId' AND @sortDirection = 'DESC' THEN ROW_NUMBER() OVER (ORDER BY [PolicyTypeId] DESC)
WHEN @sortBy = 'PolicyCode' AND @sortDirection = 'ASC' THEN ROW_NUMBER() OVER (ORDER BY [PolicyCode])
WHEN @sortBy = 'PolicyCode' AND @sortDirection = 'DESC' THEN ROW_NUMBER() OVER (ORDER BY [PolicyCode] DESC)
WHEN @sortBy = 'PolicyDesc' AND @sortDirection = 'ASC' THEN ROW_NUMBER() OVER (ORDER BY [PolicyDesc])
WHEN @sortBy = 'PolicyDesc' AND @sortDirection = 'DESC' THEN ROW_NUMBER() OVER (ORDER BY [PolicyDesc] DESC)
WHEN @sortBy = 'EffectiveDate' AND @sortDirection = 'ASC' THEN ROW_NUMBER() OVER (ORDER BY [EffectiveDate])
WHEN @sortBy = 'EffectiveDate' AND @sortDirection = 'DESC' THEN ROW_NUMBER() OVER (ORDER BY [EffectiveDate] DESC)
WHEN @sortBy = 'ExpirationDate' AND @sortDirection = 'ASC' THEN ROW_NUMBER() OVER (ORDER BY [ExpirationDate])
WHEN @sortBy = 'ExpirationDate' AND @sortDirection = 'DESC' THEN ROW_NUMBER() OVER (ORDER BY [ExpirationDate] DESC)
END AS RowNumber
FROM PolicyCTE
)
SELECT PolicyId, PolicyTypeId, PolicyCode, PolicyDesc, EffectiveDate, ExpirationDate
FROM PagedResultsCTE
WHERE RowNumber BETWEEN @start AND @end
ORDER BY RowNumber
GO
通过组合CASE语句和另一个CTE,我们能够按照传入的排序标准进行排序,并获得正确的ROWNUMBER值。然后,在最后的select语句中,我们可以简单地按rownumber列排序
我将暂时避免标记已回答的问题,以防有人想插话讨论此解决方案。欢迎反馈
原职
也许有更多DBA知识的人可以帮我解释一下。基本前提是:获取分页数据以提高页面加载性能使用存储过程中的优化查询获取记录1-10、11-20等。这些表格有数千条记录
我正在使用SQL Server 2008 R2,并提出了以下用于存储过程的T-SQL:
--Params
DECLARE @pageSize INT,
@pageIndex INT;
SET @pageIndex = 1;
SET @pageSize = 10;
--Vars
DECLARE @start INT,
@end INT
--Page 1-n
SET @pageIndex = 1;
SET @pageSize = 10;
SET @start = (@pageSize * @pageIndex) - (@pageSize - 1);
SET @end = (@pageSize * @pageIndex)
;WITH PolicyCTE AS
(
SELECT ROW_NUMBER() OVER (ORDER BY p.PolicyCode) AS RowNumber,
p.PolicyId, p.PolicyTypeId, p.PolicyCode, p.PolicyDesc, p.EffectiveDate, p.ExpirationDate
FROM Policy p INNER JOIN PolicyOrg po ON p.PolicyId = po.PolicyId
)
SELECT PolicyId, PolicyTypeId, PolicyCode, PolicyDesc, EffectiveDate, ExpirationDate
FROM PolicyCTE
WHERE RowNumber BETWEEN @start AND @end
ORDER BY PolicyCode
GO
在寻找如何做到这一点的最佳实践的过程中,我遇到了这篇旧的MSDN模式和实践文章:applies to SQL 2000,并指出这篇文章已经过时。参考特定于用户的记录部分,相当于T-SQL的部分如下所示:
DECLARE
@pageIndex int,
@pageSize int,
@sortBy nvarchar(30)
SET @pageIndex = 0;
SET @pageSize = 10;
SET @sortBy = 'PolicyCode';
DECLARE @rowsToRetrieve int,
@sortDirFlipped nvarchar(4);
IF @pageIndex < 1 SET @pageIndex = 1;
IF @pageSize < 1 SET @pageSize = 10;
SET @rowsToRetrieve = @pageIndex * @pageSize
DECLARE @sqlString nvarchar(1000);
SET @sqlString = N'
SELECT PolicyId, PolicyTypeId, PolicyCode, PolicyDesc, EffectiveDate, ExpirationDate
FROM (
SELECT TOP ' + CAST(@pageSize AS VARCHAR(10)) + ' PolicyId, PolicyTypeId, PolicyCode, PolicyDesc, EffectiveDate, ExpirationDate
FROM (
SELECT TOP ' + CAST(@rowsToRetrieve AS VARCHAR(10)) + ' PolicyId, PolicyTypeId, PolicyCode, PolicyDesc, EffectiveDate, ExpirationDate
FROM (
SELECT TOP ' + CAST(@rowsToRetrieve AS VARCHAR(10)) + ' p.PolicyId, p.PolicyTypeId, p.PolicyCode, p.PolicyDesc, p.EffectiveDate, p.ExpirationDate
FROM Policy p INNER JOIN PolicyOrg po ON p.PolicyId = po.PolicyId
ORDER BY p.' + @sortBy + '
) AS T2
ORDER BY ' + @sortBy + ' DESC
) AS T3
) AS T4
ORDER BY ' + @sortBy + ' ASC';
EXEC(@sqlString)
GO
我在运行执行计划和客户端统计数据的情况下运行了这两个版本,在我看来,它绝对不是分析MSDN版本性能更好的结果的专家。据我所知,部分原因是MSDN版本开始时记录集较小。然而,我真的不喜欢MSDN版本使用动态查询的事实。我的理解是,它们更容易受到SQL注入攻击
我发现的大多数示例更喜欢第一个示例的形式。有人能帮我解释一下这一点,并解释一下为什么除了已经列出的表单之外,第一种表单比第二种表单更好?当动态SQL暴露在存储过程之外时,它很容易受到攻击。如果使用静态排序,则可以转换MSDN示例。我还要看看ROW_NUMBER函数。前者肯定更好,并且可以被查询优化器缓存,但是动态SQL在如何执行查询方面可能更聪明一些。您是否研究过SQL Server中的应用程序?如果您运行的是SQL Server 2012,它将比任何一个选项都快得多。@AaronFriel,我已经研究过了,但不幸的是,我没有运行SQL Server 2012。我想这取决于我是否希望它是可缓存的还是更智能的。@ChrisH这是动态SQL的一个优点。顺便说一下,我的第一个示例使用了ROW_NUMBER。