来自新手关于分页效率的疑惑
下面有两条查询语句都是查找数据表中第5 到第10条数据的,假设数据量很大,下面两条语句执行起来哪个效率会比较高?各有什么优缺点?
SELECT * FROM (SELECT (row_number() OVER (ORDER BY getdate ())) AS rownum,* FROM [DataTable]) t1 WHERE rownum BETWEEN 5 AND 10
SELECT TOP 5 * FROM T_Instrument WHERE id NOT IN (SELECT TOP 5 id FROM [DataTable])
貌似第一条子查询把整张表找出来筛选了,而第二条只把id列找出来筛选了,这样的理解对不对?
还有没不同的写法,效率如何?
欢迎指教!
------解决方案--------------------top倒腾法 不是这样用的
应该 取倒序的top 5从(取正序的top 10)
------解决方案--------------------SELECT * FROM (SELECT (row_number() OVER (ORDER BY getdate ())) AS rownum,* FROM [DataTable]) t1 WHERE rownum BETWEEN 5 AND 10
应该使用这种写法,最好能够指明排序方式,而不是用getdate()去排序
第二句你用到not in效率要差很多,这个函数会导致多次全表扫描
------解决方案--------------------呵呵,直接做个试验,进行比较:
--DROP TABLE xx
CREATE TABLE XX(
id INT IDENTITY(1,1) PRIMARY KEY,
v VARCHAR(10))
INSERT INTO xx
VALUES('aaa')
go 1000
--方法1
SELECT *
FROM
(
SELECT *,
ROW_NUMBER() OVER(ORDER BY id) AS rownum
FROM xx
)t
WHERE rownum BETWEEN 6 AND 10
/*
id v rownum
6 aaa 6
7 aaa 7
8 aaa 8
9 aaa 9
10 aaa 10
*/
--方法2
SELECT TOP 5 * FROM xx
WHERE id NOT IN (SELECT TOP 5 id FROM xx)
/*
id v
6 aaa
7 aaa
8 aaa
9 aaa
10 aaa
*/
------解决方案--------------------下面的图是,上面方法1和方法2 的执行计划,从执行计划中,可以很明显的看出,第1个方法的开销占35%,而第2个方法的开销占65%,很明显的,第1中row_number的方法效率更高:
方法1,用了1次聚集索引扫描,而方法2,用了2次聚集索引扫描,而且还用了嵌套循环连接,把2次扫描的结果集关联起来,所以并不是像你所说的,第二种not in的方法不会扫描,其实也好扫描的。
------解决方案--------------------通过输入set statistics io on 命令,我们可以看到,方法1是逻辑扫描2次,而方法2是扫描了22次,很明显,第2个方法的效率较差:
(5 行受影响)
表 'XX'。扫描计数 1,逻辑读取 2 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
(5 行受影响)
表 'XX'。扫描计数 2,逻辑读取 22 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。