코드 최적화 기록 - 대용량 그룹 분할 조회

요구 사항:
같은 페이지에 표시된 내용은 2개의 다른 데이터베이스 a, b에서 조회하고 a의 결과 id를 조건으로 b에서 조회해야 한다.만약 a의 결과 데이터량이 많으면 b에 나누어 조회해야 한다.
 
    JDK:1.6
지구층 프레임:ibatis2.0
 
주의 사항:
    1.순환 횟수
    2.메모리 사용량
 
public PageResult queryForPageListNew(int pageSize, int pageNum,AForm queryForm)
	{
		//        
		int i = 0;
		//    n
		int n = 200;
		//   a  
		PageResult pr = aDAO.queryForPageResult(queryForm
				.getParams(), pageSize, pageNum, A.class);
		List<A> aList = pr.getResultList();
		//    size
		int size = aList.size();
		//       ,    a    id
		List<Long> temp = new ArrayList<Long>();
		//    hashmap,size*2  hashmap resize()
		Map<Long, Long> countMap = new HashMap<Long, Long>(size*2);
		for (A a : aList)
		{
			i++;
			temp.add(a.getId());
			//  n          
			if (((i + n) % n == 0 && i < size)||(i==size))
			{
				//               DAOImpl,      List
				List<Map<String, Long>> countMapList = bDAO
						.queryCountByOwnerForList(temp);
				//        countMap 
				for (Map<String, Long> map : countMapList)
				{
					Long id = map.get("owner");
					Long count = map.get("count");
					countMap.put(id, count);
				}
				temp.clear();
			}
		}
		temp = null;
		for (A a : aList)
		{
			a.setCount(countMap.get(a.getId()));
		}
		countMap.clear();
		countMap = null;
		return pr;
	}

b의 ibatis SqlMap:
<select id="queryCountByOwnerForList" resultMap="resultMap.B" parameterClass="List">
        select 
        	t1.owner,
        	count(t1.owner) as count        	
		from t_b t1 
		where
			(
			 t1.status= 4 
			 or t1.status=5 
			 or t1.status=6
			)
			and t1.owner in 
        <iterate open= "(" close = ")" conjunction = ",">
			#[]#
        </iterate>
        group by t1.owner
</select>

HashMap countMap 사용 설명:
두 번의 조회 결과는 id를 비교하여 조합해야 합니다.두 번 조회한 결과 집합은 모두 리스트가 없습니다. 예를 들어 직접 조합하면 for 순환의 끼워넣기를 해야 합니다. 비교 방식은 다음과 같습니다.
		for(A a: aList){ 
			for(B b: countMapList){
				if(a.id==b.id)
				{
					  ...
				}
			}
		}

이렇게 하면 n의 제곱을 순환해야 조회 결과를 조합할 수 있고 HashMap을 사용하면 2n회만 순환할 수 있다
 
여기서는 HashMap 액세스 결과가 List 네스트보다 빠른 것으로 가정합니다(테스트되지 않음).
 
 
향상된 사고 방식:
     1.hashmap 초기화 값은
(int)(size/0.75)+1보다 크고 최소 2의 n차
참조: http://www.iteye.com/topic/539465 
     2.ibatis에서 List 매개변수를 지원하고 Object의 속성을 가져오는지 알 수 없습니다.가능하다면temp를 절약할 수 있습니까?
 
코드 초평:
    1.int n = 1000;
상수는 fanal static으로 설정해야 합니다.
 
    2.int size = aList.size();
그냥 aList로 할 수 있어요.크기 (), 변수를 더 정의할 필요가 없습니다
 
    3.List temp = new ArrayList();
길이도 초기화 가능
 
    4.if (((i + n) % n == 0 && i < size)||(i==size))
너무 복잡하고 이해하기 어려우며 가능한 한 대상을 대하는 사상을 사용하고, i 
    5.첫 번째 조회 aList가 비어 있는 것을 고려하지 않았고, 프로그램은 계속 아래로 실행되고 있습니다
 
초기 평가 후 코드:
 
private final static int SELECT_IN_NUMBER=200;

public PageResult queryForPageListNew(int pageSize, int pageNum,
			CorpClaimSetQueryForm queryForm)
	{
		//   a      
		PageResult pr = aDAO.queryForPageResult(queryForm
				.getParams(), pageSize, pageNum, A.class);
		List<A> aList = pr.getResultList();
		
		//   cssList          pr
		if (aList.size() <= 0)
		{
			return pr;
		}

		//       ,    a    id
		List<Long> temp = new ArrayList<Long>(SELECT_IN_NUMBER);

		//    hashmap,size*2  hashmap resize()
		Map<Long, Long> countMap = new HashMap<Long, Long>(aList.size() * 2);
		for (A a : aList)
		{
			temp.add(a.getId());

			//  n          
			if (temp.size() == SELECT_IN_NUMBER)
			{
				List<Map<String, Long>> countMapList = bDAO
						.queryCountByOwnerForList(temp);

				//        countMap 
				for (Map<String, Long> map : countMapList)
				{
					Long id = map.get("owner");
					Long count = map.get("count");
					countMap.put(id, count);
				}
				//   1 ,    temp
				temp.clear();
			}
		}
		
		// temp          
		if (!temp.isEmpty())
		{
			List<Map<String, Long>> countMapList = bDAO
					.queryCountByOwnerForList(temp);
			for (Map<String, Long> map : countMapList)
			{
				Long id = map.get("owner");
				Long count = map.get("count");
				countMap.put(id, count);
			}
			temp.clear();
			temp = null;
		}
        
		//                
		for (A a : aList)
		{
			a.setCount(countMap.get(a.getId()));
		}
		countMap.clear();
		countMap = null;
		return pr;
	}
 
 
재검토:
     1.집합 호출clear () 후,null로 설정할 필요가 없습니다. (방법이 호출되면 메모리가 자동으로 방출됩니다. 이 동작들은 모두 필요합니까?)
 
     2.한 단락의 코드에서 같은 코드를 두 번 사용하면 이 단락의 같은 코드를 추출하여 스스로 하나의 방법을 만들어야 한다
 
 
최종 코드:
 
private final static int SELECT_IN_NUMBER = 200;

/**
	 *                   ,        , n     。
	 * @param pageSize
	 * @param pageNum
	 * @param queryForm
	 * @return PageResult
	 */
	@SuppressWarnings("unchecked")
	@Override
	public PageResult queryForPageListNew(int pageSize, int pageNum,
			CorpClaimSetQueryForm queryForm)
	{
		//   a      
		PageResult pr = aDAO.queryForPageResult(queryForm
				.getParams(), pageSize, pageNum,A.class);
		List<A> aList = pr.getResultList();
		
		//   aList          pr
		if (aList.size() <= 0)
		{
			return pr;
		}

		//       ,    a  id
		List<Long> temp = new ArrayList<Long>(SELECT_IN_NUMBER);

		//    hashmap,size*2  hashmap resize()
		Map<Long, Long> countMap = new HashMap<Long, Long>(aList.size() * 2);
		for (A a : aList)
		{
			temp.add(a.getId());

			//  n          
			if (temp.size() == SELECT_IN_NUMBER)
			{
				queryAndWarpCountMap(temp, countMap);
			}
		}
		
		// temp          
		if (!temp.isEmpty())
		{
			queryAndWarpCountMap(temp, countMap);
		}
        
		//                
		for (A a : aList)
		{
			a.setCount(countMap.get(a.getId()));
		}
		return pr;
	}

	/**
	 *     ID  ,      ,       map 。
	 *       ID  
	 * @param temp
	 * @param countMap
	 */
	private void queryAndWarpCountMap(List<Long> temp, Map<Long, Long> countMap) {
		List<Map<String, Long>> countMapList = bDAO
				.queryCountByOwnerForList(temp);
		for (Map<String, Long> map : countMapList)
		{
			Long id = map.get("owner");
			Long count = map.get("count");
			countMap.put(id, count);
		}
		//   1 ,    temp
		temp.clear();
	}

 

좋은 웹페이지 즐겨찾기