A. Oracle等数据库数据量特别大的时候怎样从程序和SQL语句方面优化使查询速度加快
一般最抄常用的大数据量优袭化:
1、创建分区表,使查询时的大表尽量分割成小表。Oracle提供范围分区、列表分区、Hash分区以及复合分区,具体选择哪种分区最优,需要根据你的业务数据来确定。
2、创建索引,创建合适的索引可以大大提高查询速度。但是你的这张大表如果会频繁的进行update、insert等操作,索引会导致这些操作变慢。就有可能需要进行动态索引的使用。
3、优化复杂SQL;对复杂的SQL进行合理的优化,这个有时候也需要根据你的数据情况来优化,可以参考一些SQL语句优化方面的文档。
B. Oracle的极大数据量的分页查询问题
1.把星都换成需要的字段名试一下。
2.索引顺序排列正确(这个你查一下,索内引不是建 了就可以。查询容时有顺序的,四年前的项目,改变顺序后,时间由35s 提升到6-8s,具体的记不清了,只记得有这么回事。)
回去以后试一下你的SQL,只有数据多才出现这个问题吗?字段长度大约都多少?
C. 网上很多人说oracle 11g在处理大数据分页时用rowid比rownum效率快很多,求rowid和rownum分页效率原理
rownum和rowid是两种不同的东西,不知道你如何利用rowid来分页?
rownum是返回的记录编号。回rowid可理解为返回记录的答实际地址。
当根据rowid访问时相当于不经查询直接取数,用rownum必须经过查询(即数据库里有查询动作)。如果已经知道了rowid再去获取数据和通过rownum计数去获取数据,肯定用rowid快。
实际上,由于oracle不支持的真正的分页查询,所谓分页,是先把数据从数据库中查询出来,然后再把对应页的数据返回给调用者,剩余的数据扔掉了。所以,这种情况下,注定用rowid不如用rownum快。
D. oracle数据库,搜索百万级别数据分页优化问题
oracle count 百万级 分页查询记录总数、总条数优化
Oracle count 百万级 查询记录总数、总条数优化
最近做一个项目时,做分页时,发现分页查询速度很慢,分页我做的是两次查询,一次是查询总数,一次是查询分页结果
[java] view plain
/** 查询总记录数 **/
SELECT
COUNT(id)
FROM
USER
order by
id
/** 查询结果集 **/
select
*
from
( select
row_.*,
rownum rownum_
from
( select
id ,
user_number,
user_name,
user_password,
sex,
Registered_time,
last_login_time,
post
from
USER u
order by
u.id) row_
where
rownum <= ?
)
where
rownum_ > ?
user表中的记录是128万多条,这个是没有查询条件时的查询,也就是用户刚刚进入模块时的查询,发现查询时间是2566ms~2152ms之间,单独执行每条语句,发现第一条的执行时间在2000ms以上,在PL/SQL中执行的结果也证实了我的判断。所以要对select count语句进行优化。
在网上找了很多优化方案,大多不尽人意,(分表的方式听上去不错,不过由于单表是历史原因,这里就不作考虑)。最后找到一个比较令人满意的答。就是在语句中加入 /*+ROWID(USER)*/或者/*+ INDEX(USER ID) */ 来提高查询效果。
听说这个就是强制使用索引统计结果?如果有哪位大虾能把原理详细告诉我,请来多多指点!
[java] view plain
SELECT /*+ROWID(USER)*/ count(*) FROM USER t
或者
SELECT /*+ INDEX(USER ID) */ count(*) FROM USER t
使用后,单条统计总数的查询在800ms左右,分页查询结果基本在900ms~950ms之间,基本在一秒之内,达到了当初设计需求。
当然,这个是没有加查询条件的,当把查询条件加入后,不管前面加不加强制索引,结果时间都在2000ms之间,所以,如果要进行有条件的查询,就要在where条件中进行优化。特别注意条件字段查询前后顺序。
E. Oracle 数据量非常大(上亿)时,使用存储过程中的游标返回分页查询的10条记录非常耗时,请问如何优化
With New_Table As
(Select Logid, No, Opttime, Rownum As Row_Num
From T_Tab_Log
Where Part_Date = ?)
Select Logid, No
From New_Table t
Where T.Row_Num <= ? And T.Row_Num >= ?
Order By Opttime Desc;
F. 大数据量实时统计排序分页查询 优化总结
大数据量实时统计排序分页查询 (并发数较小时) 的瓶颈不是函数(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秒之间。
G. 如果在数据库中有大数据量,而我们用分页存储过程,怎么样才能效率高
--------------------------------
--关于分页储存的效率问题
--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正好我正在研究这个问题 给大家分享