본문 바로가기

daily life -field

배치- for문 update와 update join쿼리

반응형

  1. 7일동안 지면의 상품/비상품별로 노출수를 측정하여 노출수에 따른 지면의 기준 노출 수를 차등하여 노출수를 조절



  1.  21만미만 지면들을 우선 추가 프레임의 상태를 변경(우선추가상태코드)





1번과 2번에 충족되는 배치 프로그램을 개발하는데, 개발의 범위(대상)을 먼저 파악함.

1)
  • 7일동안의 노출수를 기준으로 A,B,C,D,E 등급으로 나눈다.
  • 등급에 따른 노출수를 계산한다.
  • 지면에 따라 노출수를 업데이트한다.

2)
  • A등급을 제외한 지면들 찾는다.
  • 사이클당 1등횟수가 1등인 프레임을 사이즈별로 찾는다.
  • 7일간 CTR 1등인 프레임을 사이즈별로 찾는다.
  • 찾은 프레임들중에 해당 지면에 등록된 프레임중 현재 상태가 사용중/블랙리스트(사용안함)이 아닌 대기, 우선추가를 우선추가로상태로 변경하고 우선순위를 높여해 블랙리스트값을 -1씩 증가해준다.


스프링부트기반으로 테스트작성
1)개발작성
        @Test
        public void updateBaseRequestView() {
            //대상자 조회
            List<FrameDayStatsBaseViewVo> list = frameMapper.getFrameDayStatsFrom7DayPeriodList();
            log.info("list size=> " + list.size());
        }


          <select id="getFrameDayStatsFrom7DayPeriodList" resultType="FrameDayStatsBaseViewVo">
                   SELECT
                     media_script_no AS mediaScriptNo,
                    (SELECT BNR_CODE FROM FRME_MEDIA_INFO fmi WHERE fmi.media_script_no =  t.media_script_no) AS frameSize,
                     prdt_tp_code AS prdtTpCode,
                     t.view AS parEprsCnt,
                     (
                       CASE
                         WHEN t.view >= 210000
                         THEN 'A'
                         WHEN t.view >= 105000
                         THEN 'B'
                         WHEN t.view >= 35000
                         THEN 'C'      
                         ELSE 'D'
                       END
                     ) AS groupType,
                     (
                       CASE
                         WHEN t.view >= 210000
                         THEN 10000
                         WHEN t.view >= 105000
                         THEN ROUND(t.view/42 + 5000)
                         WHEN t.view >= 35000
                         THEN ROUND(t.view/28 + 3750)
                         ELSE 5000
                       END
                     ) AS baseRequestEprsCnt 
                   FROM
                     (SELECT
                       media_script_no,
                       prdt_tp_code,
                       SUM(par_eprs_cnt) VIEW,
                       SUM(click_cnt) click
                     FROM
                       FRME_DAY_STATS
                     WHERE stats_dttm BETWEEN DATE_FORMAT(
                         DATE_ADD(NOW(), INTERVAL - 7 DAY),
                         "%Y%m%d"
                       )
                       AND DATE_FORMAT(
                         DATE_ADD(NOW(), INTERVAL - 1 DAY),
                         "%Y%m%d"
                       )
                     GROUP BY media_script_no, prdt_tp_code) t                 
                     ORDER BY groupType, parEprsCnt, mediaScriptNo DESC
          </select> 


데이터 3299건정도 되었다.

로그를 찍어 그룹별로 확인하니 mapCount=> {A=394, B=205, C=456, D=2244} 총 3299개
A 그룹은 기존 노출수가 10000이라 변경할 필요가 없고
B 그룹부터 D그룹까지 각각 계산된 노출수를 변경해야한다.
2905건을 업데이트 해야된다.

for문을 돌려 2905건을 update 해야되는데, 상당히 시간과 비용이 발생된다.
따라서 update를 해야되는 테이블 구조와 뽑아온 대상 컬럼들을 비교하여 update join 문으로 작성하여 한번에 일괄적으로 작업하는 방향으로 바꿨다.
select 문을 검색하는 시간만큼 update도 비슷한 시간이 된다.

Java에서 프로그램을 작성해서 배치로 돌리기전에 1개의 row단위로 update 해야되는지, 조회한 데이터를 가지고 일괄적으로 가능한지를 판단 한 후 적용하는것이 더 좋은거 같다.

2번도 1번과 비슷한 방법으로 일괄적으로 업데이터가 가능한지 판단 한 후 적용한다.


결론) 주기적인 배치 프로그램을 작성시 update로 같은 부분은 update join을 통해 일괄적으로 작업하는것이 낫고
update가 아닌 insert는 내부 로직을 통해 계산후에 적용해야된다면 row 단위로 처리할 수 밖에 없는 거 같다.

그리고 추가적으로 update join시에 제대로 된 쿼리인지 확인하기 위해 java에서 row단위로 처리하는 개수와 맞는지 꼭 확인후 사용하는 것이 안전하다.
update 시 explain으로 잘 작성된거지 확인하는 것도 중요하다. 모르고 update를 날릴 수 있으니...

반응형

'daily life -field' 카테고리의 다른 글

웹 브라우저 종류 버전 체크  (0) 2018.08.14