性能问题:对上万条数据进行验证

时间:2022-11-24 23:28:48
问题是这样的:
       我用的数据库树mysql,有两张表分别是A表跟B表,两张表分别在不同的数据库,有900多个字段,数据为10万条。
B表里面的数据是从A表里迁移过去的,为了防止数据丢失和数据在迁移的过程中出错,所以我需要做一个小程序进行验证。
这里我的程序是写出来了,但是性能很差,检测每个字段下面的数据需要1分多钟.....
      我想请教各位高手提出你们宝贵的意见,还有一点我要说的就是我使用 JAVA 的 JDBC 来连接数据库的
      希望能够说的稍微详细点,大概需要用多少时间请标明
                                                                                           谢谢各位大虾了

41 个解决方案

#1


900个字段10万条数据,验证完毕1分钟多,算是快的了。

#2


Mark 准备记笔记

#3


如果只是数据迁移的话就不要走java这个层了。直接数据库操作就可以了,数据库之间的远程导入。

#4


朋友我是说  验证一列数据需要1分多钟,
   一共有 900多列数据需要验证,

#5


A与B取dump比较.

#6


你一列一列比较得多少个SELECT? 为何不都取出来比较?
想优化的话就是减少SELECT的次数.

#7



 回复3楼的朋友:
    数据迁移的问题不用考虑,现在我要做的就是进行验证迁移后的数据,有没有办法提高检测效率

#8


建议在数据层解决。重新考虑业务逻辑。
如果可以,尝试一下MSsql2005/2008的镜像服务器

#9


引用 7 楼 PrinceSuperman 的回复:
回复3楼的朋友:
数据迁移的问题不用考虑,现在我要做的就是进行验证迁移后的数据,有没有办法提高检测效率


在迁移的时候在存储过程顺便就做数据验证过滤了

#10


占楼学习

#11


引用 9 楼 kokobox 的回复:
引用 7 楼 PrinceSuperman 的回复:

回复3楼的朋友:
数据迁移的问题不用考虑,现在我要做的就是进行验证迁移后的数据,有没有办法提高检测效率


在迁移的时候在存储过程顺便就做数据验证过滤了
 朋友你讲的很对,不过这不是我考虑的,现在摆在我面前的问题是对这10W 条数据验证进行优化

#12


建议一行一行的验证.按照LZ描述,一列验证花了1分钟。那么一行的一个字段验证为 1/10万 分钟,里面还有去SELECT的时间,假设一次SELECT的时间占一次验证的4/5,按行验证算下来总共要花的时间1*4/5 + 1/5*900 = 180.8分钟 = 3小时。

#13


引用 6 楼 runffer_yang 的回复:
你一列一列比较得多少个SELECT? 为何不都取出来比较?
想优化的话就是减少SELECT的次数.

朋友你说的有道理
我一列一列的取是防止中间数据丢失会有问题,我感觉是应为我的java 代码写的不够好
有没有这方面的意见?

#14


可不可以用多台机器来验证呢
如果使用多台机器, 每台机器平均分配需要验证的行数, 这样时间就可以大大的节省了吧

#15


刚刚回复的又丢,,,看看用连接池吧,,先把数据提到内存中,,然后用尽可能少的SELECT语句进行验证,,试试看

#16


引用 12 楼 x360995630 的回复:
建议一行一行的验证.按照LZ描述,一列验证花了1分钟。那么一行的一个字段验证为 1/10万 分钟,里面还有去SELECT的时间,假设一次SELECT的时间占一次验证的4/5,按行验证算下来总共要花的时间1*4/5 + 1/5*900 = 180.8分钟 = 3小时。


我有点没看清楚,为什么要一行一行?总共有10万行啊....select要10万次
但是列的话只有 900多列,我也才select 900多次!!
能不能说明白点?

#17


关键在于多次从数据库取数据降低效率
从B取所有数据,缓存,ID单独保存之int数组B_IDsARR[]
然后:
StringBuffer B_IDs = new StringBuffer(B_IDsARR[0]);
for(int i = 1; i < B_IDsARR.length; i++) 
B_IDs.append(" , " + B_IDsARR[i]);
"select x,x,x,x…… form A where id in " + B_IDs.toString();
现在想随你折腾吧

#18


楼主都需要验证哪些信息啊? 900*10万 个元素都要一一对比吗 ?是不不是每个元素都要验证,有必要吗?

#19


"select x,x,x,x…… form A where id in ( " + B_IDs.toString() + " )";

#20


一列一列的取的话,尽管才有900多SELECT,不过每个SELECT传输的数据是很惊人的.
你可以分几次全取: 
select * from table order by id LIMIT 1000 OFFSET 0
select * from table order by id LIMIT 1000 OFFSET 1000
select * from table order by id LIMIT 1000 OFFSET 2000
select * from table order by id LIMIT 1000 OFFSET 3000
可以调整LIMIT和OFFSET的值,这些SELECT也可以分配到几台机器同时执行.

我还是认为用mysql_dump把表格弄出来比较的话最快,时间都浪费到传数据上了.

#21


引用 18 楼 gudufeiyang 的回复:
楼主都需要验证哪些信息啊? 900*10万 个元素都要一一对比吗 ?是不不是每个元素都要验证,有必要吗?

对都需要验证,而且还不能出一点问题

#22


引用 20 楼 runffer_yang 的回复:
一列一列的取的话,尽管才有900多SELECT,不过每个SELECT传输的数据是很惊人的.
你可以分几次全取:
select * from table order by id LIMIT 1000 OFFSET 0
select * from table order by id LIMIT 1000 OFFSET 1000
select * from table order by id LIMIT 1000 OFFSET 2000
select * from table order by id LIMIT 1000 OFFSET 3000
可以调整LIMIT和OFFSET的值,这些SELECT也可以分配到几台机器同时执行.

我还是认为用mys…


首先想说的就是 你的分页读取还是可取的,希望还有别的意见,
还有就是只能在一台机子上执行

#23


费时主要在两方面
1.SELECT特定的字段要比SELECT *费时,因为要做查找.
2.数据传输费时.

1的话没办法再简单了.
2的话你可以把900个字段做个检验码,比如说每个字段取md5码头3位连到一起,这样基本是不会出错而且传送量大减.

#24


.

#25


MySQl 不太了解。。。
Tsql有发布订阅功能。。。不错。。。。

#26


建设你换ORACLE,完全可以解决了

#27


引用 23 楼 runffer_yang 的回复:
费时主要在两方面
1.SELECT特定的字段要比SELECT *费时,因为要做查找.
2.数据传输费时.

1的话没办法再简单了.
2的话你可以把900个字段做个检验码,比如说每个字段取md5码头3位连到一起,这样基本是不会出错而且传送量大减.

我现在是通过Map把某一列的值存起来,把id存在key里,再去通过id取,
你能不能把你的代码提供出来供我参考下,

#28


这个问题值得学习!

#29


学习····

#30


学习~

#31


mark

#32


SELECT CONCAT(LEFT(md5(字段1),3), LEFT(md5(字段2),3),...) FROM table;
当然这个SQL用程序自动生成。

#33


用多线程分页读取 应该会快点吧

#34


建议LZ把字段联合起来,不要900个列就比较900多次,不仅效率低,而且超级麻烦。
既然是要验证,那么只要判断是对还是错就行了!

#35


引用 34 楼 gxj760998 的回复:
建议LZ把字段联合起来,不要900个列就比较900多次,不仅效率低,而且超级麻烦。 
既然是要验证,那么只要判断是对还是错就行了!

按你的算法,字段间要用特列字符作分隔,否则会有可能

'abcde' + 'fgh' == 'abc' + 'defgh'

#36


留名学习

#37


900个字段10万条数据,验证完毕1分钟多,算是快的了

#38


引用 35 楼 gengzhw 的回复:
引用 34 楼 gxj760998 的回复:
建议LZ把字段联合起来,不要900个列就比较900多次,不仅效率低,而且超级麻烦。 
既然是要验证,那么只要判断是对还是错就行了! 
 
按你的算法,字段间要用特列字符作分隔,否则会有可能 

'abcde' + 'fgh' == 'abc' + 'defgh'


一个思路,至于具体的拼法,就让LZ自己考虑好了!
这个兄弟的补充还好,的确存在这样的可能!

#39


咱别说是900个字段了,就是900条数据查询还要一段时间。
        

#40


其实各位说的都有道理,
总的归纳为这么几种办法:
(1)分批读取数据在JAVA里进行处理
(2)加上线程进行处理
大概思路都差不多,但是具体的实现的细节能不能贴出来,贴出代码如果要是满意的话悬赏80分,另外还有20分给予想法有创意的朋友们

#41


一台机器的话加上多线程反而overhead增加,如果不是多核反而会变慢。
建议就开两个线程从A,B里取,
每个线程就一个SELECT:
SELECT CONCAT(LEFT(md5(字段1),3), LEFT(md5(字段2),3),...,LEFT(md5(字段900),3)) as verify_code FROM table; 
这样拿过来以后10万的循环,每次比较的字符串长度是3×90=270字节。
从一台mysql传输的数据量是270Byte×10万=27M,如果md5就取一位会是9M,但精度下降。

#1


900个字段10万条数据,验证完毕1分钟多,算是快的了。

#2


Mark 准备记笔记

#3


如果只是数据迁移的话就不要走java这个层了。直接数据库操作就可以了,数据库之间的远程导入。

#4


朋友我是说  验证一列数据需要1分多钟,
   一共有 900多列数据需要验证,

#5


A与B取dump比较.

#6


你一列一列比较得多少个SELECT? 为何不都取出来比较?
想优化的话就是减少SELECT的次数.

#7



 回复3楼的朋友:
    数据迁移的问题不用考虑,现在我要做的就是进行验证迁移后的数据,有没有办法提高检测效率

#8


建议在数据层解决。重新考虑业务逻辑。
如果可以,尝试一下MSsql2005/2008的镜像服务器

#9


引用 7 楼 PrinceSuperman 的回复:
回复3楼的朋友:
数据迁移的问题不用考虑,现在我要做的就是进行验证迁移后的数据,有没有办法提高检测效率


在迁移的时候在存储过程顺便就做数据验证过滤了

#10


占楼学习

#11


引用 9 楼 kokobox 的回复:
引用 7 楼 PrinceSuperman 的回复:

回复3楼的朋友:
数据迁移的问题不用考虑,现在我要做的就是进行验证迁移后的数据,有没有办法提高检测效率


在迁移的时候在存储过程顺便就做数据验证过滤了
 朋友你讲的很对,不过这不是我考虑的,现在摆在我面前的问题是对这10W 条数据验证进行优化

#12


建议一行一行的验证.按照LZ描述,一列验证花了1分钟。那么一行的一个字段验证为 1/10万 分钟,里面还有去SELECT的时间,假设一次SELECT的时间占一次验证的4/5,按行验证算下来总共要花的时间1*4/5 + 1/5*900 = 180.8分钟 = 3小时。

#13


引用 6 楼 runffer_yang 的回复:
你一列一列比较得多少个SELECT? 为何不都取出来比较?
想优化的话就是减少SELECT的次数.

朋友你说的有道理
我一列一列的取是防止中间数据丢失会有问题,我感觉是应为我的java 代码写的不够好
有没有这方面的意见?

#14


可不可以用多台机器来验证呢
如果使用多台机器, 每台机器平均分配需要验证的行数, 这样时间就可以大大的节省了吧

#15


刚刚回复的又丢,,,看看用连接池吧,,先把数据提到内存中,,然后用尽可能少的SELECT语句进行验证,,试试看

#16


引用 12 楼 x360995630 的回复:
建议一行一行的验证.按照LZ描述,一列验证花了1分钟。那么一行的一个字段验证为 1/10万 分钟,里面还有去SELECT的时间,假设一次SELECT的时间占一次验证的4/5,按行验证算下来总共要花的时间1*4/5 + 1/5*900 = 180.8分钟 = 3小时。


我有点没看清楚,为什么要一行一行?总共有10万行啊....select要10万次
但是列的话只有 900多列,我也才select 900多次!!
能不能说明白点?

#17


关键在于多次从数据库取数据降低效率
从B取所有数据,缓存,ID单独保存之int数组B_IDsARR[]
然后:
StringBuffer B_IDs = new StringBuffer(B_IDsARR[0]);
for(int i = 1; i < B_IDsARR.length; i++) 
B_IDs.append(" , " + B_IDsARR[i]);
"select x,x,x,x…… form A where id in " + B_IDs.toString();
现在想随你折腾吧

#18


楼主都需要验证哪些信息啊? 900*10万 个元素都要一一对比吗 ?是不不是每个元素都要验证,有必要吗?

#19


"select x,x,x,x…… form A where id in ( " + B_IDs.toString() + " )";

#20


一列一列的取的话,尽管才有900多SELECT,不过每个SELECT传输的数据是很惊人的.
你可以分几次全取: 
select * from table order by id LIMIT 1000 OFFSET 0
select * from table order by id LIMIT 1000 OFFSET 1000
select * from table order by id LIMIT 1000 OFFSET 2000
select * from table order by id LIMIT 1000 OFFSET 3000
可以调整LIMIT和OFFSET的值,这些SELECT也可以分配到几台机器同时执行.

我还是认为用mysql_dump把表格弄出来比较的话最快,时间都浪费到传数据上了.

#21


引用 18 楼 gudufeiyang 的回复:
楼主都需要验证哪些信息啊? 900*10万 个元素都要一一对比吗 ?是不不是每个元素都要验证,有必要吗?

对都需要验证,而且还不能出一点问题

#22


引用 20 楼 runffer_yang 的回复:
一列一列的取的话,尽管才有900多SELECT,不过每个SELECT传输的数据是很惊人的.
你可以分几次全取:
select * from table order by id LIMIT 1000 OFFSET 0
select * from table order by id LIMIT 1000 OFFSET 1000
select * from table order by id LIMIT 1000 OFFSET 2000
select * from table order by id LIMIT 1000 OFFSET 3000
可以调整LIMIT和OFFSET的值,这些SELECT也可以分配到几台机器同时执行.

我还是认为用mys…


首先想说的就是 你的分页读取还是可取的,希望还有别的意见,
还有就是只能在一台机子上执行

#23


费时主要在两方面
1.SELECT特定的字段要比SELECT *费时,因为要做查找.
2.数据传输费时.

1的话没办法再简单了.
2的话你可以把900个字段做个检验码,比如说每个字段取md5码头3位连到一起,这样基本是不会出错而且传送量大减.

#24


.

#25


MySQl 不太了解。。。
Tsql有发布订阅功能。。。不错。。。。

#26


建设你换ORACLE,完全可以解决了

#27


引用 23 楼 runffer_yang 的回复:
费时主要在两方面
1.SELECT特定的字段要比SELECT *费时,因为要做查找.
2.数据传输费时.

1的话没办法再简单了.
2的话你可以把900个字段做个检验码,比如说每个字段取md5码头3位连到一起,这样基本是不会出错而且传送量大减.

我现在是通过Map把某一列的值存起来,把id存在key里,再去通过id取,
你能不能把你的代码提供出来供我参考下,

#28


这个问题值得学习!

#29


学习····

#30


学习~

#31


mark

#32


SELECT CONCAT(LEFT(md5(字段1),3), LEFT(md5(字段2),3),...) FROM table;
当然这个SQL用程序自动生成。

#33


用多线程分页读取 应该会快点吧

#34


建议LZ把字段联合起来,不要900个列就比较900多次,不仅效率低,而且超级麻烦。
既然是要验证,那么只要判断是对还是错就行了!

#35


引用 34 楼 gxj760998 的回复:
建议LZ把字段联合起来,不要900个列就比较900多次,不仅效率低,而且超级麻烦。 
既然是要验证,那么只要判断是对还是错就行了!

按你的算法,字段间要用特列字符作分隔,否则会有可能

'abcde' + 'fgh' == 'abc' + 'defgh'

#36


留名学习

#37


900个字段10万条数据,验证完毕1分钟多,算是快的了

#38


引用 35 楼 gengzhw 的回复:
引用 34 楼 gxj760998 的回复:
建议LZ把字段联合起来,不要900个列就比较900多次,不仅效率低,而且超级麻烦。 
既然是要验证,那么只要判断是对还是错就行了! 
 
按你的算法,字段间要用特列字符作分隔,否则会有可能 

'abcde' + 'fgh' == 'abc' + 'defgh'


一个思路,至于具体的拼法,就让LZ自己考虑好了!
这个兄弟的补充还好,的确存在这样的可能!

#39


咱别说是900个字段了,就是900条数据查询还要一段时间。
        

#40


其实各位说的都有道理,
总的归纳为这么几种办法:
(1)分批读取数据在JAVA里进行处理
(2)加上线程进行处理
大概思路都差不多,但是具体的实现的细节能不能贴出来,贴出代码如果要是满意的话悬赏80分,另外还有20分给予想法有创意的朋友们

#41


一台机器的话加上多线程反而overhead增加,如果不是多核反而会变慢。
建议就开两个线程从A,B里取,
每个线程就一个SELECT:
SELECT CONCAT(LEFT(md5(字段1),3), LEFT(md5(字段2),3),...,LEFT(md5(字段900),3)) as verify_code FROM table; 
这样拿过来以后10万的循环,每次比较的字符串长度是3×90=270字节。
从一台mysql传输的数据量是270Byte×10万=27M,如果md5就取一位会是9M,但精度下降。