文档章节

比对小工具开发之路...

Alfie
 Alfie
发布于 2014/01/16 16:25
字数 1970
阅读 4387
收藏 84

接到任务,需要做一个数据比对的小工具,要求优先做好数据库表的数据比对,首先做了下分析,既然是小工具,我又是搞JAVA的,那只能选SWING了,脑子里当时稍微列了下实现步骤:

    第一步,实现单字段的比对 ;第二步,实现多字段的比对;第三步,实现表及比对字段的可配置划,第四部,能打包成EXE可执行文件;第五步,实现结果导出,第六步,优化比对核心模块;第七步,实现Excel与表比对;第八部,实现Excel间互相比对。

    ps: 考虑到最快的开发模式:举枪>射击>瞄准的开发模式,先将比对实现打通!也就是第一步到第四步,这里之所以把优化放在第五步,是因为上头要求先做好数据库比对,而Excel相关的就当然扔最后呐。

 首先比对肯定需要两个数据源:

            一个基准数据集(基准库)              一个比对数据集(比对库)

    其次分析数据结构:

          比对数据收集    |      字段                     行                 结果集                

        CompareView     |   FieldView     <     RowView   <   ResultView   

            (后来移掉ResultView,RowView包含两个FieldView的list,分别存放比对库和基准库差异的值)        

    再次分析比对准备流程:

        数据库配置 -> 获取表 -> 获取列 -> 设置比对基准 -> 设置比对列 ->设置完成

        基准库设置完成 -> 比对库设置完成 ->开始比对!  

    最后分析比对逻辑,分以下三种:

    1. 比对基准值,基准库有的比对库没有的,

    2. 比对基准值,比对库有的基准库没有的,

    3. 比对基准值,基准库有比对库也有,比队列的值不同的!

    接下来就开始了,SWING是完全不懂,不过也难不倒本人,首先准备环境,先去找了个JFrameDesigner插件

    第一步到第四步,做得何其顺利,(导出的先不管了)除了SWING因为实在接触得少,让我纠结了点,其它几乎都没碰到什么问题,接下来开始自测,修复一下七七八八的小问题,最后做个数据分页读取,终于跑起来了。

    ps:基准库是我们公司内网的数据库(51K多的数据量),比对库连的外省远程数据库(5K多的数据量),花费时间总共288秒!

    接下来就考虑优化的事了,继续分析下去,速度的优化大方向无非就是硬件,软件和环境,硬件和环境上没办法只能说我的东西有问题~  OK,不废话了,当时的想法就是从多线程和算法上下功夫!

    优化第一步,做线程,按分析逻辑的三种,每种分配一个线程,快了10几秒...

    优化第二步,做线程池,按分析逻辑的三种,每种分配一个10thread的线程池,又快了十几秒...(和内心想法差距过大,个人感觉此处应该要快更多,难道人品出了问题?)

        ps:这里啰嗦一句,玩线程的大家应该要知道,在excuse线程前,一定要构建好自己的tasklist

    优化第三步,线程方面的优化已经走到底了,接下来优化算法吧!

        ps:这一步下来真是累死累活,洗个澡,坐个公交车满脑子的都在想,这样如何?那样做又如何...拿着本子笔先后画了5,6页,OK说正题:

        草稿上最先出来的就是这个图了,(用QQ截图随手画的,撮了点)

       

    







    数据库数据抓取,之前已经加上的分页获取了,线程池的工作也完成了,优化的主要方向就是比对引擎和结果缓存和输出了!

    首先讲一下目前的比对模式,

        比对逻辑A , 获取所有的从标准库分页获取数据,通过key值,查询比对库,比对库没有的时候,返回 List<RowView>

        比对逻辑B , 获取所有的从比对库分页获取数据,通过key....................................................................................................................

        比对逻辑C,  获取所有的从标准库分页获取数据,通过key值,查询比对库,比对库有值,进一步进行比对,比对列的列值。

    ps:

            首先考虑减少连接关闭次数,将数据库的Connection,Statement 升级到compareView中!在程序关闭的时候,统一将CompareView中的Connection,Statement给关闭掉,OK,跑起来,发现有时候正常,有时候执行过程中会报resultset is closed. 还原statement在每次都开闭后,正常!(不明白,看来statement不能只create一次,优化力度不够

           其次考虑的是如何减少数据库的抓取次数,按目前的方式,ABC逻辑都是如下公式:

                抓取次数 = 分页查询A库的次数 * B库的所有行数

            很明显瓶颈在与B库,每次分页后,拿到的A库的每一个Key,都要去B库进行一次比对,这边我冲澡冲破了头,想到了一个数据库关键字  IN,

           我在做A库分页查询的时候,同步收集了所有的A库key列对应的值,然后查询B库的时候,我一次全部 where keycolumn in ('','',''...) ,

           想法很邪恶,效果很不错,比如A库分页每次1000条,如果按这种模式,我B库查询次数从1000次下降到了 1 次 

        再次对于算法的优化,目前的A,B,C三套分析逻辑是明显有重复的!

            ps:比如逻辑A,目前只分析出了标准库有,比对库没有的情况,实际上我们还可以通过这一次比对逻辑,同时分析出标准库有,比对库也有的情况!这样再执行逻辑B,执行出来的结果还是有三个LIST,而逻辑C这一步却在A就做完了!

      OK,到此为止,我的程序从288秒,优化到了65秒!很给力吧,先给图:

        最后,考虑的是如何输出的问题,比对的结果我也不可能全部放内存里面,大概算了一下

        java一个汉字字符占2字节,如果你一条记录有100个汉字,也就是一条记录占200字节,那么600万条数据就是12000000000字节。

        1G=1024M=1024X1024K=1024X1024X1024byte=1024x1024x1024x8字节=8589934592字节

        如果是600W条数据,那么所耗内存就是:12000000000/8589934592 = 1.4G

        一直放内存显然也是不行的。   

        这边目前我的思考模式是,增加一个ExportCache(单列模式), 这个cache里面有三个list,分别对应之前逻辑A,逻辑B,逻辑C对应的比对结果list,每次比对完毕的时候,往这个cache的对应list里add进去。

       我另外有一个执行导出动作--Export的Runable,在进入比对方法时,开启比对线程之前,开辟这个单独为执行导出的线程,让他一直在跑,判断如果cache里面的list有值了,那么我就做输出动作,输出完了从对应list里面给remove掉,当然每次也是1000条,哈哈!这个导出的线程就不在compare方法里面等待关闭了,开着就一直开着吧,后面关闭系统了再统一关闭就行了。

        


        说到这里,整个思路全部出来了,看在这么多字的份上,赞一个呗!  有什么优化的建议,欢迎大家留言回复!不慎感激!  

最后上张图,以正试听,界面大家就不要扔翔了!



© 著作权归作者所有

共有 人打赏支持
Alfie
粉丝 6
博文 9
码字总数 6237
作品 0
长沙
高级程序员
私信 提问
加载中

评论(25)

s
soxgoon
scala actor
ExtremeTalk
ExtremeTalk
我也做过数据库比较工具,也是Swing的,似曾相识啊
☆冰山一角☆
应该现有对比数据库结构的;数据的对比最好能生成补丁sql就完美了。
Alfie
Alfie

引用来自“美好的2014”的评论

引用来自“Alfie”的评论

引用来自“美好的2014”的评论

如果数据只是十万级别,完全可以考虑到全部加在到内存的哈希结构中处理。而如果楼主还想考虑数据增长情况下的运行效率问题,那么就有必要对比对算法重新设计,毕竟65秒-十万级数据,这个还是很慢的。

您好,非常感谢您的批评和建议,谢谢!
首先文章中有提到,一个是局域网的数据库,一个是远程外省的一个数据库服务器,首先收到网络带宽的影响,而非都是本地库。
其次要考虑到硬件的因素,您是在脚本服务器上跑,而我是在自己的笔记本上跑,当年玩多线程的时候有发现CPU对线程的影响是非常大的,比如说I53代和core2在速度上天差地远,更何况你是在服务器上跑,你可以去玩一玩就知道了
再次你是一次读入在内存中比对,土豪啊!这对普通的用户怎么说都太奢侈了,如果人家是32位的XP呢?
不知道您有没有全部读完,文章后面有提到,600W条数据的换算,如果每条才占100个中文字符,内存就要消耗有1.4G(这还只是理论值!)
再一次感谢您的建议,谢谢!

现在4G内存的机器都很常见吧,而且你是为公司做的工具,不可能一直跑在你自己的32位XP上吧?

是为公司做的,但一开始我给它的定位并非是给程序员,DBA一类专业人事用的,大众化一点的比对工具。
Alfie
Alfie

引用来自“美好的2014”的评论

引用来自“Alfie”的评论

引用来自“胡东成”的评论

对数据库不熟悉。。。

我在做A库分页查询的时候,同步收集了所有的A库key列对应的值,然后查询B库的时候,我一次全部 where keycolumn in ('','',''...)

是否考虑IN效率的问题?
in的是字段,而非子查询,不会出现笛卡尔积的情况,谢谢!

不知道你的数据库是不是MySQL,对于MySQL的某些低版本col IN(val1, val2, val3,....valn)和col=val1 OR col=val2 OR col=val3...OR col=valn,尤其是n非常大的时候,性能差距还是非常大的。

使用in的时候当时是就有考虑这个问题肯定会被大家揪住,目前来说就1000条一次的比对;
你个这个建议非常好,后面考虑对mysql做性能优化测试的时候用到,谢谢!
优雅先生
优雅先生

引用来自“Alfie”的评论

引用来自“胡东成”的评论

对数据库不熟悉。。。

我在做A库分页查询的时候,同步收集了所有的A库key列对应的值,然后查询B库的时候,我一次全部 where keycolumn in ('','',''...)

是否考虑IN效率的问题?
in的是字段,而非子查询,不会出现笛卡尔积的情况,谢谢!

不知道你的数据库是不是MySQL,对于MySQL的某些低版本col IN(val1, val2, val3,....valn)和col=val1 OR col=val2 OR col=val3...OR col=valn,尤其是n非常大的时候,性能差距还是非常大的。
优雅先生
优雅先生

引用来自“Alfie”的评论

引用来自“美好的2014”的评论

如果数据只是十万级别,完全可以考虑到全部加在到内存的哈希结构中处理。而如果楼主还想考虑数据增长情况下的运行效率问题,那么就有必要对比对算法重新设计,毕竟65秒-十万级数据,这个还是很慢的。

您好,非常感谢您的批评和建议,谢谢!
首先文章中有提到,一个是局域网的数据库,一个是远程外省的一个数据库服务器,首先收到网络带宽的影响,而非都是本地库。
其次要考虑到硬件的因素,您是在脚本服务器上跑,而我是在自己的笔记本上跑,当年玩多线程的时候有发现CPU对线程的影响是非常大的,比如说I53代和core2在速度上天差地远,更何况你是在服务器上跑,你可以去玩一玩就知道了
再次你是一次读入在内存中比对,土豪啊!这对普通的用户怎么说都太奢侈了,如果人家是32位的XP呢?
不知道您有没有全部读完,文章后面有提到,600W条数据的换算,如果每条才占100个中文字符,内存就要消耗有1.4G(这还只是理论值!)
再一次感谢您的建议,谢谢!

现在4G内存的机器都很常见吧,而且你是为公司做的工具,不可能一直跑在你自己的32位XP上吧?
Alfie
Alfie

引用来自“胡东成”的评论

对数据库不熟悉。。。

我在做A库分页查询的时候,同步收集了所有的A库key列对应的值,然后查询B库的时候,我一次全部 where keycolumn in ('','',''...)

是否考虑IN效率的问题?
in的是字段,而非子查询,不会出现笛卡尔积的情况,谢谢!
Alfie
Alfie

引用来自“坏孩子”的评论

建个db link做对比,直接写sql,用完删了db link

谢谢您的建议,这个完全可以有!
局限于数据库是人家的,需要考虑是否只有查询权限。
谢谢!
Alfie
Alfie

引用来自“美好的2014”的评论

如果数据只是十万级别,完全可以考虑到全部加在到内存的哈希结构中处理。而如果楼主还想考虑数据增长情况下的运行效率问题,那么就有必要对比对算法重新设计,毕竟65秒-十万级数据,这个还是很慢的。

您好,非常感谢您的批评和建议,谢谢!
首先文章中有提到,一个是局域网的数据库,一个是远程外省的一个数据库服务器,首先收到网络带宽的影响,而非都是本地库。
其次要考虑到硬件的因素,您是在脚本服务器上跑,而我是在自己的笔记本上跑,当年玩多线程的时候有发现CPU对线程的影响是非常大的,比如说I53代和core2在速度上天差地远,更何况你是在服务器上跑,你可以去玩一玩就知道了
再次你是一次读入在内存中比对,土豪啊!这对普通的用户怎么说都太奢侈了,如果人家是32位的XP呢?
不知道您有没有全部读完,文章后面有提到,600W条数据的换算,如果每条才占100个中文字符,内存就要消耗有1.4G(这还只是理论值!)
再一次感谢您的建议,谢谢!
问道:b/s的系统,测试自动化,求推荐

后台是java的servlet,前端有通常的html,javascript,css和特殊的xml请求相应。测试这块想搞成自动化,大家有没有推荐。或者是一个想法也行的。小小的奢望,针对测试的开发规模要小,最好能进行...

如比如比
2015/09/16
212
3
数据库结构比较工具--dbcompare

数据库结构比较工具,目前支持mysql,oracle,sql server. 概述: 在设计开发过程中经常会出现开发库与测试库不一致,测试库与生产库不一致,每次手工比对是个辛苦的活。 以前用java写过一个数...

dbcompare
2013/06/25
4.7K
0
Shell学习之路和我发布过的Shell脚本博文

Shell学习之路 目录 Shell学习之路【第一篇】:别名,管道,用户配置文件,变量,read Shell学习之路【第二篇】:条件测试,运算符,选择结构,for循环结构 Shell学习之路【第三篇】:While循环,C-...

yht_1990
2016/07/19
0
0
疯狂的小潘/IdCardFaceIdentifier

IdCardFaceIdentifier 项目介绍 基于虹软人脸识别与华视二代身份证阅读器的访客比对系统。 软件架构 开发工具: vs2017 开发包: 虹软人脸识别SDK + 华视CVR100SDK + Aforge 硬件: USB摄像头...

疯狂的小潘
08/02
0
0
Aqua Data Studio 数据库工具使用

Aqua Data Studio是一款完整IDE的数据库开发工具,它提供3种主要功能:数据查询与管理工具。比对数据工具与源控制和文件系统的整合工具。帮助你创建,编辑 和执行 SQL 的管理工具脚本编写,以...

易水寒丶开源
2015/10/22
2.6K
0

没有更多内容

加载失败,请刷新页面

加载更多

盘点愚人节各大网站彩蛋,谁最爱恶搞?

如今的愚人节俨然已是各品牌宣传了一个重要节日,同时,也成为了各大互联网科技企业凑热闹,比拼创意和策划的节日。跟小编一起看看有哪些有趣的策划吧! Google地图变成吃豆人游戏 每年愚人节...

临江仙卜算子
17分钟前
0
0
Java7/8 中的 HashMap 和 ConcurrentHashMap 全解析

本文分析的是源码,所以至少读者要熟悉它们的接口使用,同时,对于并发,读者至少要知道 CAS、ReentrantLock、UNSAFE 操作这几个基本的知识,文中不会对这些知识进行介绍。Java8 用到了红黑树...

java菜分享
18分钟前
0
0
玩手机与做实验

看过这样一个故事:说的是在二十世纪二十年代初的一个深夜,担任英国剑桥大学卡文迪许实验室主任的卢瑟福来实验室检查,发现一位学生还在做实验。卢瑟福就问他:“你上午做什么了?”学生回答...

Bob2100
51分钟前
4
0
Kafka流式处理

Kafka Streams 初识流式处理 什么是数据流 数据流(也叫事件流)是无边界数据集的抽象表示。无边界意味着无限和持续增长。无边界数据集之所以是无限的,是因为随着时间的推移,新记录会不断加...

东都大狼狗
今天
5
0
Mysql主从复制(拓展博客文章扩充知识面)

#不停库不锁表在线主从配置 使用 Xtrabackup 在线对MySQL做主从复制 1.数据量大的话还是建议使用工具例如xtrabackup,mysqldump比较适合操作10G以下的数据备份复制。 2.做业务之前考虑清楚具...

robertt15
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部