返回总行数的MS SQL Server分页

时间:2014-01-08 18:45:29

标签: asp.net sql sql-server tsql pagination

我正在尝试使用带有大型数据集的SQL SERVER 2012进行服务器分页的最快方法,同时返回完整的总记录。

这是一个完整的问题

我之所以这样说,是因为我研究的越多,人们似乎就会越来越多地忽略了这个问题。我知道所有关于估计总记录,索引和硬件更新的性能,但这不是我要求的。

目前我正在使用'OFFSET x ROWS FETCH NEXT y ROWS ON'并且我在我的查询中使用当前'COUNT(*)OVER()AS TotalRows'来尝试使用一个查询而不是两个查询。 / p>

我不得不稍微篡改我的查询以适应'COUNT(*)OVER()',当它们本质上是DISTINCT时。

人们对此有何体验,或者您是否一起使用不同的方法。

知道什么是最好添加到示例中以测试实际时间而没有任何缓存编译等等也是有趣的。我有一个小玩,但无论我尝试哪种方式我很少得到两次相同查询的结果相同。 我猜这是因为操作系统正在做的其他事情,硬盘速度和缓存。

注意:我现在已经添加了一些时间,在我的测试中,第二个查询看起来几乎是第一个查询的两倍。

实施例

DECLARE @RowCount INT 
  SET @RowCount = 0 

DECLARE @TestTable TABLE
( 
  Value1 INT, Value2 INT, Value3 INT
)

-- The above table contains no relevant data and no indexes etc on purpose 
-- as that's not really the point

SET NOCOUNT ON

WHILE @RowCount < 200000 
BEGIN 
  INSERT 
    INTO @TestTable 
      ( Value1, Value2, Value3) 
    VALUES 
      (
       ABS(CHECKSUM(NewId())) % 10,
       ABS(CHECKSUM(NewId())) % 1000,
       8
      )
    SET @RowCount = @RowCount + 1 
END

SET NOCOUNT OFF

-- The following WONT work for DISTINCT Because the COUNT(*) OVER() is 
-- calculated first. 
--
-- SELECT DISTINCT Value1, Value2, Value3, COUNT(*) OVER() AS TotalRows 
-- FROM @TestTable 

CHECKPOINT; 
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE

DECLARE @StartTime DATETIME
DECLARE @EndTime DATETIME 

SET STATISTICS IO ON
SET STATISTICS TIME ON


------------------------------------------------------------------------------------

SET @StartTime = GETDATE()

-- So we have the following using one query
--
SELECT Value1, 
       Value2, 
       Value3, 
       COUNT(*) OVER() AS TotalRows
FROM 
(
  SELECT DISTINCT Value1, Value2, Value3
    FROM @TestTable
    -- INNER JOIN ...
    -- WHERE      ...
) AS foo
ORDER BY Value1
OFFSET (200) ROWS FETCH NEXT (100) ROWS ONLY;

SELECT @EndTime=GETDATE()   
SELECT DATEDIFF(ms,@StartTime,@EndTime) AS [Duration in microseconds] 

------------------------------------------------------------------------------------

SET @StartTime = GETDATE()

-- And this using TWO querys
--
-- Query ONE
SELECT DISTINCT Value1, Value2, Value3
FROM @TestTable
    -- INNER JOIN ...
    -- WHERE      ...
ORDER BY Value1
OFFSET (200) ROWS FETCH NEXT (100) ROWS ONLY;

--Query TWO
SELECT COUNT(*) AS TotalRows FROM (SELECT DISTINCT Value1, Value2, Value3 
FROM (TestTable) AS Foo

SELECT @EndTime=GETDATE()   
SELECT DATEDIFF(ms,@StartTime,@EndTime) AS [Duration in microseconds] 

------------------------------------------------------------------------------------

SET STATISTICS TIME OFF
SET STATISTICS IO OFF

0 个答案:

没有答案