zoukankan      html  css  js  c++  java
  • 使用SQL Server 2005 新的语法ROW_NUMBER()进行分页的两种不同方式的性能比较

    相比在SQL Server 2000 中使用的分页方式,在SQL Server 2005中使用新的语法ROW_NUMBER()来分页效率要高出很多,但是很多人在使用ROW_NUMBER()这种分页方式时,使用的方法并不正确,以下列出不正确的和正确的做法并做简单分析:

    首先假设我们已经创建了如下的表和索引并初始化了100万条数据:

    CREATE TABLE [dbo].[Users]
    (
        [ID] [int] IDENTITY(1,1) NOT NULL,
        [Name] [varchar](50) NULL,
        [Test] [nchar](10) NULL,
        CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED 
        (
            [ID] ASC
        ) ON [PRIMARY]
    ) ON [PRIMARY]
    
    CREATE UNIQUE NONCLUSTERED INDEX [Inx_Name] ON [dbo].[Users] 
    (
        [Name] ASC
    ) ON [PRIMARY]
    
    
    DECLARE @index INT
    SET @index=0
    WHILE @index<1000000 
    BEGIN
        INSERT INTO [dbo].[Users]([Name],[Test]) values(@index,'walkingp') 
        SET @index = @index + 1
    END 

    不正确的使用方式(查出所有数据后再排序):

    SELECT ID,Name,Test 
    FROM (SELECT ROW_NUMBER() OVER(ORDER BY Name) AS RowNum,* 
          FROM dbo.Users
          ) AS T 
    WHERE RowNum BETWEEN 5000 AND 5100 

    正确的使用方式如下(查出主键进行排序过滤,然后使用过滤后的主键来查找数据):

    SELECT A.ID,A.Name,A.Test  
    FROM dbo.Users AS A 
    INNER JOIN 
    (SELECT RowNum,ID 
     FROM (SELECT ROW_NUMBER() OVER(ORDER BY Name) AS RowNum,ID 
           FROM dbo.Users) AS T 
     WHERE RowNum BETWEEN 4000 AND 4100) as B 
    ON A.ID = B.ID 
    ORDER BY B.RowNum

    以下具体分析:

    SET STATISTICS IO ON
    SET STATISTICS TIME ON
    GO
    
    PRINT 'Error.5000-------------------------'
    DECLARE @time DATETIME  
    DECLARE @ms INT 
    SET @time= GETDATE() 
    
    SELECT ID,Name,Test 
    FROM (SELECT ROW_NUMBER() OVER(ORDER BY Name) AS RowNum,* 
          FROM dbo.Users) AS T 
    WHERE RowNum BETWEEN 5000 AND 5100 
    
    SET @ms=DATEDIFF(ms,@time,GETDATE())  
    PRINT @ms--毫秒数
    GO
    
    PRINT 'Right.5000-------------------------'
    DECLARE @time DATETIME  
    DECLARE @ms INT 
    SET @time= GETDATE() 
    
    SELECT A.ID,A.Name,A.Test  
    FROM dbo.Users AS A 
    INNER JOIN 
    (SELECT RowNum,ID 
     FROM (SELECT ROW_NUMBER() OVER(ORDER BY Name) AS RowNum,ID 
           FROM dbo.Users) AS T 
     WHERE RowNum BETWEEN 5000 AND 5100) AS B 
    ON A.ID = B.ID 
    ORDER BY B.RowNum
    
    SET @ms=DATEDIFF(ms,@time,GETDATE())  
    PRINT @ms--毫秒数
    GO
    
    PRINT 'Error.500000-------------------------'
    DECLARE @time DATETIME  
    DECLARE @ms INT 
    SET @time= GETDATE() 
    
    SELECT ID,Name,Test 
    FROM (SELECT ROW_NUMBER() OVER(ORDER BY Name) AS RowNum,* 
          FROM dbo.Users) AS T 
    WHERE RowNum BETWEEN 500000 AND 500100 
    
    SET @ms=DATEDIFF(ms,@time,GETDATE())  
    PRINT @ms--毫秒数
    GO
    
    PRINT 'Right.500000-------------------------'
    DECLARE @time DATETIME  
    DECLARE @ms INT 
    SET @time= GETDATE() 
    
    SELECT A.ID,A.Name,A.Test  
    FROM dbo.Users AS A 
    INNER JOIN 
    (SELECT RowNum,ID 
     FROM (SELECT ROW_NUMBER() OVER(ORDER BY Name) AS RowNum,ID 
           FROM dbo.Users) AS T 
     WHERE RowNum BETWEEN 500000 AND 500100) AS B 
    ON A.ID = B.ID 
    ORDER BY B.RowNum
    
    SET @ms=DATEDIFF(ms,@time,GETDATE())  
    PRINT @ms--毫秒数
    GO
    
    PRINT 'Error.900000-------------------------'
    DECLARE @time DATETIME  
    DECLARE @ms INT 
    SET @time= GETDATE() 
    
    SELECT ID,Name,Test 
    FROM (SELECT ROW_NUMBER() OVER(ORDER BY Name) AS RowNum,* 
          FROM dbo.Users) AS T 
    WHERE RowNum BETWEEN 900000 AND 900100 
    
    SET @ms=DATEDIFF(ms,@time,GETDATE())  
    PRINT @ms--毫秒数
    GO
    
    PRINT 'Right.900000-------------------------'
    DECLARE @time DATETIME  
    DECLARE @ms INT 
    SET @time= GETDATE() 
    
    SELECT A.ID,A.Name,A.Test  
    FROM dbo.Users AS A 
    INNER JOIN 
    (SELECT RowNum,ID 
     FROM (SELECT ROW_NUMBER() OVER(ORDER BY Name) AS RowNum,ID 
           FROM dbo.Users) AS T 
     WHERE RowNum BETWEEN 900000 AND 900100) AS B 
    ON A.ID = B.ID 
    ORDER BY B.RowNum
    
    SET @ms=DATEDIFF(ms,@time,GETDATE())  
    PRINT @ms--毫秒数

    以下是SQL的统计信息:

    Error.5000-------------------------

    (101 row(s) affected)
    Table 'Users'. Scan count 1, logical reads 15649, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

    SQL Server Execution Times:
       CPU time = 31 ms,  elapsed time = 35 ms.

    36

    Right.5000-------------------------

    (101 row(s) affected)
    Table 'Users'. Scan count 1, logical reads 325, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

    SQL Server Execution Times:
       CPU time = 0 ms,  elapsed time = 7 ms.

    6

    Error.500000-------------------------

    (101 row(s) affected)
    Table 'Users'. Scan count 1, logical reads 1532807, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

    SQL Server Execution Times:
       CPU time = 1797 ms,  elapsed time = 1789 ms.

    1786

    Right.500000-------------------------

    (101 row(s) affected)
    Table 'Users'. Scan count 1, logical reads 1545, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

    SQL Server Execution Times:
       CPU time = 453 ms,  elapsed time = 454 ms.

    453

    Error.900000-------------------------

    (101 row(s) affected)
    Table 'Users'. Scan count 1, logical reads 2758790, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

    SQL Server Execution Times:
       CPU time = 3266 ms,  elapsed time = 3280 ms.

    3273

    Right.900000-------------------------

    (101 row(s) affected)
    Table 'Users'. Scan count 1, logical reads 2528, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

    SQL Server Execution Times:
       CPU time = 750 ms,  elapsed time = 748 ms.

    750

      通过分析可以看出错误的使用方式逻辑读要比正确的使用方式的逻辑读大的多,而且页码越大读的越多,最终导致效率越来越差,这点也可以通过执行计划看出端倪。

          希望对您有所帮助^_^。

  • 相关阅读:
    C语言寒假大作战01
    C语言I作业12—学期总结
    C语言I博客作业11
    C语言I博客作业10
    C语言I博客作业09
    C语言I作业07:第十二周作业
    团队作业6--复审与事后分析
    Alpha阶段项目复审
    事后诸葛亮
    团队作业5——测试与发布(Alpha版本)
  • 原文地址:https://www.cnblogs.com/JinvidLiang/p/4606120.html
Copyright © 2011-2022 走看看