当前位置: 首页 > news >正文

真正高效的SQLSERVER分页查询(多种方案)

yuanwen:http://www.jb51.net/article/35212.htm

Sqlserver数据库分页查询一直是Sqlserver的短板,闲来无事,想出几种方法,假设有表ARTICLE,字段ID、YEAR...(其他省略),数据53210条(客户真实数据,量不大),分页查询每页30条,查询第1500页(即第45001-45030条数据),字段ID聚集索引,YEAR无索引,Sqlserver版本:2008R2 
第一种方案、最简单、普通的方法: 

复制代码代码如下:

SELECT TOP 30 * FROM ARTICLE WHERE ID NOT IN(SELECT TOP 45000 ID FROM ARTICLE ORDER BY YEAR DESC, ID DESC) ORDER BY YEAR DESC,ID DESC 


平均查询100次所需时间:45s 
第二种方案: 

复制代码代码如下:

SELECT * FROM (  SELECT TOP 30 * FROM (SELECT TOP 45030 * FROM ARTICLE ORDER BY YEAR DESC, ID DESC) f ORDER BY f.YEAR ASC, f.ID DESC) s ORDER BY s.YEAR DESC,s.ID DESC 


平均查询100次所需时间:138S 
第三种方案: 

复制代码代码如下:

SELECT * FROM ARTICLE w1, 

SELECT TOP 30 ID FROM 

SELECT TOP 50030 ID, YEAR FROM ARTICLE ORDER BY YEAR DESC, ID DESC 
) w ORDER BY w.YEAR ASC, w.ID ASC 
) w2 WHERE w1.ID = w2.ID ORDER BY w1.YEAR DESC, w1.ID DESC 


平均查询100次所需时间:21S 
第四种方案: 

复制代码代码如下:

SELECT * FROM ARTICLE w1 
WHERE ID in 

SELECT top 30 ID FROM 

SELECT top 45030 ID, YEAR FROM ARTICLE ORDER BY YEAR DESC, ID DESC 
) w ORDER BY w.YEAR ASC, w.ID ASC 

ORDER BY w1.YEAR DESC, w1.ID DESC 


平均查询100次所需时间:20S 
第五种方案: 

复制代码代码如下:

SELECT w2.n, w1.* FROM ARTICLE w1, (   
SELECT TOP 50030 row_number() OVER (ORDER BY YEAR DESC, ID DESC) n, ID FROM ARTICLE 
) w2 WHERE w1.ID = w2.ID AND w2.n > 50000 ORDER BY w2.n ASC 


平均查询100次所需时间:15S 
查询第1000-1030条记录 
第一种方案: 

复制代码代码如下:

SELECT TOP 30 * FROM ARTICLE WHERE ID NOT IN(SELECT TOP 1000 ID FROM ARTICLE ORDER BY YEAR DESC, ID DESC) ORDER BY YEAR DESC,ID DESC 


平均查询100次所需时间:80s 
第二种方案: 

复制代码代码如下:

SELECT * FROM (    
SELECT TOP 30 * FROM (SELECT TOP 1030 * FROM ARTICLE ORDER BY YEAR DESC, ID DESC) f ORDER BY f.YEAR ASC, f.ID DESC 
) s ORDER BY s.YEAR DESC,s.ID DESC 


平均查询100次所需时间:30S 
第三种方案: 

复制代码代码如下:

SELECT * FROM ARTICLE w1, 

SELECT TOP 30 ID FROM 

SELECT TOP 1030 ID, YEAR FROM ARTICLE ORDER BY YEAR DESC, ID DESC 
) w ORDER BY w.YEAR ASC, w.ID ASC 
) w2 WHERE w1.ID = w2.ID ORDER BY w1.YEAR DESC, w1.ID DESC 


平均查询100次所需时间:12S 
第四种方案: 

复制代码代码如下:

SELECT * FROM ARTICLE w1 
WHERE ID in 

SELECT top 30 ID FROM 

SELECT top 1030 ID, YEAR FROM ARTICLE ORDER BY YEAR DESC, ID DESC 
) w ORDER BY w.YEAR ASC, w.ID ASC 

ORDER BY w1.YEAR DESC, w1.ID DESC 


平均查询100次所需时间:13S 
第五种方案: 

复制代码代码如下:

SELECT w2.n, w1.* FROM ARTICLE w1,(    
SELECT TOP 1030 row_number() OVER (ORDER BY YEAR DESC, ID DESC) n, ID FROM ARTICLE 
) w2 WHERE w1.ID = w2.ID AND w2.n > 1000 ORDER BY w2.n ASC 


平均查询100次所需时间:14S 
由此可见在查询页数靠前时,效率3>4>5>2>1,页码靠后时5>4>3>1>2,再根据用户习惯,一般用户的检索只看最前面几页,因此选择3 4 5方案均可,若综合考虑方案5是最好的选择,但是要注意SQL2000不支持row_number()函数,由于时间和条件的限制没有做更深入、范围更广的测试,有兴趣的可以仔细研究下。 
以下是根据第四种方案编写的一个分页存储过程: 

复制代码代码如下:

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[sys_Page_v2]') and OBJECTPROPERTY(id, N'IsProcedure') = 1) 
drop procedure [dbo].[sys_Page_v2] 
GO 
CREATE PROCEDURE [dbo].[sys_Page_v2] 
@PCount int output, --总页数输出 
@RCount int output, --总记录数输出 
@sys_Table nvarchar(100), --查询表名 
@sys_Key varchar(50), --主键 
@sys_Fields nvarchar(500), --查询字段 
@sys_Where nvarchar(3000), --查询条件 
@sys_Order nvarchar(100), --排序字段 
@sys_Begin int, --开始位置 
@sys_PageIndex int, --当前页数 
@sys_PageSize int --页大小 
AS 
SET NOCOUNT ON 
SET ANSI_WARNINGS ON 
IF @sys_PageSize < 0 OR @sys_PageIndex < 0 
BEGIN 
RETURN 
END 
DECLARE @new_where1 NVARCHAR(3000) 
DECLARE @new_order1 NVARCHAR(100) 
DECLARE @new_order2 NVARCHAR(100) 
DECLARE @Sql NVARCHAR(4000) 
DECLARE @SqlCount NVARCHAR(4000) 
DECLARE @Top int 
if(@sys_Begin <=0) 
set @sys_Begin=0 
else 
set @sys_Begin=@sys_Begin-1 
IF ISNULL(@sys_Where,'') = '' 
SET @new_where1 = ' ' 
ELSE 
SET @new_where1 = ' WHERE ' + @sys_Where 
IF ISNULL(@sys_Order,'') <> '' 
BEGIN 
SET @new_order1 = ' ORDER BY ' + Replace(@sys_Order,'desc','') 
SET @new_order1 = Replace(@new_order1,'asc','desc') 
SET @new_order2 = ' ORDER BY ' + @sys_Order 
END 
ELSE 
BEGIN 
SET @new_order1 = ' ORDER BY ID DESC' 
SET @new_order2 = ' ORDER BY ID ASC' 
END 
SET @SqlCount = 'SELECT @RCount=COUNT(1),@PCount=CEILING((COUNT(1)+0.0)/' 
+ CAST(@sys_PageSize AS NVARCHAR)+') FROM ' + @sys_Table + @new_where1 
EXEC SP_EXECUTESQL @SqlCount,N'@RCount INT OUTPUT,@PCount INT OUTPUT', 
@RCount OUTPUT,@PCount OUTPUT 
IF @sys_PageIndex > CEILING((@RCount+0.0)/@sys_PageSize) --如果输入的当前页数大于实际总页数,则把实际总页数赋值给当前页数 
BEGIN 
SET @sys_PageIndex = CEILING((@RCount+0.0)/@sys_PageSize) 
END 
set @sql = 'select '+ @sys_fields +' from ' + @sys_Table + ' w1 ' 
+ ' where '+ @sys_Key +' in (' 
+'select top '+ ltrim(str(@sys_PageSize)) +' ' + @sys_Key + ' from ' 
+'(' 
+'select top ' + ltrim(STR(@sys_PageSize * @sys_PageIndex + @sys_Begin)) + ' ' + @sys_Key + ' FROM ' 
+ @sys_Table + @new_where1 + @new_order2 
+') w ' + @new_order1 
+') ' + @new_order2 
print(@sql) 
Exec(@sql) 
GO 

转载于:https://www.cnblogs.com/newcoder/p/4186510.html

相关文章:

  • KVM虚拟化技术简介
  • 【Spark亚太研究院系列丛书】Spark实战高手之路-第3章Spark架构设计与编程模型第3节②...
  • 我对于 setWindow, setViewPort 与 translate 的理解
  • DG_Oracle DataGuard Failover主备节点切换(案例)
  • 怎样设计接口?
  • 选择器,可选择通道和选择键类
  • Java中有关Null的9件事
  • 数据结构与算法JavaScript (二) 队列
  • JavaScript编写了一个计时器
  • 基于 jQuery 实现的精致作品集图片导航效果
  • 这两天自己模仿写的一个Asp.Net的显示分页方法 附加实体转换和存储过程
  • show processlist 执行状态分析
  • 登陆oracle慢原因分析和解决方案
  • 多线程和多进程的差别(小结)
  • 常见Exchange 邮件黑名单移除方法
  • python3.6+scrapy+mysql 爬虫实战
  • 【每日笔记】【Go学习笔记】2019-01-10 codis proxy处理流程
  • 【面试系列】之二:关于js原型
  • CSS选择器——伪元素选择器之处理父元素高度及外边距溢出
  • iOS仿今日头条、壁纸应用、筛选分类、三方微博、颜色填充等源码
  • k个最大的数及变种小结
  • npx命令介绍
  • Shadow DOM 内部构造及如何构建独立组件
  • Vue2.0 实现互斥
  • 服务器之间,相同帐号,实现免密钥登录
  • 复杂数据处理
  • 关于 Cirru Editor 存储格式
  • 区块链分支循环
  • 王永庆:技术创新改变教育未来
  • 学习HTTP相关知识笔记
  • 怎样选择前端框架
  • Android开发者必备:推荐一款助力开发的开源APP
  • 我们雇佣了一只大猴子...
  • ​LeetCode解法汇总2808. 使循环数组所有元素相等的最少秒数
  • ​卜东波研究员:高观点下的少儿计算思维
  • ​一些不规范的GTID使用场景
  • (4.10~4.16)
  • (poj1.3.2)1791(构造法模拟)
  • (第9篇)大数据的的超级应用——数据挖掘-推荐系统
  • (三分钟了解debug)SLAM研究方向-Debug总结
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (一)WLAN定义和基本架构转
  • (转)Android学习系列(31)--App自动化之使用Ant编译项目多渠道打包
  • (转)详解PHP处理密码的几种方式
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .net 7 上传文件踩坑
  • .NET 程序如何获取图片的宽高(框架自带多种方法的不同性能)
  • .Net(C#)自定义WinForm控件之小结篇
  • .NET基础篇——反射的奥妙
  • /run/containerd/containerd.sock connect: connection refused
  • @Import注解详解
  • @Responsebody与@RequestBody
  • @selector(..)警告提示
  • [ vulhub漏洞复现篇 ] Apache Flink目录遍历(CVE-2020-17519)
  • [ 常用工具篇 ] POC-bomber 漏洞检测工具安装及使用详解