400万条数据存到本地,你会怎么存?
现在在维护一个项目,因为当初的数据库设计并不是我,所以现在被坑爽了。
该项目跑了一年多了,其他问题到没啥,就是报表那块很蛋疼。
这个项目是关于物联网的,其中有一个表,记录设备上下线(其中还有一个blob字段,这是最蛋疼的)。
由于大量设备频繁上下线,一年多,记录已经到达几千万,
而项目中,则是去查询该表一个月的记录(400万左右),并做成报表并导出成excel(有查询条件可以选择,选择后可能还是有200万左右)。
我测试过,(根据设备ID,且能创建索引的地方我都创建了)查询一个设备,一个月的记录所用时间为60秒左右。目前数据库中有2000个设备。(如果循环遍历。。)所用时间就是。。。。60 * 2000 大概是。。33.3小时。。
但这个事情必须解决啊,现在该数据库结构是不可能了,又不能删除以前的数据啊(毕竟才一年的数据也不是很久远),肿么办呢?我做了个很大胆的决定,将数据查询到本地内存中!!!
首先选用比较给力的JDBC(hibernate都没有用),然后,用ArrayList来装,结果。。。list装了30W 就挂了。。内存溢出。。。汗。。 立即修改java虚拟机内存 果断1024M(我本机只有2G内存) 结果。。。也只能装60W左右。。
无助。。。。
几经周折,最终还是被我给拿下了。说说方法。
首先采用了HashMap,但这个Map有点“大” 在Map的value中我又存了个ArrayList 而Map的Key则是设备ID
查询的时候先查询出所有的设备ID(是另一个表,查询速度很快),再将查询出的所有设备Id都存到Map中,然后查询记录表,遍历每条记录,根据每天记录的设备Id,在在Map中找到Id对应的List,再进行list的add。。
这样摊下来,一个list的大小大约是 4000000 / 2000 = 2000。。。
这样 绝对不会内存益处了。
各位高手,如果是你们,你们会怎么做呢?
这个我得说明下,客户的需求是月报表。记录设备上下线,是为了统计设备的信息,比如设备的上下线次数、频率、以及上线时长、掉线时长、总在线、掉线时间等。 至于存储过程,我也试过,时间上。。没区别。
你的存储过程是增量的么?如果是按日增量计算,每天才10几万条数据,不应该一样啊!你的上下线表明显是起的历史记录的作用,这个表在时间那个列上按天分区,存储过程只查某一天的数据应该会快很多才对啊。
------解决方案--------------------
我记得有种东西叫做文件索引。。。。才几千万的数据算什么
[解决办法]
是你坑用户吧,你把几百万的数据记录放在excel里面让客户看?
[解决办法]
打算控制在多少时间之内呢?
[解决办法]
要做DB备份 可以用数据库的备份工具。
要做报表 也要选择客户关注的一部分数据,很可能再对这部分数据进行再分析,跟本不可能把几百万记录直接给客户看。
[解决办法]
把数据放到硬盘上是个正确的选择,然后用lucence检索合适的还是速度很客观的,但是下面重点是导出excel的难度拉...集合初始化大小调个合适的,不要让他随便就扩容一次,很浪费资源呢,很容易就在扩容的时候内存溢出,然后开多线程分别把查询出来的数据写入excel,...个人愚见,哈哈