日期:2014-05-17  浏览次数:20545 次

倒序索引在业务系统中分页查询时候的应用
本帖最后由 x_wy46 于 2013-08-22 17:34:10 编辑

--本文所说的情况只是符合特定的应用场景,所假设的条件也都不绝对
--仅仅是有感而发,根据自己的感受体会写出来的,可能有不对的地方,欢迎指正
 
 
--倒序索引在业务系统中分页的应用
 
 
 
--系统中的查询中,经常会遇到分页查询
--因为是业务系统,所以基本上是按照时间的倒序来排序的,
--注意,这里说的情况不绝对,相当一部分数据,多数情况下是按照时间倒序来排序的
--其实这种情况也可以理解,
--比如业务系统,
--今天是不是来了新的需要报关的单子.......
--今天是不是有哪些新的加班单需要批准.......
--今天还有哪些送货信息还没有确认.......
--随着“老”数据被一步一步地处理
--系统用户总是关注最新的数据,我翻了一下代码,绝大多数业务数据查询分页是是按照时间的倒序排的
--但是多数情况下是按照CreateDate来order by的,
--但是在创建时间字段上建立聚集索引的时候默认是ASC
--按照B树索引的结构,我们每次查询的最新的数据,
--默认的正序索引的,最新的数据存储在B树的最右边
--每次要遍历整个B树才能查询到这部分最新的数据
 
 
--所以就想到了,何不来个倒序索引,这样最新的数据永远存储在B树的最左边,
--查询时,可能是一开始遍历B树就找到了这部分数据
--下面开始测试
 
 
 
--建立测试表,比较简单,有一个ID,模拟业务表中的主键,
--这里为了简单起见,就用整型的自增列吧
create table Test_ASCIndex
(
    id int identity(1,1),
    Cloumn1 varchar(100),
    Cloumn2 varchar(100),
    CreateDate datetime2
)
 
 
--创建测试数据,用GUID和时间来填充列,
--其中时间字段在当前时间的基础上,HH递加
--目的就是为了减少同一个时刻存在大量的数据的情况,
--模拟日常生产系统中的业务数据增长情况
--当然实际生产系统下也有统一时刻插入的情况,这个不绝对
--若有特殊情况,再根据具体情况处理
declare @i int
set @i=1
while @i<=100000
begin
    insert into Test_ASCIndex values (NEWID(),NEWID(),DateAdd(HH,@i,GETDATE()))
    set @i=@i+1
end
 
 
--将数据插入到另外一个测试表中
select * into Test_DESCIndex from Test_ASCIndex 
 
 
--在Test_ASCIndex建立正序索引
create clustered index ASCIndex on Test_ASCIndex(CreateDate)
--在Test_ASCIndex建立倒序索引
create clustered index DESCIndex on Test_DESCIndex(CreateDate desc)
 
 
set statistics io on
 
--比如这里我要查询按时间倒序排,第三页数据(其实随便第一页,第二页,第三页都一样)
 
--在正序索引的表中是这样的
SELECT TOP 10 *
  FROM Test_ASCIndex
 WHERE (createdate >
           (SELECT max(createdate)
               FROM (SELECT TOP 99970 createdate
                       FROM Test_ASCIndex
                      ORDER BY createdate ) AS T))