基于如下基础分页方案
from table1
where id>
(select max (id) from
(select top ((页码-1)*页大小) id from table1 order by id) as T --瓶颈
)
order by id
随着分页数的上升,尽管只选取了ID列,但量上仍然很惊人,关键就是top得太多>:
改进点也就出在这里:
1、一分为二
因为 纪录中点 = 总纪录数/2,如果超过纪录中点,改变一下order的顺序(降序<->升序),
由X = ((页码-1)*页大小),更改相应的top数(总纪录-X)
SELECT TOP 页大小 * FROM 表 WHERE ID <
(SELECT MIN(ID)
FROM
(SELECT TOP X ID FROM 表 ORDER BY ID DESC) AS tblTmp)
ORDER BY ID DESC
=>
SELECT TOP 页大小 * FROM 表 WHERE ID >
(SELECT MAX(ID)
FROM
(SELECT TOP 总记录-X ID FROM 表 ORDER BY ID ASC) AS tblTmp)
ORDER BY ID ASC
以上只是分段纪录集的特例,我们完全可以通过SQL计算出1/4,1/8,1/16,1/32……等不同情况下的纪录临界,进一步缩小结果集。
2、top 10
尽管一个N大的表可以分为N/pagesize多的页,不过现实情况是,很少有人会一页一页的翻到10000页,统计概率告诉我们,一个人的翻页的耐心很少有大于10的,80%的翻页又集中在前20%,也就是前两页!
2.1 预载
我们可以不用吹灰之力预先计算出top 10页的临界ID:
(select top ((页码-1)*页大小) id from table1 order by id) as T
然后放入[1][2][3][……]这样的分页链接中(形如showpage.asp?id=1000),用
from table1
where id>QueryString(ID)
轻松实现分页。
2.2 setp by setp
更幸运的是,绝大多数情况下,人们是一页接一页的翻阅,于是,我们还有针对这90%+情况的更优的解决方案。
首先打开第一页,我们得到第一页最后一条纪录的ID,这就是第二页分页的初始ID!
如果打开第N页,那么第一条记录的ID就是MAX(N-1页纪录ID)+1,最后一条纪录就是MIN(N+1页纪录ID)-1,用所得到的ID更改临近页面的URL;
升序排列:
--N-1页
SELECT TOP 页大小 *
FROM table1
WHERE ID < MIN_ID ORDER ORDER BY ID ASC
--N+1页
SELECT TOP 页大小 *
FROM table1
WHERE ID > MAX_ID ORDER ORDER BY ID ASC
降序排列:
--N-1页
SELECT TOP 页大小 *
FROM table1
WHERE ID > MAX_ID ORDER ORDER BY ID DESC
--N+1页
SELECT TOP 页大小 *
FROM table1
WHERE ID < MIN_ID ORDER ORDER BY ID DESC