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進行操作比對