java解决mysql大数据联查问题
近期有一个需求是联查两张表比对三个字段
一般用mysql就可以解决
SELECT*
FROMtb_a aLEFT JOIN b ON a.test = b.testAND a.NAME = b.NAME AND a.type = b.type
但是表a和表b的数据量都很不小,大概在10w左右,由于并不是以固定的id去关联,加了索引也没有效果,使用navicate根本就查不出来。
这时候想到了使用java去查,一开始采用的是双重for去比对,但是导致内存溢出根本差不出来。
后来想到了使用map利用这三个字段作为key去查,查询结果很快,大概几秒内就查出来了,由于这次是一个数据比对导出,不涉及到上线业务,所以就没有进行进一步的优化。
下面是核心代码
public List<NoWidCompareDTO> getNoWidCompare() {List<NoWidCompareDTO> result = new ArrayList<>();// 为了方便直接查的,可以优化查询List<EEaResourceDataWidNo> noWidList = noWidMapper.selectList(null);List<CollectionAllLevel> otherList = allLevelMapper.selectList(null);log.info("开始比对:{}", DateUtil.now());// 构建一个以三个条件为键,CollectionAllLevel对象为值的Map,方便后续查找Map<String, CollectionAllLevel> otherMap = new HashMap<>();for (CollectionAllLevel allLevelDTO : otherList) {String key = getKey(allLevelDTO);otherMap.put(key, allLevelDTO);}for (EEaResourceDataWidNo noWidDTO : noWidList) {String key = getKey(noWidDTO);CollectionAllLevel allLevelDTO = otherMap.get(key);// 构建NoWidCompareDTO,并进行属性复制NoWidCompareDTO dto = BeanUtil.toBean(noWidDTO, NoWidCompareDTO.class);if (allLevelDTO != null) {// 如果比对成功进行复制BeanUtil.copyProperties(allLevelDTO, dto);}// 都要添加进去result.add(dto);}log.info("比对结束:{}", DateUtil.now());return result;}/*** 等级,馆藏名称,资源名称统一设置为key,当然也可以在查询的时候直接设置*/private String getKey(EEaResourceDataWidNo noWidDTO) {return noWidDTO.getLevel() + "_" + noWidDTO.getCollectionUnits() + "_" + noWidDTO.getResourceName();}/*** 等级,馆藏名称,资源名称统一设置为key,当然也可以在查询的时候直接设置*/private String getKey(CollectionAllLevel allLevelDTO) {return allLevelDTO.getOtherLevel() + "_" + allLevelDTO.getMuseumCollectionName() + "_" + allLevelDTO.getCollectionName();}
这效果和以a表作为主表进行左连接查询一样。
总之上面的代码仅作为简单的操作,还有一些逻辑都没校验,也可以进行优化,重点就是使用map的key,value进行操作比对