sqlserver高效分页
Ⅰ sqlserver 聚合 如何分页
我看没人回答我再上。
-----------------------------
这个用子查询就可以了!如果嵌套很多,证明你的数据库设计很蹩脚。
给你个例子:
----------
SELECT TOP 10
convert(varchar(10),K.ID) as ID,
convert(varchar(20),convert(decimal(18,2),K.SumRealSaleCost)) as SumRealSaleCost,
K.CountRes
from
(
select
ROW_NUMBER() OVER (ORDER BY GetDate()) AS ID,
(sum(M.Sale) over()-sum(M.ReturnSaleCost) over()) as SumRealSaleCost,
count(*) over() as CountRes
from
(
---这里你爱用什么聚合函数就用什么聚合函数,我只用了一个简单的子查询而已!
select
A.Sale,
A.ReturnSaleCost
from ProctStore A
) M
) K
where K.ID >?
--这个排序最好和分页函数一致。
ORDER BY K.Sale DESC
--------------------
最外层为类型转化层
中间是数据逻辑层
最内层就是集合构建层
我这种写法很多人不理解,本人原创。你网络不到!
---------------------
如果LZ数据库有功底的话,加入我的团队吧!数据库聚贤庄
Ⅱ 几种常见SQL分页方式效率比较,一帖子
sqlserver分页 第一种分页方法 需用到的参数: pageSize 每页显示多少条数据 pageNumber 页数 从客户端传来 totalRecouds 表中的总记录数 select count (*) from 表名 totalPages 总页数 totalPages=totalRecouds%pageSize==0?totalRecouds/pageSize:totalRecouds/pageSize+1 pages 计算前pages 条数据 pages= pageSize*(pageNumber-1) SQL语句: select top pageSize * from 表名 where id not in (select top pages id from 表名 order by id) order by id 第二种分页方法 pageSize 每页显示多少条数据 pageNumber 页数 从客户端传来 pages=pageSize*(pageNumber-1)+1 select top pageSize * from 表名 where id>=(select max(id) from (select top pages id from 表名 order by id asc ) t ) mysql分页 需用到的参数: pageSize 每页显示多少条数据 pageNumber 页数 从客户端传来 totalRecouds 表中的总记录数 select count (*) from 表名 totalPages 总页数 totalPages=totalRecouds%pageSize==0?totalRecouds/pageSize:totalRecouds/pageSize+1 pages 起始位置 pages= pageSize*(pageNumber-1) SQL语句: select * from 表名 limit pages, pageSize; mysql 分页依赖于关键字 limit 它需两个参数:起始位置和pageSize 起始位置=页大小*(页数-1) 起始位置=pageSize*(pageNumber -1) oracle分页 pageSize 每页显示多少条数据 pageNumber 页数 从客户端传来 totalRecouds 表中的总记录数 select count (*) from 表名 totalPages 总页数 totalPages=totalRecouds%pageSize==0?totalRecouds/pageSize:totalRecouds/pageSize+1 startPage 起始位置 startPage= pageSize*(pageNumber-1)+1 endPage=startPage+pageSize SQL语句 select a.* from ( select rownum num ,t.* from 表名 t where 某列=某值 order by id asc )a where a.num>=startPage and a.num<endPage db2分页 int startPage=1 //起始页 int endPage; //终止页 int pageSize=5; //页大小 int pageNumber=1 //请求页 startPage=(pageNumber-1)*pageSize+1 endPage=(startPage+pageSize); SQL语句 select * from (select 字段1,字段2,字段3,字段4,字段5,rownumber() over(order by 排序字段 asc ) as rowid from 表名 )as a where a.rowid >= startPage AND a.rowid <endPage access分页 pageSize 每页显示多少条数据 pageNumber 页数 从客户端传来 pages=pageSize*(pageNumber-1)+1 SQL语句 select top pageSize * from 表名 where id>=(select max(id) from (select top pages id from 表名 order by id asc ) t )
Ⅲ sqlserver2000 如何提高分页查询大数据量的效率
sqlserver2005及以上的版本有row_number()函数可以高效分页,sqlserver2000的话只能看算法了
Ⅳ sqlserver查询分页问题,条件比较复杂,怎样实现较好求指点
尽量不要使用嵌套子查询,优先使用连接子查询;
In 关键字尽量少使用,效率低,除非 in 包含的信息量非常少,并且叫固定;
如果查询条件和查询结果表无直接关联,优先根据查询条件查询出符合条件的临时结果值,然后和最终结果表关联;
除 top n 方式分页之外,使用 row_number() over 方式分页也可以;
能明确指定结果字段的,尽量不要用 * ;
不相关的字段可以省略;
如果最终结果表数据比较大,考虑分表,分区,分库;
查询结果表字段尽量不要包含大文本之类的字段;
where 条件中对于varchar 字段 的 like 查询要适度,不要用太多,会影响效率;
Ⅳ 如何优化Mysql千万级快速分页
很多应用往往只展示最新或最热门的几条记录,但为了旧记录仍然可访问,所以就需要个分页的导航栏。然而,如何通过MySQL更好的实现分页,始终是比较令人头疼的问题。虽然没有拿来就能用的解决办法,但了解数据库的底层或多或少有助于优化分页查询。
我们先从一个常用但性能很差的查询来看一看。
SELECT *
FROM city
ORDER BY id DESC
LIMIT 0, 15
这个查询耗时0.00sec。So,这雀则个查询有什么问题呢?实际上,这个查询语句和参数都没有问题,因为它用到了下面表的主键,而且只读取15条记录。
CREATE TABLE city (
id int(10) unsigned NOT NULL AUTO_INCREMENT,
city varchar(128) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;
真正的问题在于offset(分页偏移量)很大的时候,像下面这样:
SELECT *
FROM city
ORDER BY id DESC
LIMIT 100000, 15;
上面的查询在有2M行记录时需要0.22sec,通过EXPLAIN查看SQL的执行计划可以发现该SQL检索了100015行,但最后只需要15行。大的分页偏移量会增加使用的数据,MySQL会将大量最终不会使用的数据加载到内存中。就算我们假设大部分网站的用户只访问前几页数据,但少量的大的分页偏移量的请求也会对整个系统造成危害。Facebook意识到了这一点,但Facebook并没有为了每秒可以处理更多的请求而去优化数据库,而是将重心放在将请求响应时间的方差变小。
对于分页请求,还有一个信息也很重要,就是总共的记录数。我们可以通过下面的查询很容易的获取总的记录数。
SELECT COUNT(*)
FROM city;
然而,上面的SQL在采用InnoDB为存储引擎时需要耗费9.28sec。一个不正确的优化是采用 SQL_CALC_FOUND_ROWS,SQL_CALC_FOUND_ROWS 可以在能够在分启岁历页查询时事先准备好符合条件的记录数,随后只要执行一句 select FOUND_ROWS(); 就能获得总记录数。但是在大多数情况下,查询语句简短并不意味着性能的提高。不幸的是,这种分页查询方式在许多主流框架中都有用到,下面看看这个语句的查询性能。
SELECT SQL_CALC_FOUND_ROWS *
FROM city
ORDER BY id DESC
LIMIT 100000, 15;
这个语句耗时20.02sec,是上一个的两倍。事实证明使用 SQL_CALC_FOUND_ROWS 做分页是很糟糕的想法。
下面来看看到底如何优化。文章分为两部分,第一部分是如何获取记录的总数目,第二部分是获取真正的记录。
高效的计算行数
如果采用的引擎是MyISAM,可以直接执行COUNT(*)去获取行数即可。相悄搜似的,在堆表中也会将行数存储到表的元信息中。但如果引擎是InnoDB情况就会复杂一些,因为InnoDB不保存表的具体行数。
我们可以将行数缓存起来,然后可以通过一个守护进程定期更新或者用户的某些操作导致缓存失效时,执行下面的语句:
SELECT COUNT(*)
FROM city
USE INDEX(PRIMARY);
获取记录
下面进入这篇文章最重要的部分,获取分页要展示的记录。上面已经说过了,大的偏移量会影响性能,所以我们要重写查询语句。为了演示,我们创建一个新的表“news”,按照时事性排序(最新发布的在最前面),实现一个高性能的分页。为了简单,我们就假设最新发布的新闻的Id也是最大的。
CREATE TABLE news(
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(128) NOT NULL
) ENGINE=InnoDB;
一个比较高效的方式是基于用户展示的最后一个新闻Id。查询下一页的语句如下,需要传入当前页面展示的最后一个Id。
SELECT *
FROM news WHERE id < $last_id
ORDER BY id DESC
LIMIT $perpage
查询上一页的语句类似,只不过需要传入当前页的第一个Id,并且要逆序。
SELECT *
FROM news WHERE id > $last_id
ORDER BY id ASC
LIMIT $perpage
上面的查询方式适合实现简易的分页,即不显示具体的页数导航,只显示“上一页”和“下一页”,例如博客中页脚显示“上一页”,“下一页”的按钮。但如果要实现真正的页面导航还是很难的,下面看看另一种方式。
SELECT id
FROM (
SELECT id, ((@cnt:= @cnt + 1) + $perpage - 1) % $perpage cnt
FROM news
JOIN (SELECT @cnt:= 0)T
WHERE id < $last_id
ORDER BY id DESC
LIMIT $perpage * $buttons
)C
WHERE cnt = 0;
通过上面的语句可以为每一个分页的按钮计算出一个offset对应的id。这种方法还有一个好处。假设,网站上正在发布一片新的文章,那么所有文章的位置都会往后移一位,所以如果用户在发布文章时换页,那么他会看见一篇文章两次。如果固定了每个按钮的offset Id,这个问题就迎刃而解了。Mark Callaghan发表过一篇类似的博客,利用了组合索引和两个位置变量,但是基本思想是一致的。
如果表中的记录很少被删除、修改,还可以将记录对应的页码存储到表中,并在该列上创建合适的索引。采用这种方式,当新增一个记录的时候,需要执行下面的查询重新生成对应的页号。
SET p:= 0;
UPDATE news SET page=CEIL((p:= p + 1) / $perpage) ORDER BY id DESC;
当然,也可以新增一个专用于分页的表,可以用个后台程序来维护。
UPDATE pagination T
JOIN (
SELECT id, CEIL((p:= p + 1) / $perpage) page
FROM news
ORDER BY id
)C
ON C.id = T.id
SET T.page = C.page;
现在想获取任意一页的元素就很简单了:
SELECT *
FROM news A
JOIN pagination B ON A.id=B.ID
WHERE page=$offset;
还有另外一种与上种方法比较相似的方法来做分页,这种方式比较试用于数据集相对小,并且没有可用的索引的情况下—比如处理搜索结果时。在一个普通的服务器上执行下面的查询,当有2M条记录时,要耗费2sec左右。这种方式比较简单,创建一个用来存储所有Id的临时表即可(这也是最耗费性能的地方)。
CREATE TEMPORARY TABLE _tmp (KEY SORT(random))
SELECT id, FLOOR(RAND() * 0x8000000) random
FROM city;
ALTER TABLE _tmp ADD OFFSET INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, DROP INDEX SORT,ORDER BY random;
接下来就可以向下面一样执行分页查询了。
SELECT *
FROM _tmp
WHERE OFFSET >= $offset
ORDER BY OFFSET
LIMIT $perpage;
简单来说,对于分页的优化就是。。。避免数据量大时扫描过多的记录。
Ⅵ 如果在数据库中有大数据量,而我们用分页存储过程,怎么样才能效率高
--------------------------------
--关于分页储存的效率问题
--5个存储过程都是采用不同的方式
--------------------------------
------------------------------------------
--利用select top 和select not in进行分页--
------------------------------------------
create procere proc_paged_with_notin --利用select top and select not in
(
@pageIndex int, --页索引
@pageSize int --每页记录数
)
as
begin
set nocount on;
declare @timediff datetime --耗时
declare @sql nvarchar(500)
select @timediff=Getdate()
set @sql='select top '+str(@pageSize)+' * from tb_TestTable where(ID not in(select top '+str(@pageSize*@pageIndex)+' id from tb_TestTable order by ID ASC)) order by ID'
execute(@sql) --因select top后不支技直接接参数,所以写成了字符串@sql
select datediff(ms,@timediff,GetDate()) as 耗时
set nocount off;
endexec proc_paged_with_notin 10000,10
--------------------------------------
--利用select top 和 select max(列键)--
--------------------------------------
create procere proc_paged_with_selectMax --利用select top and select max(列)
(
@pageIndex int, --页索引
@pageSize int --页记录数
)
as
begin
set nocount on;
declare @timediff datetime
declare @sql nvarchar(500)
select @timediff=Getdate()
set @sql='select top '+str(@pageSize)+' * From tb_TestTable where(ID>(select max(id) From (select top '+str(@pageSize*@pageIndex)+' id From tb_TestTable order by ID) as TempTable)) order by ID'
execute(@sql)
select datediff(ms,@timediff,GetDate()) as 耗时
set nocount off;
end--------------------------------------------------------
--利用select top和中间变量--此方法因网上有人说效果最佳--
--------------------------------------------------------
create procere proc_paged_with_Midvar --利用ID>最大ID值和中间变量
(
@pageIndex int,
@pageSize int
)
as
declare @count int
declare @ID int
declare @timediff datetime
declare @sql nvarchar(500)
begin
set nocount on;
select @count=0,@ID=0,@timediff=getdate()
select @count=@count+1,@ID=case when @count<=@pageSize*@pageIndex then ID else @ID end from tb_testTable order by id
set @sql='select top '+str(@pageSize)+' * from tb_testTable where ID>'+str(@ID)
execute(@sql)
select datediff(ms,@timediff,getdate()) as 耗时
set nocount off;
end
---------------------------------------------------------------------------------------
--利用Row_number() 此方法为SQL server 2005中新的方法,利用Row_number()给数据行加上索引--
---------------------------------------------------------------------------------------
create procere proc_paged_with_Rownumber --利用SQL 2005中的Row_number()
(
@pageIndex int,
@pageSize int
)
as
declare @timediff datetime
begin
set nocount on;
select @timediff=getdate()
select * from (select *,Row_number() over(order by ID asc) as IDRank from tb_testTable) as IDWithRowNumber where IDRank>@pageSize*@pageIndex and IDRank<@pageSize*(@pageIndex+1)
select datediff(ms,@timediff,getdate()) as 耗时
set nocount off;
end
--------------------------
--利用临时表及Row_number--
--------------------------
create procere proc_CTE --利用临时表及Row_number
(
@pageIndex int, --页索引
@pageSize int --页记录数
)
as
set nocount on;
declare @ctestr nvarchar(400)
declare @strSql nvarchar(400)
declare @datediff datetime
begin
select @datediff=GetDate()
set @ctestr='with Table_CTE as
(select ceiling((Row_number() over(order by ID ASC))/'+str(@pageSize)+') as page_num,* from tb_TestTable)';
set @strSql=@ctestr+' select * From Table_CTE where page_num='+str(@pageIndex)
end
begin
execute sp_executesql @strSql
select datediff(ms,@datediff,GetDate())
set nocount off;
end
我们分别在每页10条数据的情况下在第2页,第1000页,第10000页,第100000页,第199999页进行测试,耗时单位:ms 每页测试5次取其平均值 存过第2页耗时第1000页耗时第10000页耗时第100000页耗时第199999页耗时效率排行1用not in0ms16ms47ms475ms953ms32用select max5ms16ms35ms325ms623ms13中间变量_number0ms0ms34ms365ms710ms24临时表780ms796ms798ms780ms805ms4正好我正在研究这个问题 给大家分享
Ⅶ sqlserver分页查询,谁给我解释解释啊为什么这个效率就高,看不懂是怎么查询的
简单点说 就好比 现在有 100斤的东西 不分页就是直接拿100斤 sqlserver分页 就是一次拿20斤 你说哪个拿得快一点
Ⅷ 数据库sqlserver如何用存储过程做分页
存储过程:create Procere pname
( @pageIndex int,@pageSize)
as
select * from tableName order by id
offset @pageIndex * pageSize fetch next pageSize rows only
分页:
sqlserver 在2008之前 使用 top 和 not int top 的方式来做分页
2008以后使用 row_number() 函数作为分页关键函数
2012使用 offset 1 fetch next 10 rows only
你问了2个问题,你可以优先把视图,存储过程,触发器等弄明白,分页是查询,在存储过程里可以写复杂的sql文,只是在运行时是预编译和参数化查询防止sql注入