是一篇我们讨论了,SQL Server 2005 分页 的两种情况,在取不同分页时,花的时间很大,如果我们真的取后面几页,如果有几千倍的ioa差异,
假如客户是自己输入页数,那他要等多长时间才能打开,有没有好的办法优化速度。
我们先把先前的sql语句做一个修改:
select * from
(select id, row_number() over (order by id)
scn from [dbo].[[[zping.com]]]]] ) t
where scn<100000 and scn>100000-20
(select id, row_number() over (order by id)
scn from [dbo].[[[zping.com]]]]] ) t
where scn<100000 and scn>100000-20
这里我们看到只是把select *,row_number() over (order by id)修改成了
select id, row_number() over (order by id)
执行一下看看效率:
(19 行受影响)
表 '[[zping.com]]'。扫描计数 1,逻辑读取 740 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 '[[zping.com]]'。扫描计数 1,逻辑读取 740 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
这时我们发现和上次很大差距,上一次是10万IO,这次是740个,为何,看看执行计划
这时发现,数据库并没有去扫描表数据,而是直接去扫描索引。效率很高 ,但有个缺点就是不能读出需要的数据 。
那对于上次分页的10万IO,我们怎么优化啊,如果数据有1000万,那时间是很长的。这时我们可以利用这个索引扫描来
优化该分页:
修改了一下10万行的分页的sql语句:
select * from [dbo].[[[zping.com]]]]] where id in (
select id from
(select id, row_number() over (order by id)
scn from [dbo].[[[zping.com]]]]] ) t
where scn<100000 and scn>100000-20)
select id from
(select id, row_number() over (order by id)
scn from [dbo].[[[zping.com]]]]] ) t
where scn<100000 and scn>100000-20)
这时候运行一下sql语句
(19 行受影响)
表 '[[zping.com]]'。扫描计数 1,逻辑读取 816 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 '[[zping.com]]'。扫描计数 1,逻辑读取 816 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
这时你发现读出的数据都有了,逻辑IO次数有10万次变成816次,io数大大降低。时间也大大提高。
注意:
我们现在讨论时单个表的数据分页,而且是索引覆盖情况下,当复杂多表关联查询分页,效率不高,有很大局限性。