百万级表对比统计数据,如何提高效率和减少系统内存占用?

现有一个A表和B表,他们具有同样的表结构(ID, CODE, DATATIME,...),其中有一些数据具有相同的ID,现在需要统计:

  1. A表相对比B表有多少不同ID的数据
  2. B表相对比A表有多少不同ID的数据
  3. A表中有多少和B表ID相同但其他列不同的数据
  4. A表中有多少和B表ID相同并且其他列也相同的数据

需要注意的是,A表和B表的数据量均在500万左右,需要比较的列在10列左右,B表数据基本不会更新,但A表数据时刻可能更新。希望得到一个尽可能高效并且耗费内存较少的解决方案。

我的解决方案:

  1. 同时将A表和B表数据缓存到内存,拿着A表的每条数据逐条去B表中对比,同时统计结果。这样比较耗费内存,单条请求就可能耗费近几GB内存,放弃;
  2. 直接通过SQL查询出统计结果,例如SELECT COUNT(*) FROM A WHERE NOT EXSIT (SELECT 1 FROM B WHER A.ID = B.ID)得到问题1的结果。

环境:
MySQL5.7

阅读 3.4k
2 个回答

目前采用在A表打标记的方法,在A表新增了一个CHANGE_STATE列(bit(2)); 00-情况1,01-情况3;10-情况4;在B表新增一个CHANGE_STATE字段(B表中CHANGE_STATE为00的就表示情况2).开始时先手动处理一下库里的数据,之后对于A表任何一条记录的更新都同时更新他的CHANGE_STATE,如果是删除就需要去更新B表的CHANGE_STATE。查询时直接在A表中查(需要对A表的CHANGE_STATE列上创建索引),效率还不错,平均查询时间稳定在2S内

问题1:A表相对比B表有多少不同ID的数据

select count(*) from A left join B on A.id = B.id where B.id is null;

问题3:A表中有多少和B表ID相同但其他列不同的数据
步骤1、A、B表增加一列"uk",并创建索引;并创建触发器(插入、更新)更新uk列值;
步骤2、更新uk值为:

update a set uk = md5(concat_ws('-','1',col1,'2',col2,'3',col3));
update b set uk = md5(concat_ws('-','1',col1,'2',col2,'3',col3));

步骤3、

select count(*) from a inner join b on a.id = b.id where a.uk <> b.uk;


select count(*) from a left join b on a.id = b.id where b.id is null;
clipboard.png

select count(*) from a WHERE not exists (SELECT 1 FROM B WHERE A.ID = B.ID);
clipboard.png


补充回答:
问题3,4应该也可以在a表增加一列'is_eq_b'(1相同,0不同),然后在a,b表上添加插入、更新触发器,去更新'is_eq_b'的值,查询的时候直接查a表就可以了,应该能更快些。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进