我们知道,在数据量小的时候,数据的分页处理,一般情况下都没有什么问题,但是在大的数据量的情况下,我们就会有数据压力的问题,以前把所有数据都取出来,对数据库以及数据流量的压力也是非常大的,这样会造成性能会非常差。对于大的数据量分页的方法主要有下面的三种思想,它们共同的思路是:只取出我们要分页显示的数据记录,而不是全部取出来。
下面我们来具体分析这三种方法的实现以及性能的测试情况。先说明一下数据表的建立情况。

大数据量的分页处理CREATE TABLE [dbo].[Test] (
大数据量的分页处理    
[ID] [int] IDENTITY (11NOT NULL ,
大数据量的分页处理    
[T_Name] [char] (32) COLLATE Chinese_PRC_CI_AS NOT NULL ,
大数据量的分页处理    
[Voting] [int] NOT NULL 
大数据量的分页处理
ON [PRIMARY]
大数据量的分页处理
GO
大数据量的分页处理
大数据量的分页处理
ALTER TABLE [dbo].[Test] WITH NOCHECK ADD 
大数据量的分页处理    
CONSTRAINT [PK_Test] PRIMARY KEY  CLUSTERED 
大数据量的分页处理    (
大数据量的分页处理        
[ID]
大数据量的分页处理    )  
ON [PRIMARY] 
大数据量的分页处理
GO
大数据量的分页处理
大数据量的分页处理
ALTER TABLE [dbo].[Test] ADD 
大数据量的分页处理    
CONSTRAINT [DF_Test_voting] DEFAULT (0FOR [Voting]
大数据量的分页处理
GO
大数据量的分页处理
大数据量的分页处理
CREATE  INDEX [IX_Test_tName_asc] ON [dbo].[Test]([T_Name]ON [PRIMARY]
大数据量的分页处理
GO
大数据量的分页处理
大数据量的分页处理
CREATE  INDEX [IX_Test_voting_asc] ON [dbo].[Test]([Voting]ON [PRIMARY]
大数据量的分页处理
GO
大数据量的分页处理
大数据量的分页处理
CREATE  INDEX [IX_Test_voting_desc] ON [dbo].[Test]([ID]ON [PRIMARY]
大数据量的分页处理
GO
大数据量的分页处理
大数据量的分页处理
CREATE  INDEX [IX_Test_tName_DESC] ON [dbo].[Test]([T_Name] DESC ) ON [PRIMARY]
大数据量的分页处理
GO

我们新建了一个数据库表TEST,ID是PK并且是自增长的,CLUSTERED索引。T_Name和Voting分别建了ASC和DESC的索引。由于我们只单独对t_Name和Voting字段做分页查询,所以只建立了单独的索引,而没有建相关的组合索引了。
现在只对Voting做分页处理的一个案例。分页处理,一般情况下,我们知道要显示的哪一页Page,以及分页显示的PageSize.对于一些例外在这里我们不用考虑。

方法 INDEXROWCOUNT结合来做分页处理。

大数据量的分页处理CREATE PROC dbo.TestPage_Index
大数据量的分页处理           
@pageSize  INT
,
大数据量的分页处理           
@pageIndex INT

大数据量的分页处理
AS
大数据量的分页处理  
BEGIN
大数据量的分页处理      
DECLARE
大数据量的分页处理        
@PageLower INT,
大数据量的分页处理        
@PageUpper INT

大数据量的分页处理      
DECLARE
大数据量的分页处理        
@id INT
大数据量的分页处理      
DECLARE
大数据量的分页处理        
@voting    INT,
大数据量的分页处理        
@maxvoting INT

大数据量的分页处理                   
大数据量的分页处理      
SET @PageLower = (@pageIndex - 1* @PageSize
大数据量的分页处理                                          
大数据量的分页处理      
SET @PageUpper = @PageLower + @PageSize
大数据量的分页处理                                    
大数据量的分页处理      
SET RowCount  @PageLower
大数据量的分页处理      
大数据量的分页处理      
SELECT   @id = Id,
大数据量的分页处理               
@voting =
 voTing
大数据量的分页处理      
FROM
     Test.dbo.Test (NoLock )
大数据量的分页处理      
ORDER BY voTing ASC

大数据量的分页处理               
大数据量的分页处理      
SET RowCount  @PageUpper
大数据量的分页处理      
SELECT   @maxvoting = voTing
大数据量的分页处理      
FROM
     Test.dbo.Test (NoLock )
大数据量的分页处理      
ORDER BY
 voTing
大数据量的分页处理               
大数据量的分页处理      
SET RowCount  @PageSize

大数据量的分页处理      
大数据量的分页处理      
SELECT   Id,
大数据量的分页处理               t_Name,
大数据量的分页处理               voTing
大数据量的分页处理      
FROM
     Test.dbo.Test (NoLock )
大数据量的分页处理      
WHERE    (voTing = @voting

大数据量的分页处理                
AND Id > @id)
大数据量的分页处理                
OR (voTing > @voting

大数据量的分页处理                    
AND voTing <= @maxVoting)
大数据量的分页处理      
ORDER BY
 voTing
大数据量的分页处理               
大数据量的分页处理      
SET RowCount  0

大数据量的分页处理      
大数据量的分页处理  
END
大数据量的分页处理
大数据量的分页处理
GO
大数据量的分页处理

第二种方法:用临时表的方法来分页处理

大数据量的分页处理CREATE PROC dbo.TestPage_Tab
大数据量的分页处理           
@pageSize  INT
,
大数据量的分页处理           
@pageIndex INT

大数据量的分页处理
AS
大数据量的分页处理  
BEGIN
大数据量的分页处理      
DECLARE
大数据量的分页处理        
@PageLower INT,
大数据量的分页处理        
@PageUpper INT

大数据量的分页处理      
DECLARE
大数据量的分页处理        
@id INT
大数据量的分页处理      
DECLARE
大数据量的分页处理        
@voting    INT,
大数据量的分页处理        
@maxvoting INT

大数据量的分页处理                   
大数据量的分页处理      
CREATE TABLE ##IndexTable (
大数据量的分页处理        Id  
INT IDENTITY1  , 1
  ),
大数据量的分页处理        nId 
INT
)
大数据量的分页处理      
大数据量的分页处理      
SET @PageLower = (@pageIndex - 1* @PageSize

大数据量的分页处理                                          
大数据量的分页处理      
SET @PageUpper = @PageLower + @PageSize
大数据量的分页处理      
SET RowCount  @PageUpper
大数据量的分页处理      
INSERT INTO ##IndexTable
大数据量的分页处理                 (nId)
大数据量的分页处理      
SELECT
   Id
大数据量的分页处理      
FROM
     Test.dbo.Test (NoLock )
大数据量的分页处理      
ORDER BY
 voTing
大数据量的分页处理      
SET RowCount  @PageSize

大数据量的分页处理      
SELECT   a.*
大数据量的分页处理      
FROM     Test.dbo.Test a (NoLock),
大数据量的分页处理               ##IndexTable t (NoLock)
大数据量的分页处理      
WHERE    a.Id =
 t.nId
大数据量的分页处理               
AND t.Id > @PageLower

大数据量的分页处理               
AND t.Id <= @PageUpper
大数据量的分页处理      
ORDER BY t.Id
大数据量的分页处理      
SET RowCount  0

大数据量的分页处理      
DROP TABLE ##IndexTable 
大数据量的分页处理      
大数据量的分页处理  
END

大数据量的分页处理
大数据量的分页处理
GO

第三种方法:用Cursor来做分页处理

大数据量的分页处理CREATE PROC dbo.TestPage_CurSor
大数据量的分页处理           
@pageSize  INT
,
大数据量的分页处理           
@pageIndex INT

大数据量的分页处理
AS
大数据量的分页处理  
BEGIN
大数据量的分页处理      
DECLARE
大数据量的分页处理        
@PageLower INT,
大数据量的分页处理        
@PageUpper INT

大数据量的分页处理      
DECLARE
大数据量的分页处理        
@id INT,
大数据量的分页处理        
@i  INT

大数据量的分页处理      
DECLARE
大数据量的分页处理        
@voting    INT,
大数据量的分页处理        
@maxvoting INT

大数据量的分页处理      
DECLARE
大数据量的分页处理        
@condition CHAR(400)
大数据量的分页处理      
DECLARE

大数据量的分页处理        
@cur  AS  CURSOR
大数据量的分页处理      
SET @PageLower = (@pageIndex - 1* @PageSize
大数据量的分页处理      
SET @PageUpper = @PageLower + @PageSize
大数据量的分页处理      
SET RowCount  @PageUpper
大数据量的分页处理      
SET @cur = CURSOR FAST_FORWARD READ_ONLY FOR SELECT   Id
大数据量的分页处理                                                   
FROM
     Test.dbo.Test (NoLock )
大数据量的分页处理                                                   
ORDER BY
 voTing
大数据量的分页处理      
OPEN @cur

大数据量的分页处理      
SET RowCount  0
大数据量的分页处理      
FETCH NEXT FROM @cur
大数据量的分页处理      
INTO @id
大数据量的分页处理      
SET @i = 1
大数据量的分页处理      
WHILE @@FETCH_STATUS = 0
大数据量的分页处理          
BEGIN
大数据量的分页处理          
大数据量的分页处理              
IF (@i >= @PageLower + 1)
大数据量的分页处理                 
AND @i <= @pageUpper

大数据量的分页处理                  
BEGIN
大数据量的分页处理                      
IF @i = @PageLower + 1
大数据量的分页处理                          
BEGIN
大数据量的分页处理                              
SET @condition = Rtrim(CAST(@id AS CHAR(10)))
大数据量的分页处理                          
END

大数据量的分页处理                       
ELSE
大数据量的分页处理                        
BEGIN
大数据量的分页处理                            
SET @condition = Rtrim(@condition+ ',' + Rtrim(CAST(@id AS CHAR(10)))
大数据量的分页处理                        
END

大数据量的分页处理                  
END
大数据量的分页处理              
SET @i = @i + 1
大数据量的分页处理              
FETCH NEXT FROM @cur
大数据量的分页处理              
INTO @id
大数据量的分页处理          
END
大数据量的分页处理      
CLOSE @cur
大数据量的分页处理      
DEALLOCATE @cur
大数据量的分页处理      
IF @condition IS NOT NULL 
大数据量的分页处理          
EXEC'select * from test..test(nolock) where id in (' + @Condition + ')'
)
大数据量的分页处理  
END

大数据量的分页处理
GO


测试比较
我现在的机器是T43 ,CPU 1.86G SQL SERVER 2000
TEST表里有400,000条记录
测试程序如下:

大数据量的分页处理DECLARE  @dt DATETIME
大数据量的分页处理
大数据量的分页处理
SET @dt = Getdate()
大数据量的分页处理
大数据量的分页处理
EXEC TestPage_CurSor  25,200
大数据量的分页处理
大数据量的分页处理
SELECT Getdate() - @dt AS m_CurSor
大数据量的分页处理
大数据量的分页处理
SET @dt = Getdate()
大数据量的分页处理
大数据量的分页处理
EXEC TestPage_Index  25,200
大数据量的分页处理
大数据量的分页处理
SELECT Getdate() - @dt AS m_Index
大数据量的分页处理
大数据量的分页处理
SET @dt = Getdate()
大数据量的分页处理
大数据量的分页处理
EXEC TestPage_Tab  25,200
大数据量的分页处理
大数据量的分页处理
SELECT Getdate() - @dt AS m_Tab

测试的结果为:
 大数据量的分页处理


我们可以看到测试的结果是如此的悬殊:
第一种对比下来,基本上没有花时间,就处理了
第二种花了50ms的时间,但是多了一个临时表
第三种花了近6s的时间才能处理。
在数据量小的时候,三种方法都差不多,但是在大的数据量的情况却是如此之大,所以如果有开发人员遇到相同的问题的时候,可以参考这个例子。
对于用临时表的做法,如果查询的视图,没有主键的时候,请用临时表,第一种处理完全依赖于索引,速度才如此快。

转载于:https://www.cnblogs.com/dicman/archive/2006/07/14/450539.html

相关文章: