由于原来系统的分页方式,采用的是假分页,效率很低,且经常数据库超时报黄页。所以,最近都在寻找合适的分页优化方法。
原sql模型:
WITH Records
AS ( SELECT ROW_NUMBER() OVER ( ORDER BY XXX DESC ) AS RecordNumber,
RecordCount = COUNT(1) OVER ( ),
……
……
……
FROM table1
WHERE 条件)
SELECT *
FROM Records WITH ( NOLOCK )
WHERE RecordNumber BETWEEN 1 AND 15
目前找到的比较有效地优化方式,有两种,一种仍采取这种假分页方式,但是,将with中的select 字段拿到with外,具体如下:
假分页优化方式:
WITH Records
AS ( SELECT ROW_NUMBER() OVER ( ORDER BY XXX DESC ) AS RecordNumber,
RecordCount = COUNT(1) OVER ( ),
id
FROM table1
WHERE 条件)
SELECT ……
……
……
,Records.*
FROM Records WITH ( NOLOCK )
JoIN table1 WITH ( NOLOCK ) ON table1.partid = Records.partid
WHERE RecordNumber BETWEEN 1 AND 15
这种方式,因with中只是select索引字段,而wiht仅对一页需要的15条数据,select出所有字段,这样可以较好的提高数据库处理效率。
另外一种优化方式比较彻底,是采用top方式,进行真分页查询,效率提高非常明显,具体如下:
真分页优化方式:
SELECT TOP 页大小 * FROM table1 WHERE id > ( SELECT ISNULL(MAX(id),0) FROM ( SELECT TOP 页大小*(页数-1) id FROM table1 WHERE 条件 ORDER BY id ) A ) ORDER BY id
但是因为这种方式没法求的总数量,
所以,我又进行了改进,具体如下:
DECLARE @RecordCount INT; SET @RecordCount= (SELECT COUNT(1) FROM table1 WHERE 条件);
SELECT TOP 页大小 * FROM table1 WHERE id > ( SELECT ISNULL(MAX(id),0) FROM ( SELECT TOP 页大小*(页数-1) id FROM table1 WHERE 条件 ORDER BY id ) A ) ORDER BY id
就目前测试使用情况看,两种优化方式的优缺点:
假分页优化
优点:当select字段较大、较多,尤其是有类似varchar(max)类型时,提高性能明显;易于规范编写。
缺点:当数据量过大时,如数据集过百万时,仍有超时隐患。
真分页优化
优点:因是真分页方式,数据库处理效率非常快,效率是目前最高的。
缺点:当逻辑较复杂时,语句过于繁琐,不利于规范编写;且当表关联结构过于复杂,无统一关键字段时,将更加不便于编写。
为实现多关键字问题,又进行了改进,具体如下:
DECLARE @RecordCount INT; SET @RecordCount= (SELECT COUNT(1) FROM table1
JOIN table2 on 1.id=2.tb_id
WHERE 条件);
SELECT TOP 页大小 *
,@RecordCoun as RecordCoun FROM table1
JOIN table2 on 1.id=2.tb_id WHERE NOT EXISTS ( SELECT 1 FROM ( SELECT TOP 页大小*(页数-1)
table1.id as tb1,
table2 .id as tb2
FROM table1
JOIN table2 on 1.id=2.tb_id
WHERE 条件
ORDER BY 1.id,2.id ) A
WHERE A.tb1= 1.id and A.tb2=2.id ) ORDER BY 1.id,2.id