一次关于sqlserver查询分页的实践

前几天因为工作需要,将sqlserver库里所有的表导入oracle中,因为需要数据上的转换,所以自己写了个库转换程序。编程语言采用java。
前期开发工作很顺利,因为库的数据比较大,所以采用分页查询导出的方式,每次一万条数据。既然分页,很自然想到了采用row_number()的方式。
一次关于sqlserver查询分页的实践
那么准备开始跑程序,刚开始很好,速度很快,几毫秒噢。不错不错。但是跑着跑着就发现不对了,怎么越到后面,这一万条数据越慢,从几毫秒慢慢的涨到几百毫秒,果断关闭程序,排查原因。于是又找到了第二种办法,offset…fetch next
一次关于sqlserver查询分页的实践
又开始跑程序,哇,这次一开始比第一次更快,但是跑着跑着,也是速度越来越慢。
于是乎又是关掉程序,排查原因。
既然我只是想要简单的拿出表里的数据,而且也是根据主键进行分页,何必采用前两种那么麻烦的方式,要重新生成行号进行分页取呢,如果简单暴力,直接以主键分页取,因为主键本身是排序过的,速度是不是更快。
于是乎上第三种方案,直接采用top的形式,每次取完之后,记录最后一行的主键数据。
一次关于sqlserver查询分页的实践
再跑程序,果然每次取一万条的数据速度基本是一样的,2毫秒。
为了佐证这个结果,我也做了小小的实验
一次关于sqlserver查询分页的实践
如上图,实验8 9 10分别对应以上的第1 2 3 中语句的查询结果,而且查询数据是0-10000条。可以看到,试验10的等待时间最小,具有小小的优势,试验9次之。
那么查询第1000000-1010000条数据结果如何呢?
一次关于sqlserver查询分页的实践
依然是试验8 9 10 我们可以看到试验8 和9出现了明显的增长,而10和之前保持一样。
从这我们不难得出,如果只是采用我当前这种以主键为条件的简单分页的话,查询优势top>fetch next>row_number()
当然,如果是联合查询,我相信top的优势应该是荡然无存的,所以不同的场合,我们应该使用不同的sql。