导航:首页 > 网络数据 > 大数据sql分页查询

大数据sql分页查询

发布时间:2024-07-17 18:49:07

1. MySQL大数据量分页查询方法及其优化

使用子查询优化大数据量分页查询

这种方式的做法是先定位偏移位置的id,然后再往后查询,适用于id递增的情况。

使用id限定优化大数据量分页查询
使用这种方式需要先假设数据表的id是连续递增的,我们根据查询的页数和查询的记录数可以算出查询的id的范围,可以使用 id between and 来查询:

当然了,也可以使用in的方式来进行查询,这种方式经常用在多表关联的情况下,使用其他表查询的id集合来进行查询:

但是使用这种in查询方式的时候要注意的是,某些MySQL版本并不支持在in子句中使用limit子句。

参考 sql优化之大数据量分页查询(mysql) - yanggb - 博客园 (cnblogs.com)

2. 如果在数据库中有大数据量,而我们用分页存储过程,怎么样才能效率高

--------------------------------
--关于分页储存的效率问题
--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正好我正在研究这个问题 给大家分享

3. 大数据量实时统计排序分页查询 优化总结

大数据量实时统计排序分页查询 (并发数较小时) 的瓶颈不是函数(count,sum等)执行,

不是having, 也不是order by,甚至不是表join, 导致慢的原因就在于“数据量太大本身”

就是将表划分为M份相互独立的部分,可以是分表,也可以是不分表但冗余一个取模结果字段

实际结果是不分表比分表更加灵活,只需稍加配置,就可以动态切分大表,随意更改M的大小。

将1条慢sql(大于30秒)拆分成为N条查询速度巨快的sql(单条sql执行时间控制在20毫秒以内)

然后再web应用中以适当的线程数去并发查询这些执行时间快的N条小sql再汇总结果

第一步查询中去并发执行这N条小sql, 只取排序字段和标识字段,其他字段一律丢弃

汇总结果后定位出当前页面要显示的pageNum条数据,再进行第二步查询,取出页面上需要展示的所有字段

PS:这一点是至关重要的,其他几点都可以不看,这点是最关键的。慢慢解释一下:

a) 第一种方式是把数据库中所有记录(只取排序字段和标识字段并且不做任何sum,count having order by等操作)

全部拉到web应用中,在web应用中完成所有的计算

b) 第二种方式是把数据库中所有记录做sum count having等操作之后的所有行数拉到web应用中,在web应用中完成剩余计算

c) 第三种方式是把数据库中所有记录做sum count having order by等操作之后把limit后的数据拉到web应用中,

在web应用中对limit后的数据再计算

显然,第一种方式 数据库什么活都不做只取数据 是不可行的。以lg_order_count_seller为例,1500万行,

如果只算id, seller_id和order_count 这三个bigint类型,至少需要拉8*3*1500 0000 = 360000000=340M,

拉到内存中之后存储需要8*4*15000000= 460M,这还不算List是的2的n次方这个特点和计算排序等的内存开销,

不仅数据库与web应用机器IO扛不住,就是应用自身恐怕也要OOM了。

第二种方式,所有记录做sum count having等操作之后,由于是group by seller_id的,总得数据量变为100万(就是卖家总数),

这样子一来,共需要拉8*3*100 0000 = 23M,拉到内存之后,需要8*4*100 0000 = 30M, 再算上List是的2的n次方这个特点和

计算排序等的内存开销也不会超过100M, IO的时间和内存开销勉强可以考虑接受。

第三种方式,所有记录做sum count having order by等操作之后把limit后的数据拉到web应用中,因为做了limit,所以,

数据量很小了,无论是IO还是内存开销都已经很小了。可以忽略。

综合以上三种,第三种方式适用于页面的前n页和后n页,因为这个limit的数据量随着页数的增大而增大,

当大到每个切分后的小表的数据量时就转为第二种方式了。

第二种方式适用于页面的第[n+1, totaoPageNum-n]页。

切分成N条小sql后并行执行时排序不稳定性的解决办法

① 问题描述:

优化之前,还是是一条大慢sql查询时,由于数据库排序是稳定排序,

所以当两条记录排序字段值相同时他们在页面上的页码位置是固定的。

优化之后,当并行执行这N条小sql时,由于无法控制这些小sql的先后执行顺序,

导致在web应用中当两条记录的排序字段值相同时在页面上的页码位置是随机的。

② 解决办法:

除了拉标识字段(seller_id)和排序字段(order_count_sum)之外,再取一个unique(id)的字段,当两条记录的排序字段值相同时,再用这个unique的字段(在卖家监控中这个字段是id)进行第二次排序.这样就解决了排序不稳定的问题。

③ 也许,看到这里会有疑问,为什么不用seller_id?seller_id也是唯一, 这样子不是少取id这个字段,减少IO了?

seller_id虽然也是唯一,可以辅助排序,但是不要忘记数据库的排序规则是:

如果两列的值相等,那么序号在前的排在前面,这里的序号就是主键(自动生成,autoincrement),

如果用seller_id的话还是不能保证排序的稳定性,只能用主键id.

优先加载页面上的主要元素,然后再去异步加载次要元素,

反应在卖家监控页面中,查数据和查页页码的sql语句基本相同,是在竞争同一资源,

所以,需要做一个策略,优先把资源让给查数,数据查完之后再去查页码。

限流

由于多线程取数据并没有从本质上提高数据库性能,所以必须针对大数据量实时统计排序分页查询做限流

我这里打个比方:食堂有6个窗口,物流团队吃饭要买6个菜,平均每买1个菜需要1分钟的时间,

如果派我一个人去一个窗口买的话需要6分钟的时间

假如派6个人分别去6个窗口买这6个菜,只需要1分钟的时间

但是,如果除了物流团队,再来其他5个团队呢,也就是说6个团队每个团队买6个菜共买36个菜,

这样子有的团队先买完,有的团队后买完,但平均时间还是6分钟。本质上没有变化。

所以,对于特定的查询条件,必须进行限流。让每分钟至多有6个团队买菜,这样子能使得情况变得不至于太糟糕。

从根本上改变现状

这一点从目前来看只能是展望了,比如mysql数据库换更为强大的oracle数据库,

或更换InnoDb引擎为其他,或更换SATA硬盘为SSD 。。。。。。

从实践效果来看,优化后的效果是很明显的。

相同的查询条件,原来一个页面查询时间由于超过60秒超时了,根据1-6点建议优化之后,查询时间变为2秒至3.5秒之间。

4. sql怎么控制检索出的最大数据量,数量太大机器受不了,有能分批检索的命令吗

用分页查询算法来实现。给你一个我写的通用分页存储过程,将这个存储过程创建在你的SQL数据库上,调用该过程即可实现分页查询:

/*
通用存储过程
只要传入页码,每页大小,查询的sql语句,排序方式(不需要order)即可
*/
CREATE Procere [sp_common_cuspage3]
(
@PageNo int, --当前查询页码
@PageSize int, --每页数量
@sql nvarchar(2000), --查询的SQL语句
@order nvarchar(200), --排序方式,例如:ResID desc
@totalcount int out --返回当前查询SQL的符合总条数
)
AS
Begin
declare @querysql nvarchar(2000)
declare @countsql nvarchar(2000)
declare @begin int
declare @end int
declare @totalPage int

--查询符合条件的条目数
set @countsql = N'select @count = count(*) from ('+@sql + N')G0'
exec sp_executesql @countsql, N' @count int output ', @totalcount output

--计算总页码及纠正当前页码
set @totalPage = (@totalcount-1)/@PageSize +1
IF(@PageNo > @totalPage ) set @PageNo = @totalPage

--计算起止位置
set @begin = @PageSize * (@PageNo-1)
set @end = @PageSize * @PageNo +1

--组合出SQL进行查询
set @querysql = N'select * from ('
set @querysql = @querysql + N' SELECT Row_Number() OVER(ORDER BY ' + @order + N' ) as RowID ,G0.* FROM ('
set @querysql = @querysql + @sql
set @querysql = @querysql + N' ) G0 ) G1'
set @querysql = @querysql + N' Where G1.RowID >' + CAST(@begin as nvarchar) + N' AND G1.RowID<'+CAST(@end as nvarchar)

--print @querysql
exec(@querysql)
End

阅读全文

与大数据sql分页查询相关的资料

热点内容
小米平板2win10刷miui教程 浏览:204
wordpress时区 浏览:96
手机如何录制音频文件 浏览:594
excel数据相对超链接怎么用 浏览:799
word乱码修复器免费 浏览:101
夏花网站存在多少年了 浏览:671
无线模块下载哪个app 浏览:584
河北银行app怎么查开户行 浏览:936
华为路由器的数据配置文件 浏览:508
文件名字复制为路径导入表格 浏览:324
点击电脑桌面文件总是跳出磁盘 浏览:857
桌面文件不刷新 浏览:114
linux怎么列举子文件夹 浏览:949
查看编程代码的软件有哪些 浏览:171
可以看文件有多少个字的软件 浏览:857
苹果没有appstore如何充值 浏览:845
好人平安哪个app上能看 浏览:663
如何用微信发送不同文件夹 浏览:935
英制扣怎么编程 浏览:957
win10如何启动小娜 浏览:933

友情链接