728x90
작업 중에 정말 궁금한 것이 생겼다.
필요한 데이터를 매번 디비에 가서 가져오는 것이 빠를까,
아니면 모든 데이터를 다 가져온 뒤, 메소드 안에서 for문으로 돌려서 비교하여 필요한 값을 가져오는 것이 ㄷ ㅓ 빠를까.
#. 테스트 소스 : 테스트라 빠른 결과값을 얻기 위해 컨트롤러에서 모든 걸 구현.
필요한 데이터를 매번 디비에 가서 가져오는 것이 빠를까,
아니면 모든 데이터를 다 가져온 뒤, 메소드 안에서 for문으로 돌려서 비교하여 필요한 값을 가져오는 것이 ㄷ ㅓ 빠를까.
#. 테스트 소스 : 테스트라 빠른 결과값을 얻기 위해 컨트롤러에서 모든 걸 구현.
1. 언어 : JAVA
2. Framework : Spring 3.0.5
3. 기능 : Depth를 가지는 트리형 카테고리 리스트를 뿌릴 때, 최상단 부모까지 정보를 모두 표시 해 준다.
2. Framework : Spring 3.0.5
3. 기능 : Depth를 가지는 트리형 카테고리 리스트를 뿌릴 때, 최상단 부모까지 정보를 모두 표시 해 준다.
예 ) Entertainment > Game > Puzzle
4. 문제 : 최말단 카테고리 정보를 가져와 상단의 부모 카테고리의 이름을 얻어 올 때, 전체 리스트 정보를 가지고 하나하나 디비에 접속해서 값을 얻어 오는 것이 빠른가, 최말단 카테고리 정보를 비교할 전체 리스트를 디비에 한번만 접속해서 가져온 후 계속 For 문으로 비교하여 값을 얻는 것이 빠른가.
(※ 참고 사항 : 전체 Row는 50개 정도.)
5. 사용 DB 엔진 : MySQL
public class TestController {
@Autowired
private TestService testService;
@Autowired
private CategoryCommonService categoryCommonService;
@Autowired
private StatisticsMapper statisticsMapper;
/* URL 주소 http://localhot/test로 요청을 보내면 결과값을 확인 할 수 있다. */
@RequestMapping("")
public String test(HttpServletRequest request) throws Exception{
HttpSession session = request.getSession();
List<StatisticsModel> statisticsList = new ArrayList<StatisticsModel>();
List<StatisticsModel> statisticsList = new ArrayList<StatisticsModel>();
/* 쿼리 날릴 때 필요한 파라미터 설정 */
Map<String, Object> map = new HashMap<String, Object>();
map.put("mppLevel",AppStateUtil.USER_MAPPING);
map.put("avrLevel",AppStateUtil.USER_APPROVAL);
map.put("memId",(Integer)session.getAttribute("memberId"));
map.put("isAdmin", AppStateUtil.SUPER_ADMIN.equals((String)session.getAttribute("memberLevel")));
map.put("appCategoryState", AppStateUtil.APPSTATE_COMPLETE_APPROVAL);
map.put("type", "predefined");
map.put("appMappingState", AppStateUtil.APPSTATE_WAITING_APPROVAL);
map.put("appApprovalState", AppStateUtil.APPSTATE_COMPLETE_APPROVAL);
/* 최말단 카테고리 리스트 가져오기 */
List<StatisticsModel> tempNewCategoryList = new ArrayList<StatisticsModel>();
int maxLevel = categoryCommonService.getMaxLevel(); //전체 카테고리에서 가장 큰 Depth값.
for(int t=1; t<=maxLevel; t++){
map.put("catLevel", t);
List<StatisticsModel> tempList = statisticsMapper.getMemberNewCategory(map);
if(tempList != null)
tempNewCategoryList.addAll(tempList);
}
/* 디비에 접속 : 시작 ***************************************************** */
// 디비 접속 반복으로 카테고리 정보 얻는 과정 시작 시간
long sTime = System.currentTimeMillis();
Iterator<StatisticsModel> iNew = tempNewCategoryList.iterator();
while(iNew.hasNext()){
StatisticsModel statisticsInfo = (StatisticsModel)iNew.next();
statisticsInfo.setCatName(categoryCommonService.makeNewCategoryPathName(statisticsInfo.getCatId()));
statisticsList.add(statisticsInfo);
}
System.out.println("1. ============================== BEFOR : " + sTime );
long eTime = System.currentTimeMillis();
System.out.println("1. ============================== AFTER : " + eTime);
System.out.println("1. HOW MANY : " +( eTime - sTime) );
/* 디비에 접속 : 끝 ***************************************************** */
/* for문으로 비교 : 시작 ****************************************************** */
sTime = System.currentTimeMillis(); // for문을 통해 카테고리 경로 얻는 과정 시작 시간
maxLevel = categoryCommonService.getMaxLevel();
for(int t=1; t<=maxLevel; t++){
map.put("catLevel", t);
List<StatisticsModel> tempList = statisticsMapper.getMemberNewCategory(map);
if(tempList != null)
tempNewCategoryList.addAll(tempList);
}
Map<String, List<NewCategoryModel>> allNewCategoryMap = categoryCommonService.getAllCategory(null);
// 전체 카테고리 가져와서, 카테고리 이름을 경로까지 표시 해 줄 때 비교 기준으로 쓴다.
List<NewCategoryModel> allNewCategoryList = (List<NewCategoryModel>)allNewCategoryMap.get("newCategoryList");
iNew = tempNewCategoryList.iterator();
while(iNew.hasNext()){
StatisticsModel statisticsInfo = (StatisticsModel)iNew.next();
String catId = statisticsInfo.getCatId();
String categoryPathName = "";
String parentName = "";
String parentId = "";
int categoryLevel = 1;
int t=0;
//각 말단 카테고리마다 해당 카테고리의 이름과 부모 카테고리 아이디를 얻는다.
for(t=0; t<allNewCategoryList.size(); t++) {
NewCategoryModel s = (NewCategoryModel)allNewCategoryList.get(t);
if( catId.equals(s.getCatId())){
parentId = s.getParentCatId();
categoryLevel = s.getCatLevel();
categoryPathName = s.getCatName();
}
}
//얻어온 부모 카테고리 아디디를 이용하여 반복문을 통해 카테고리 경로를 얻는다
while(categoryLevel > 1) { //자기자신은 이미 Path 에 추가 했으므로 1은 제외됨
for(t=0; t<allNewCategoryList.size(); t++) {
NewCategoryModel s = (NewCategoryModel)allNewCategoryList.get(t);
if(parentId != null && parentId.equals(s.getCatId())){
parentName = s.getCatName();
parentId = s.getParentCatId(); //다음 부모 아이디 설정
}
}
categoryPathName = parentName+ " > " + categoryPathName;
categoryLevel--;
}
statisticsInfo.setCatName(categoryPathName);
statisticsList.add(statisticsInfo);
}
System.out.println("2. ============================== BEFOR : " + sTime );
eTime = System.currentTimeMillis(); // for문을 통해 카테고리 경로 얻는 과정 끝나는 시간
System.out.println("2. ============================== AFTER : " + eTime);
System.out.println("2. HOW MANY : " +( eTime - sTime) );
return "test/test";
}
#. 결과
1. ============================== BEFOR : 1312423551746
1. ============================== AFTER : 1312423552899
1. HOW MANY : 1153
2. ============================== BEFOR : 1312423552900
2. ============================== AFTER : 1312423553099
2. HOW MANY : 199
#. 결론
디비에 여러번 접속하는 것보다 전체 데이터를 한번에 가져와서 for문으로 비교하는 것이 훨씬 빨랐다.
#. 파생되는 의문
1. 현재는 50건의 데이터만 가지고 테스트 하였기 때문에 문제가 안 되는 것 같지만, 수백만건의 데이터라고 가정한다면 그 많은 데이터를 메모리에 올려서 비교하는 것이 괜찮을까?
2. 다른 데이터베이스 (Oracle , MSSQL server 등)를 사용해도 같은 결과가 나올까?
================ KSUG에서 얻은 배움 ====================================================
by 신승한 님
#. 파생되는 의문
1. 현재는 50건의 데이터만 가지고 테스트 하였기 때문에 문제가 안 되는 것 같지만, 수백만건의 데이터라고 가정한다면 그 많
은 데이터를 메모리에 올려서 비교하는 것이 괜찮을까?
전부 메모리에 올리는건 불가능하기때문에
코드성 데이터 / 메뉴정보 처럼 자주 사용되고 양이 적은것은 전체 캐싱을 하거나,
자주 접근되는 데이터만 메모리에 올려놓고 활용할 수 있도록 캐싱엔진을 사용합니다.
2. 다른 데이터베이스 (Oracle , MSSQL server 등)를 사용해도 같은 결과가 나올까?
네
--------------------------------------------------------------------------------------------------------------------
메모리야 요즘 싸니까 데이터 수백만건을 올릴 수 있다고 해도 왜 메모리에서
는 1차월 배열에 담고 for 문으로 탐색하시나요? 알고리즘과 자료구조 시간에
배우는 지식을 활용할 좋은 기회인데요. ^^
그리고 직접 자료 구조 잡고 탐색 알고리즘 구현하기 어렵다면 hsql이나
javadb 같은 내장형 DB를 메모리만 사용하도록 설정하고 쓰는 방식도 생각해
볼만 합니다.
'Dev' 카테고리의 다른 글
Maven Build lifecycle and POM version SNAPSHOT (0) | 2015.02.28 |
---|---|
Windows XP 탐색기에서 이미지 미리보기 제거 (0) | 2013.01.27 |
Windows XP 자동실행 기능 막는 방법 (0) | 2013.01.27 |
XHR(Ajax) > Comet > HTML5 WebSockets (2) | 2011.04.25 |
웹페이지 만들 때 생각해야 할 것 (2) | 2010.08.10 |