您的位置:首页 > 数据库

我的数据库每天数据量目前高达7000万条插入!可能还要提高!

2006-06-04 16:19 399 查看
violing
资深会员

我的数据库每天数据量目前高达7000万条插入!可能还要提高!

这么极端的情况我还得进行各种各样的统计,其中不乏难度比较大的统计工作,没想到经过我的潜心研究竟然工作得爽爽的!搞得我特有成就感!
这个表t的列很多,其中比较重要的列有以下几个:
nr varchar2(256)
sj date

其中有一个统计是对t表其中一列nr varchar2(256)进行,统计每十分钟执行一次,要统计sj从当前时间开始往以前24小时,其中nr重复超过一个设定值(比如100)的时候就产生一条记录插入到一个统计表gb中,此表中要有
nr varchar2(256) ,
sj1 date (统计开始时间),
sj2 date (统计结束时间),
sl number(10) (重复数量),

并将此表中每条记录在t表中对应的记录统计出来放到第三个表mx表中!这么缺德的统计我竟然找到了一个非常好的解决方法.
我们这个项目由两个公司一起做,做得一模一样,这样有个竟争,是个大项目,结果那个公司这个统计竟然做不出来!所以本人感觉特牛!如果大家有兴趣我可以介绍一下我的做法,但我更想知道大家有没有更好的办法,我也想集思广益一下,开拓一下思路看看有没有更好的办法,所以我想先不说,以免得影响了大家的思路.

violing
资深会员

哈哈,好呀,保密几天

这么大的数据量自然只能用盘阵了,一天的数据量加上索引一共得20G,原本打算把这些数据存上几个月,现在看一个月都够呛,所以只能每天删除.这里我只能用到分区,这时候就会发现分区真的起到很大的作用.之前有还本想用SYBASE来做,结果SYBASE没有分区这个东西,可以说如果没有分区这个好工具我这个项目就完蛋了!

violing
资深会员

nr是varchar2(256)这个上面建分区有意义吗?

quote: 最初由 rollingpig 发布
7000万条纪录
跨分区
nr 上有index吗?
速度什么要求?


既然我们要对nr这个列进行group by,而group by是用不到索引的,所以就算你建了索引用有什么用吗?
这个应用要每十分钟进行一次,也就是说这个程序要在十分钟内完成一次执行.也就是说要在十分钟内完成sj从当前时间到之前24小时内nr重复超过比如100的记录,放到gb表中,并将对应明细从T表中取出放到mx表中.所有这样一定要在10分钟之内完成!
也就是说JOB肯定在10分钟之内调用一定,你一定在下次调用之前完成本次执行的任务.

violing
资深会员

我是按SJ分的区

应用需求表结构如下:
CREATE TABLE t(
SJ DATE NOT NULL,
l1 NUMBER(5) NOT NULL,
l2 NUMBER(10) NOT NULL,
l3 NUMBER(10) NOT NULL,
l4 VARCHAR2(30 BYTE) NOT NULL,
l5 VARCHAR2(30 BYTE) NOT NULL,
NR VARCHAR2(256 BYTE) NOT NULL,
l6 NUMBER(2) NOT NULL,
l7 NUMBER(2) NOT NULL,
l8 NUMBER(2) NOT NULL,
l9 NUMBER(2) NOT NULL,
l9 NUMBER(2) NOT NULL,
l10 VARCHAR2(30 BYTE) NOT NULL,
l11 VARCHAR2(30 BYTE) NOT NULL,
l12 VARCHAR2(30 BYTE) NOT NULL,
l13 VARCHAR2(30 BYTE) NOT NULL,
l14 NUMBER(5) NOT NULL,
l15 NUMBER(5),
)

当然后来为了实现目标我自己以加上了几个列,这个以后我再透露

violing
资深会员

我是按SJ分的区

应用需求表结构如下:
CREATE TABLE t(
SJ DATE NOT NULL,
l1 NUMBER(5) NOT NULL,
l2 NUMBER(10) NOT NULL,
l3 NUMBER(10) NOT NULL,
l4 VARCHAR2(30 BYTE) NOT NULL,
l5 VARCHAR2(30 BYTE) NOT NULL,
NR VARCHAR2(256 BYTE) NOT NULL,
l6 NUMBER(2) NOT NULL,
l7 NUMBER(2) NOT NULL,
l8 NUMBER(2) NOT NULL,
l9 NUMBER(2) NOT NULL,
l9 NUMBER(2) NOT NULL,
l10 VARCHAR2(30 BYTE) NOT NULL,
l11 VARCHAR2(30 BYTE) NOT NULL,
l12 VARCHAR2(30 BYTE) NOT NULL,
l13 VARCHAR2(30 BYTE) NOT NULL,
l14 NUMBER(5) NOT NULL,
l15 NUMBER(5),
)

当然后来为了实现目标我自己以加上了几个列,这个以后我再透露

violing
资深会员

如果NR上有index,会降低insert速度
而在做group by 时,只需读分区索引,速度会挺快的。

biti_rainy
人生就是如此

其实比插入速度可能意义不大

更多地是看如何设计易于管理,很多数据仓库类型的应用,数据量都非常大

violing
资深会员

大家好象对这个问题不太关心哟

我这个统计要面对的问题是,如果你不想出好办法,你只能每十分钟面对一次7000万条数据的查询,对nr varchar2(256)进行GROUP BY ,然后还要进行其他明细的查询,这其中nr建成索引没有意义,或者说nr建了索引还不如不建.所以并不是其他的问题,所以发言的朋友首先要明确矛盾的所在.也就是说如果这个问题放在你面前你有什么好的办法?

biti_rainy
人生就是如此

nr 上建立索引的意义在于 减小 IO ,避免对全表排序

是不是你只需要nr 以及 时间 两个数字,根据时间在24小时以内的nr进行统计,如果这样的话是可以建立local 索引的,并且在索引上包含 (nr,date) ,这样统计就能在索引内完成而不会去度表。

violing
资深会员

老弟的主意指导意义不大哟

quote: 最初由 biti_rainy 发布
nr 上建立索引的意义在于 减小 IO ,避免对全表排序

是不是你只需要nr 以及 时间 两个数字,根据时间在24小时以内的nr进行统计,如果这样的话是可以建立local 索引的,并且在索引上包含 (nr,date) ,这样统计就能在索引内完成而不会去度表。


因为这个统计要每十分钟做一次,如果这样做的话十分钟之内肯定完不成的.

biti_rainy
人生就是如此

Re: 老弟的主意指导意义不大哟

quote: 最初由 violing 发布

因为这个统计要每十分钟做一次,如果这样做的话十分钟之内肯定完不成的.


你是十分钟统计无法完成还是什么意思?

通过时间条件限制在最近24小时范围的分区里面,并且只读这些分区范围内的index segment,避免排序并且不用访问表数据,就可以完成统计。

我不明白 为什么这样做 反而完不成?

难道你去全部扫描24小时范围内的分区数据并且排序完成的更快?

violing
资深会员

真不好意思,我没有说明白

是这样,这个统计是每十分钟进行一次,比如现在是下午2:50,你开始统计从这个时间开始到昨天下午2:50之间的nr重复在比如100次上以的记录以及其明细,统计完后,你需要在3:00开始进行下一次统计,也就是统计从3:00开始到昨天3:00之间的nr重复在比如100次上以的记录以及其明细,统计完后,再到3:10开始统计这时到昨天3:10...........以此下去,所以这个统计是每十分钟进行一次.也就是说每次开始统计必需要在10分钟之内完成.
你的建索引的想法是好的,只是这样建索引你的效率没有提高多少,我相信10分钟之内肯定没能完成统计.

embed_rabbit
高级会员

Re: 真不好意思,我没有说明白

quote: 最初由 violing 发布
是这样,这个统计是每十分钟进行一次,比如现在是下午2:50,你开始统计从这个时间开始到昨天下午2:50之间的nr重复在比如100次上以的记录以及其明细,统计完后,你需要在3:00开始进行下一次统计,也就是统计从3:00开始到昨天3:00之间的nr重复在比如100次上以的记录以及其明细,统计完后,再到3:10开始统计这时到昨天3:10...........以此下去,所以这个统计是每十分钟进行一次.也就是说每次开始统计必需要在10分钟之内完成.
你的建索引的想法是好的,只是这样建索引你的效率没有提高多少,我相信10分钟之内肯定没能完成统计.


还在测试么 把index 加上去 测试下看看

violing
资深会员

测过,不成

十分钟内要做两次查询,一次是针对nr的GROUP BY HAVING,另一个是从gb表中将对应的t表中的数据查询出来放到mx表中,你相信可以在十分钟之内从7000万记录中搞定吗?

funnyok
老会员:)

如果楼主的的表符合下面条件的话
1 不需要修改
2 只增加新的时间

下面的方法可不可行?
检索:
每10分钟或者更短的时间,定期动态增加基于时间partition,使新的值都加入到新的partition,然后定期把新的partition的group by统计叠加到统计表上去。
插入:
插入的优化可以基于hash subpartition的来避免itl的竞争,开上parallel dml,用上append hint

violing
资深会员


这位老弟动脑子了!

quote: 最初由 funnyok 发布
如果楼主的的表符合下面条件的话
1 不需要修改
2 只增加新的时间

下面的方法可不可行?
检索:
每10分钟或者更短的时间,定期动态增加基于时间partition,使新的值都加入到新的partition,然后定期把新的partition的group by统计叠加到统计表上去。
插入:
插入的优化可以基于hash subpartition的来避免itl的竞争,开上parallel dml,用上append hint


有许多想法与我的实际做法有接近的地方,不过我没用到hash subpartition,我自己的经验是如果每秒插入实际不会超过2000条,只要索引建得不太多,分区小些,不会影响插入速度的.我不关心插入速度,我更关心查询速度

biti_rainy
人生就是如此

 Re: 测过,不成

quote: 最初由 violing 发布
十分钟内要做两次查询,一次是针对nr的GROUP BY HAVING,另一个是从gb表中将对应的t表中的数据查询出来放到mx表中,你相信可以在十分钟之内从7000万记录中搞定吗?

你说在索引中快还是在表中快? 我有一个前提条件,统计能在索引内部完成而不需要去读表! 索引索引是建立在 (nr,date)上的复合索引!
如果你只在nr字段上建立索引那肯定是没有意义的,因为你还要去访问表本身以获得 时间数据!

我一直在强调这个问题,不知道你注意到没有!

violing
资深会员

 我明白你的意思

可对一个varchar2(256)的列和一个时间列建索引你觉得效果会好吗?我当然相信你建索引总比不建索引好,这一点我坚决同意你的看法,只是没有好到我希望的效果,因为我的第一个查询用不到索引的,GROUP BY是用不到索引的,你明白了吗?

biti_rainy
人生就是如此

Re: 我明白你的意思

quote: 最初由 violing 发布
可对一个varchar2(256)的列和一个时间列建索引你觉得效果会好吗?我当然相信你建索引总比不建索引好,这一点我坚决同意你的看法,只是没有好到我希望的效果,因为我的第一个查询用不到索引的,GROUP BY是用不到索引的,你明白了吗?

1:你能阐述一下你下面这段话是什么意思吗?下面这个阐述是可以用到索引的,只不过不是通常的用法。

其中有一个统计是对t表其中一列nr varchar2(256)进行,统计每十分钟执行一次,要统计sj从当前时间开始往以前24小时,其中nr重复超过一个设定值(比如100)的时候就产生一条记录插入到一个统计表gb中,此表中要有
nr varchar2(256) ,
sj1 date (统计开始时间),
sj2 date (统计结束时间),
sl number(10) (重复数量),

2:我没有说过建索引总比没建索引好,我没这个绝对的看法。这是你误会了我的意图。

3: varchar2(256) 如果不合适建立索引,那你至少应该给出该列的平均长度给我们show一下,你不说,永远不会有人知道到底是多长。

我使用索引的目标没有其他的,就是为了降低 IO (如果你的 nr这个字段占了整个行的长度的大部分,那就没什么意义了),例子(如果索引是 index(owner,created)则数据库在9204上选择的是 FFS ,两者到底哪个更好一些则需要具体权衡测试 )

alibaba@OCN>create table test as select * from dba_objects;

Table created.

alibaba@OCN>desc test
Name Null? Type
----------------------------------------------------- -------- ------------------------------------
OWNER VARCHAR2(30)
OBJECT_NAME VARCHAR2(128)
SUBOBJECT_NAME VARCHAR2(30)
OBJECT_ID NUMBER
DATA_OBJECT_ID NUMBER
OBJECT_TYPE VARCHAR2(18)
CREATED DATE
LAST_DDL_TIME DATE
TIMESTAMP VARCHAR2(19)
STATUS VARCHAR2(7)
TEMPORARY VARCHAR2(1)
GENERATED VARCHAR2(1)
SECONDARY VARCHAR2(1)

alter table test modify(owner not null,created not null);

alibaba@OCN>create index test_ind_2 on test(created,owner);

Index created.

alibaba@OCN>analyze table test estimate statistics for table for all indexes for all indexed columns;

Table analyzed.

alibaba@OCN> explain plan for
select owner,count(*),sysdate,sysdate - 1
2 3 from test
where created > sysdate - 1
4 5 group by owner
having count(*) > 100;
6
Explained.

alibaba@OCN>
@?/rdbms/admin/utlxplp;
alibaba@OCN>
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------

--------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 12 | 27 |
|* 1 | FILTER | | | | |
| 2 | SORT GROUP BY | | 1 | 12 | 27 |
|* 3 | INDEX RANGE SCAN | TEST_IND_2 | 501 | 6012 | 2 |
--------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter(COUNT(*)>100)
3 - access("TEST"."CREATED">SYSDATE@!-1)
filter("TEST"."CREATED">SYSDATE@!-1)

Note: cpu costing is off

18 rows selected.

adamyang
中级会员

Re: 我明白你的意思

quote: 最初由 violing 发布
可对一个varchar2(256)的列和一个时间列建索引你觉得效果会好吗?我当然相信你建索引总比不建索引好,这一点我坚决同意你的看法,只是没有好到我希望的效果,因为我的第一个查询用不到索引的,GROUP BY是用不到索引的,你明白了吗?

GROUP BY也是可以用索引的。

像biti所说的“索引是建立在 (nr,date)上的复合索引”
这时形如“select count(*),nr from table1 group by nr ”就只会用到索引,并且避免了排序消耗。

biti_rainy
人生就是如此

当然,事实上,如果你的这个表中 nr 的总体记录是有限的,比如明确这个表总量在百万级,并且,同时大于100条的用户数量是少数。

那还可以10分钟的频率增量地做这件事情。同时记录24小时以前的10分钟和当前10分钟内的数字,每次就是一加一减。

funnyok
老会员:)

同意biti用index_ffs减少io的说法。
另外,index会增加插入io和多sessiond的segment竞争。第一个字段是时间的B-Tree总是有这样的麻烦,有什么好方法吗?

violing
资深会员

首先谢谢各位的关心,可能我描述的不太清楚,这是我的错

这个表t每天插入7000万条左右记录,而且不同时间段插入量不一样,但总量大约这么多,而且以后数据量有可能再增加一些.
这个表的nr列为varchar2(256),真实的情况是平均为80-90字节左右,所以GROUP BY这么长的列挺麻烦吧?速度不会太高的.
每十分钟计算一次从当前这个时间到24小时前nr重复的记录,当超过一定的值时,这个一定值是用户事先自己定的,可以是50次,也可以是1000次甚至更高.这个需求不是我提出的,是用户提的,不做不成.先找到这样重复的记录把相关信息放到表gb中,这个表有nr varchar(256),sj1 date(重复记录出现的第一条的时间),sj2 date(重复记录出现的最后一条的时间),all number(10)(重复总次数).也就是说把重复的情况总结放到这个gb表中.
然后根据刚插入gb表的记录,将具体的明细再从t表中查询出来,插入到mx表中,从而gb表与mx表是主从一对多的关系.
所以从大体讲我对这个7000万条的表要进行两次查询,第一次查重复记录以GROUP BY为主,第二次查明细要以WHERE为主,用得到索引.
所有以上的内容,要在10分钟内完成,然后下一个10分钟进行下一次的重复操作.当然,我还要确保同一时段统计出来的gb表的记录只出现一次,等等,这里面还有许多细节,我就不想说了,我们不用关心这些太细的东西.
这个统计的难度在于nr这个列太长,GROUP BY起来太累,再有就是数据量大,还有就是要求进行的时间间隔太小.

biti_rainy
人生就是如此

如果关键历史数据不会发生变化,则

做一个总体所有nr的记录,然后10分钟做一个增量的统计,保留下来,并merge(比如9i的merge into)到总体记录的表中,统计完毕后,立即减去紧靠24小时前的那一个增量部分,等待下一次新统计的数据来merge,如此反复。

7000万平均下来是每10分钟有48万,如果这48万中还有重复的信息,数据量可能会更少一些。处理48万的数据对于oracle来讲应该是可以的。

我觉得这样做是可行的,问题的关键是如何定义 出错时候的对策和处理办法

另外,如果服务器强劲,你的索引7000万*100字节大约可能会占7--10G的索引空间。10分钟以内完成这个查询并不是不可能的,我的系统一个20G的表上创建一个4个字段的联合索引,也只需要4分钟不到(无其他负载)。

funnyok
老会员:)

其实256(长度)的256(字符的可去值)排列并不太大。如果在application级上处理这个问题会不会很简单?
1. 做一个256*256的hash或者直接是数组用作计数
2. 给每一个记录计数

另外2如果需要并行,实现方法只要做一些小变化
2' 让所有的ap thread对这个数据结构的semophone申请/释放

2‘’ 把所有的输入sj,nr放进一个input queue(ibm mq之类),
然后再让数个thread分别处理多个数据结构计数,
最后把结果相加。

3. 用一个queue

funnyok
老会员:)

 

quote: 最初由 biti_rainy 发布
另外,如果服务器强劲,你的索引7000万*100字节大约可能会占7--10G的索引空间。10分钟以内完成这个查询并不是不可能的,我的系统一个20G的表上创建一个4个字段的联合索引,也只需要4分钟不到(无其他负载)。

能说说你的配置吗?parallel几做的?做个参考。


violing
资深会员

 

谢谢你的指点,说真的真的开拓了我的思路

quote: 最初由 biti_rainy 发布
如果关键历史数据不会发生变化,则

做一个总体所有nr的记录,然后10分钟做一个增量的统计,保留下来,并merge(比如9i的merge into)到总体记录的表中,统计完毕后,立即减去紧靠24小时前的那一个增量部分,等待下一次新统计的数据来merge,如此反复。

7000万平均下来是每10分钟有48万,如果这48万中还有重复的信息,数据量可能会更少一些。处理48万的数据对于oracle来讲应该是可以的。

我觉得这样做是可行的,问题的关键是如何定义 出错时候的对策和处理办法

另外,如果服务器强劲,你的索引7000万*100字节大约可能会占7--10G的索引空间。10分钟以内完成这个查询并不是不可能的,我的系统一个20G的表上创建一个4个字段的联合索引,也只需要4分钟不到(无其他负载)。


不过你还不太理解我的需求,首先nr中的内容自然是百花齐发,没有一定之规,所以你说的增量的方法不太适合.这个问题我想过好久,也就是说每次自然要从24小时之前算起,这不样是不成的.用户的这个需求就是:在任意24小时之内,nr列重复值超过一个设定值的记录.我们争取了很久,才争取下个粒度,也就是十分钟一个算一次,不然如果一分钟一个粒度甚至一秒钟一个粒度我们死定了!
而且不但要算出重复数,还得找出明细来,所以两个查询要在十分钟之内完成,我不能说在8分钟内完成,或9分半钟完成就算成功,因为如果有不确定因素的话那肯定超过10分钟了,那不就惨了?
如果你说的十分钟完成只针对一次查询那就还是不满足我的需求呀
violing
资深会员

这位老兄的几次发言一直说得跟我的思路接近!

quote: 最初由 funnyok 发布
其实256(长度)的256(字符的可去值)排列并不太大。如果在application级上处理这个问题会不会很简单?
1. 做一个256*256的hash或者直接是数组用作计数
2. 给每一个记录计数

另外2如果需要并行,实现方法只要做一些小变化
2' 让所有的ap thread对这个数据结构的semophone申请/释放

2‘’ 把所有的输入sj,nr放进一个input queue(ibm mq之类),
然后再让数个thread分别处理多个数据结构计数,
最后把结果相加。

3. 用一个queue


我开始怀疑你是我们竟争对手的人了

,不过我们竞争对手还没算出来,所以是也无所谓.更何况项目己经都上马了.
不过你的hash不知道是怎么做的,不知道能不能介绍一下,也许真是个好办法!其实ORACLE的工具就那些,能否用得好全得看自己的理解程度,这也可以算经验,说实在的,我在这个项目中也用了HASH,但跟你的用法不一样,最后我一定把我的HASH告诉你,你一定感到意外,因为肯定跟你的不一样.但你的HASH我还真不太理解他的优点在什么地方,你方便介绍一下吗?
另外,这样的查询我当然都用了并行查询,加个HINT,并行度为4或5,并行查速度真的提高不少,
另外,我的数据库不光运行我这一个统计,还有很多统计,所以我不能把我的资源都给这个,还得考虑其他的统计工作的进行,因此我不能让这个统计确保在8,9分钟左右才完成,而实际情况是我5分钟之内肯定完成,这是我做的实际效果!

biti_rainy
人生就是如此

Re: 谢谢你的指点,说真的真的开拓了我的思路

quote: 最初由 violing 发布


不过你还不太理解我的需求,首先nr中的内容自然是百花齐发,没有一定之规,所以你说的增量的方法不太适合.这个问题我想过好久,也就是说每次自然要从24小时之前算起,这不样是不成的.用户的这个需求就是:在任意24小时之内,nr列重复值超过一个设定值的记录.我们争取了很久,才争取下个粒度,也就是十分钟一个算一次,不然如果一分钟一个粒度甚至一秒钟一个粒度我们死定了!
而且不但要算出重复数,还得找出明细来,所以两个查询要在十分钟之内完成,我不能说在8分钟内完成,或9分半钟完成就算成功,因为如果有不确定因素的话那肯定超过10分钟了,那不就惨了?
如果你说的十分钟完成只针对一次查询那就还是不满足我的需求呀


之所以不理解你的需求,是因为你一开始并没有完整地表达清楚你的需求。

如果用户需要任意一个24小时之内的统计,并且你们以10分钟做一个粒度的统计,那我们也可以把 十分钟做一个分区,把任意连续24小时内的数据统计好记录下来了后,我们可以在一定的周期范围内循环覆盖这些分区。

*****************************************************************************************
当然。这么想我们仅仅是站在数据库的角度老考虑的,而没考虑到应用设计的配合。

刚才看见你在前面说你为了实现你的目标,修改了表结构!如果表结构都可以修改,应用也可以做配合,那可实现的方式就多了。

我先来模拟一下你的业务需求(我其实一点都不懂你们是做什么的):
八九十个字节,我们姑且定义为 短信内容,所以内容百花齐放。政府为了加强监管,对每天重复发送内容多的信息进行跟踪,若发现有内容被重复发送很多次,则要立即报告出来,并查出明细(包括手机号等用户信息),若是违法或者反党内容要立即处理……

ok,在这样一起前提下,怎么来满足用户的需求,在入库的环节,我们定义为从交换机上采集下来的数据,由于短信内容重复的概率是很小的(你也说了百花齐放嘛),所以,我们可以在入库的时候采集短信内容的前面N个字符做一个算法算成数字记录下来(比如oracle在搜集 varchar2 column histograms的时候就是采集前14个字符的ascii码再乘以 255的N次方来计算的),由于这仅仅是一个数字,统计起来容易的多。比如前14个字节都重复的概率应该很小,我们在第一级通过一个数字统计排序(有索引)则非常的快,这样可以把这批少量的数据抽取出来(前14个字节相同并不一定就完全相同),对这些少量数据,我们再进行二级统计,这个时候数据量恐怕就非常少了,想怎么算就怎么算。

如果我们不把数据本身取出来再进行二级抽取,也可以把256的字符串截取成N段,每段算出一个hash值来(考虑到重复的概率很小,我们可以把这个值设计得相对比较小而便于我们处理,甚至不同分段的算法都可以有差异,做一个折中的处理),根据应用特征我们可以在入库的时候进行很多的考虑来处理。不管是构造hash表还是其他…… 方式很多

实际上,一个应用本身潜在的可利用的条件,对于你来说是清楚的,但是就你发在这里的文字是表达不出这些条件的,这就局限了大家的思考的余地,而只能局限于数据库的角度来处理。

biti_rainy
人生就是如此

 

quote: 最初由 funnyok 发布


能说说你的配置吗?parallel几做的?做个参考。



8CPU , AIO , raw device,32 disks (LVM),ram 16G,buffer cache 8G (由于创建索引时候都是物理读,实际上内存意义不大)

我没有使用并行创建也没有使用nologging,所以实际上还有很大的提高的余地!

草中宝
中级会员

 在楼主说下面这个
~~~~~~~~~~
真不好意思,我没有说明白
是这样,这个统计是每十分钟进行一次,比如现在是下午2:50,你开始统计从这个时间开始到昨天下午2:50之间的nr重复在比如100次上以的记录以及其明细,统计完后,你需要在3:00开始进行下一次统计,也就是统计从3:00开始到昨天3:00之间的nr重复在比如100次上以的记录以及其明细,统计完后,再到3:10开始统计这时到昨天3:10...........以此下去,所以这个统计是每十分钟进行一次.也就是说每次开始统计必需要在10分钟之内完成.
你的建索引的想法是好的,只是这样建索引你的效率没有提高多少,我相信10分钟之内肯定没能完成统计.
~~~~~~~~~~
的时候,我就估计楼主不是用索引扫描,而仅仅是在前后十分钟进行累加累减运算。
不知道我说错了没有?
另外我想向楼主请教一下,这么大的数据量,怎么做备份,还是不需要做备份呢?

violing
资深会员

 老弟还是很鬼机灵的哟

quote: 最初由 草中宝 发布
在楼主说下面这个
~~~~~~~~~~
真不好意思,我没有说明白
是这样,这个统计是每十分钟进行一次,比如现在是下午2:50,你开始统计从这个时间开始到昨天下午2:50之间的nr重复在比如100次上以的记录以及其明细,统计完后,你需要在3:00开始进行下一次统计,也就是统计从3:00开始到昨天3:00之间的nr重复在比如100次上以的记录以及其明细,统计完后,再到3:10开始统计这时到昨天3:10...........以此下去,所以这个统计是每十分钟进行一次.也就是说每次开始统计必需要在10分钟之内完成.
你的建索引的想法是好的,只是这样建索引你的效率没有提高多少,我相信10分钟之内肯定没能完成统计.
~~~~~~~~~~
的时候,我就估计楼主不是用索引扫描,而仅仅是在前后十分钟进行累加累减运算。
不知道我说错了没有?
另外我想向楼主请教一下,这么大的数据量,怎么做备份,还是不需要做备份呢?


你猜对了.我一会马上说说我的大至做法,你会看到你的累加,我是先统计到中间表,然后对中间表进行累加,你很厉害哟!!!
我们备份的方法很怪异,没技术含量,见不得人,这不是我的问题,是领导不懂胡来的,所以没必要在这儿丢人

violing
资深会员

不得不说biti_rainy老兄是个大大的人才!

实在是个人才!这个不服不成,虽然我跟你的解决方法有区别,但指导思想上是一曲同工的,可我这办法我想了很久才搞定,没想到你老兄这么快就有了这样的办法!
我不得不在这里向本论坛的所有人庄严地宣告:biti_rainy是个大大的人才!佩服佩服!说实在的这其中涉及到不少我不方便讲的内容,但总体思想biti_rainy老兄基本表达清楚了.实在不好意思的是我的表达能力差些.
正象biti_rainy所说,我的分区正是十分钟一分区,一点不差,而且我在t表中增加的列也是从nr列转换过来的,只不过转换的方法与biti_rainy有一些不同,但目的都一样.我是用一种所谓HASH的算法将nr列转换为hash number(10)的列,这样可以保证相同nr一定有相同的hash,当然不同nr也有可能有相同的hash但极少,可以在以后的程序中进行控制重复的正确性.这样对hash列和sj列进行索引以及group by操作性能就提高了不少.我每次将刚插完数据的十分钟的分区记录进行GROUP BY,其结果放到中间表中,然后根据需要对中间表的结果按时间范围如24小时,以用相同内容的重复值进行SUM,SUM大于用户指定值如100的插入到gb表中.之后的操作有索引以及并行查询就快快的不着急了.这样我可以在五分钟之内完成两个这样条件的计算而且中间表的数据量比t表小两个数量级!所以查询速度当然快快的!
当然其中还有一些小把戏,没什么技术含量,纯属不择手段,本人也不好意思多讲.但有一点,我的这个程序很好用.而我们竞争公司的同人非常实在,只能对那个t表进行各种直接操作,没有什么别的技巧和手段,当然没办法即时地算出结果来!
我本来之前是个数据库的入门者,但胆大包天地接下了这样一个大数据量的项目并象小平同志摸着石头过河一样完成了并完成的还算不错,以至于得到不少人的称赞,搞的本人心情真是很复杂,原来二把刀也可以混得虎了这么多人呀?哈哈
当然我还有不少别的收获,这些收获有些是我自己的创造,还有不少是本论坛的大侠们的帮助,在此我深表感谢!这个感谢是真心的.所以我对本论坛很有感情,现在一有空就想多为本论坛做些贡献.而且我还会有不少问题请教,希望大家互帮互助,一起发财!

adamyang
中级会员

方法不错,不过HASH算法碰撞很难避免(MD5那么多年了都难逃厄运)

多分区给系统之后代来的影响不知道有没有考虑过?
十分钟一个分区,一天100多个分区,不到三个月分区数量将超过一万。
不知道你的数据要保留多少时间历史数据。
这么多的segment对于你业务数据正常的录入是否有影响呢?
其实以前也问过多segment对实时数据插入的影响,不知道楼主有什么看法。

funnyok
老会员:)

Re: 这位老兄的几次发言一直说得跟我的思路接近!

quote: 最初由 violing 发布


我开始怀疑你是我们竟争对手的人了

,不过我们竞争对手还没算出来,所以是也无所谓.更何况项目己经都上马了.


好啊,告诉我他们在哪儿?我好去赚点儿零花。呵呵。

我的想法和biti的差不太多,就是在入库之前做一遍分析。用hash和queue把没有意义的值和有意义的分开。能做的计数预处理都做了。主要是db本来是面向transaction的,对于这种不太需要信息完整性、只要速度的处理并不太适合。

觉得biti分析的更全面一些。

funnyok
老会员:)

 

quote: 最初由 biti_rainy 发布


8CPU , AIO , raw device,32 disks (LVM),ram 16G,buffer cache 8G (由于创建索引时候都是物理读,实际上内存意义不大)

我没有使用并行创建也没有使用nologging,所以实际上还有很大的提高的余地!


没错,和db_cache_size无关,
所以还想知道ibm/hp/sun的系列,raid 5/0+1,lvm类型,scsi/fc,storage cache,最后pga_aggregate_target/sort_area_size, db_file_multiblock_read_count
——我是不是有些太细了:P

biti_rainy
人生就是如此

 

quote: 最初由 funnyok 发布

没错,和db_cache_size无关,
所以还想知道ibm/hp/sun的系列,raid 5/0+1,lvm类型,scsi/fc,storage cache,最后pga_aggregate_target/sort_area_size, db_file_multiblock_read_count
——我是不是有些太细了:P


IBM p590 .hds 9970 ,raid10(2p+2d) ,lvm stripe size 64k width 16,fc ,storage cache 16G(读写比例自动调节), pga_aggregate_target 2G

funnyok
老会员:)

 Re: 老弟还是很鬼机灵的哟

quote: 最初由 violing 发布


你猜对了.我一会马上说说我的大至做法,你会看到你的累加,我是先统计到中间表,然后对中间表进行累加,你很厉害哟!!!
我们备份的方法很怪异,没技术含量,见不得人,这不是我的问题,是领导不懂胡来的,所以没必要在这儿丢人


关于备份:
如果primary机负荷太高可以考虑搞个physical stand by,在stand by 上备份
如果备份本身无法用一个逻辑TL解决,可以按tbs分别备到多个逻辑TL上(恢复比较麻烦)
你这样的需求估计alter 当前的df backup的话 redo就吃紧了吧。
最差的情况,可以加一个按partition export的,不过就不是hot的了。

数据的删除用purge partition应该没问题。

熟悉存储的兄弟们,直接用存储snapshot怎么样?

funnyok
老会员:)

 

quote: 最初由 玉面飞龙 发布
开发的时候还要考虑到灵活性,如果用户突然从10分钟要求到15分钟或者20分钟,因为物理分区已经不可改变,需要各种调度作业灵活运作

如果负荷在可以承受的范围内,可以把粒度减小到最大公因数。
或者在最大公因数上作sub range partition。如何?

violing
资深会员

  

quote: 最初由 adamyang 发布
方法不错,不过HASH算法碰撞很难避免(MD5那么多年了都难逃厄运)

多分区给系统之后代来的影响不知道有没有考虑过?
十分钟一个分区,一天100多个分区,不到三个月分区数量将超过一万。
不知道你的数据要保留多少时间历史数据。
这么多的segment对于你业务数据正常的录入是否有影响呢?
其实以前也问过多segment对实时数据插入的影响,不知道楼主有什么看法。


这个我考虑过,从目前的数据量和盘阵大小来看只能存一个月的数据,所以分区有几千个.我用一个动态创建分区的程序,定时运行,创建新的分区并DROP过期的分区,使分区数量保持动态的平衡.多分区确实要影响插入速度,但影响多少我这里没有定量算,但实际情况并没有受到什么影响.因为我的实际插入速度并不是特别大.
之前我曾经试过一天一个分区,那时有四个索引,结果确实出现插数速度受到影响的问题.
最早我还试过一种方法,我在插入t表数据以前先将数据插入到一个144分区里,这个分区只存一天的数据,统计完成后将数据移到t表,而t表以天分区.但由于这样觉得出现了没有必要的数据传递,我最终放弃了这个做法,
总之,还可再权衡看哪个更合理实际一些!

violing
资深会员

  

 quote: 最初由 玉面飞龙 发布
关键在于 每次操作要尽量减少input data数据量,包括10分钟粒度分区的group by,和对24小时的sum haveing统计;

这其中使用的"hash 算法"非常重要,因为还要根据hash value找到对应的 短信息text; 所以需要类似zip/unzip的算法,可以根据hash value还原到原来的文本(可以在应用上作)。

开发的时候还要考虑到灵活性,如果用户突然从10分钟要求到15分钟或者20分钟,因为物理分区已经不可改变,需要各种调度作业灵活运作


明白你的意思,可我的分区是通过一个过程定时运行后自动创建并自动删除这种方式进行的,所以可通过修改程序以改变分区的大小.不过目前还没考虑这个,因为用户真提出这样的无理要求我只能面对着他们做出手式并声嘶力竭地高叫:我鄙视你!!!
violing
资深会员

  Re: Re: 老弟还是很鬼机灵的哟

quote: 最初由 funnyok 发布


关于备份:
如果primary机负荷太高可以考虑搞个physical stand by,在stand by 上备份
如果备份本身无法用一个逻辑TL解决,可以按tbs分别备到多个逻辑TL上(恢复比较麻烦)
你这样的需求估计alter 当前的df backup的话 redo就吃紧了吧。
最差的情况,可以加一个按partition export的,不过就不是hot的了。

数据的删除用purge partition应该没问题。

熟悉存储的兄弟们,直接用存储snapshot怎么样?


老兄一定是备份专家

,考虑的真的很有道理,我有空想想试试

rollingpig
老不死会员

 

quote: 最初由 玉面飞龙 发布
关键在于 每次操作要尽量减少input data数据量,包括10分钟粒度分区的group by,和对24小时的sum haveing统计;

这其中使用的"hash 算法"非常重要,因为还要根据hash value找到对应的 短信息text; 所以需要类似zip/unzip的算法,可以根据hash value还原到原来的文本(可以在应用上作)。

开发的时候还要考虑到灵活性,如果用户突然从10分钟要求到15分钟或者20分钟,因为物理分区已经不可改变,需要各种调度作业灵活运作


1.可逆算法没有必要也没有意义也很难实现。

2。区间改变只会多acess几个分区,对性能影响应该不大。

funnyok
老会员:)

 

quote: 最初由 rollingpig 发布


1.可逆算法没有必要也没有意义也很难实现。
2。区间改变只会多acess几个分区,对性能影响应该不大。


赞成你的1,只要在中间表上加个nr存储,数据就不需要还原
unzip的算法是基于LZ78的字典压缩+huffman,对于80-90byte的数据没有太大意义。而且还"百花齐放"熵值不像太低。应该很难达到hash的精简。

但是关于2还是需要考虑一下,要不然就会变成O*上取整[S range / P range]的算法。
设P10为10分一次的partition,S17为17分一次的统计
S17.1--|-- S17.2---|--S17.3
->
P10.1 P10.2 P10.3 P10.4 P10.5
如上所示,因为partition的处理如果没有partition index不可分割,S17.2之后的大多数处理将花费O*3的cost。这在S range > P range的情况下是几乎必然的。partition index动态的rebuild和analyze几乎是不可接受的。

所以解决方法也就出来了——追加条件
1. 粒度即S range的改变不是随时随意的,而是每次给出一个固定值
2. 统计过程是一次的连续的,即不能由多次shcedule执行。如果非要中断可以把这个进程挂起,但不能终止。
如果有上述的两个条件,只要扫描需要的P10.n-1到P10.n+1就可以保证完成。

funnyok
老会员:)

 

quote: 最初由 violing 发布


这个我考虑过,从目前的数据量和盘阵大小来看只能存一个月的数据,所以分区有几千个.我用一个动态创建分区的程序,定时运行,创建新的分区并DROP过期的分区,使分区数量保持动态的平衡.多分区确实要影响插入速度,但影响多少我这里没有定量算,但实际情况并没有受到什么影响.因为我的实际插入速度并不是特别大.
之前我曾经试过一天一个分区,那时有四个索引,结果确实出现插数速度受到影响的问题.
最早我还试过一种方法,我在插入t表数据以前先将数据插入到一个144分区里,这个分区只存一天的数据,统计完成后将数据移到t表,而t表以天分区.但由于这样觉得出现了没有必要的数据传递,我最终放弃了这个做法,
总之,还可再权衡看哪个更合理实际一些!


对了有一件事情有没有考虑过?频繁的add partition, drop partition会导致system表领域的碎片,free list的不平衡,index b+tree的不平衡——所以理论上考虑应该定期维护system表领域。这在普通的oltp里是基本不要考虑的。

另外还有一个之前问过的问题,动态的add partition, drop partition不会和大量的DML发生dictionary的竞争?

funnyok
老会员:)

Re: Re: Re: 这位老兄的几次发言一直说得跟我的思路接近!

quote: 最初由 violing 发布


哈哈,看来真是高手云集哟! 其实我更想知道如果在数据仓库里面对更大的数据量如何进行各种统计哪位知道呀?我从没搞过数据仓库


数据仓库一般少有实时的,主要是统计和dill down,最后给mining提供原材料。总而言之不用像你这么处心积虑的自己考虑时间,主要是cube index的设计和parallel的问题。
如果是处理小的话oracle olap option的etl转移数据,然后再oracle里加上cube index materialized view基本就可以搞定。
如果再上到大规模的据说是可以teradata专用的全并行机,我就没摸过了。估计dw版有足够的资源。

violing
资深会员

你提醒得有道理!

quote: 最初由 funnyok 发布


对了有一件事情有没有考虑过?频繁的add partition, drop partition会导致system表领域的碎片,free list的不平衡,index b+tree的不平衡——所以理论上考虑应该定期维护system表领域。这在普通的oltp里是基本不要考虑的。

另外还有一个之前问过的问题,动态的add partition, drop partition不会和大量的DML发生dictionary的竞争?


我有空关心一下此事.我不知道用LMT分不分尽可能地减少碎片的产生.
我这个项目在数据量少的地方用过,出显问题的情况不太多,可能是数据量不足到立刻出问题的情况.而7000万这个地方刚上,还需要观察一段,我以后会在这些方面多留意一下.

violing
资深会员

你说得好深奥呀!

quote: 最初由 funnyok 发布


赞成你的1,只要在中间表上加个nr存储,数据就不需要还原
unzip的算法是基于LZ78的字典压缩+huffman,对于80-90byte的数据没有太大意义。而且还"百花齐放"熵值不像太低。应该很难达到hash的精简。

但是关于2还是需要考虑一下,要不然就会变成O*上取整[S range / P range]的算法。
设P10为10分一次的partition,S17为17分一次的统计
S17.1--|-- S17.2---|--S17.3
->
P10.1 P10.2 P10.3 P10.4 P10.5
如上所示,因为partition的处理如果没有partition index不可分割,S17.2之后的大多数处理将花费O*3的cost。这在S range > P range的情况下是几乎必然的。partition index动态的rebuild和analyze几乎是不可接受的。

所以解决方法也就出来了——追加条件
1. 粒度即S range的改变不是随时随意的,而是每次给出一个固定值
2. 统计过程是一次的连续的,即不能由多次shcedule执行。如果非要中断可以把这个进程挂起,但不能终止。
如果有上述的两个条件,只要扫描需要的P10.n-1到P10.n+1就可以保证完成。


粒度之类的确实还没有考虑改变,如果用户提出要变肯定找借口不能让他们得逞

.不过我的中间表的作用很大,如果他们的要求变了,我只需从中间表中按新需求累加就得了,这个中间表还是很有用的,我跟领导提出过这个中间表的意义,还可以挖掘出许多有用的东西,可领导们不关心,所以只好把过期的值删除掉.唉,可惜

统计过程连续不应该是很必要的,只要让程序即时执行就成了,我采用过几种方式,但都是通过一些小机制,统计当前正在插入分区之前那个分区的数据,一量目前这个分区一插完,程序马上进行统计,也就是数据处理不影响正在插数的这个分区,这个不难实现,而且还很好用.所以我的程序总是让JOB调用,不过间隔很少.

violing
资深会员

Re: Re: Re: Re: 这位老兄的几次发言一直说得跟我的思路接近!

quote: 最初由 funnyok 发布


数据仓库一般少有实时的,主要是统计和dill down,最后给mining提供原材料。总而言之不用像你这么处心积虑的自己考虑时间,主要是cube index的设计和parallel的问题。
如果是处理小的话oracle olap option的etl转移数据,然后再oracle里加上cube index materialized view基本就可以搞定。
如果再上到大规模的据说是可以teradata专用的全并行机,我就没摸过了。估计dw版有足够的资源。


哦,我还算是比较基本的,只不过用些小技巧解决了个数据量大的问题,其实深的东西还真知道的不多.以后有机会学学数据仓库.我们公司听说有一套SIEBEL,听起来挺唬人的,好象跟数据仓库之类的有点关系,不过还没搞懂,真是学无止境呀,越学越觉得会的东西太少

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息