현재 고유아이디와 시간값을 PK 로 하여, 해당 ID의 장비의 상태 데이터를 저장하는 테이블이 있습니다.
사용 프로그램 설정에 따라 해당 테이블에서 A장비의 11:30:01~11:31:32, 12:12:31 ~ 12:13:59 이런 시간간격범위로 쿼리를 해와야합니다.
시간 범위 조건은 하나가 될 수도 있고, 여러개가 될수도 있어서 현재 프로그램상에서 WHERE절에 시간범위 or 시간범위 ... 이런식으로 or로 조건을 붙여서 쿼리를 합니다.
이렇게 하니 쿼리가 엄청 느리네요. 분석을 하면 PK INDEX SCAN을 한다고는 표시가 되는데, 향상시킬 방법이 없을까요? ㅠ.ㅠ
"Index Scan using "PK_HIS_WORKING_DATA" on his_working_data w (cost=0.00..454258.47 rows=1 width=16) (actual time=310077.684..310077.684 rows=0 loops=1)"
" Index Cond: ((booth_id = 3) AND (zone_id = 3) AND (robot_id = 9))"
" Filter: ((factory_id = 202) AND (color = 16) AND (((time_stamp >= to_timestamp('2017-07-05 13:31:24.981'::text, 'YYYY-MM-DD HH24:MI:SS.MS'::text)) AND (time_stamp <= to_timestamp('2017-07-05 13:31:56.7'::text, 'YYYY-MM-DD HH24:MI:SS.MS'::text))) OR ((time_stamp >= to_timestamp('2017-07-05 13:29:24.231'::text, 'YYYY-MM-DD HH24:MI:SS.MS'::text)) AND (time_stamp <= to_timestamp('2017-07-05 13:30:35.653'::text, 'YYYY-MM-DD HH24:MI:SS.MS'::text))) OR ((time_stamp >= to_timestamp('2017-07-05 13:25:23.59'::text, 'YYYY-MM-DD HH24:MI:SS.MS'::text)) AND (time_stamp <= to_timestamp('2017-07-05 13:26:35.247'::text, 'YYYY-MM-DD HH24:MI:SS.MS'::text))) OR ((time_stamp >=
..."
Rows Removed by Filter: 4872347"
"Total runtime: 310079.625 ms"
select *
FROM his_working_data as w
WHERE w.factory_id = 202 and w.booth_id = 3 and w.zone_id = 3 and w.robot_id = 9 and ( w.time_stamp BETWEEN to_timestamp('2017-07-05 13:31:24.981','YYYY-MM-DD HH24:MI:SS.MS') AND to_timestamp('2017-07-05 13:31:56.7','YYYY-MM-DD HH24:MI:SS.MS') OR w.time_stamp BETWEEN to_timestamp('2017-07-05 13:29:24.231','YYYY-MM-DD HH24:MI:SS.MS') AND to_timestamp('2017-07-05 13:30:35.653','YYYY-MM-DD HH24:MI:SS.MS') OR....
특정 작업을 한 시간대가 저장된 테이블이 따로 있을 것 같네요.
쿼리를 스트링으로 만들지 마시고 조인형태로 풀어보세요.
SELECT * FROM his_working_data AS w INNER JOIN xxx AS x -- 특정 작업을 한 시간대가 저장된 테이블 ON w.time_stamp BETWEEN x.s_time_stamp AND x.e_teim_stamp WHERE w.factory_id = 202 AND w.booth_id = 3 AND w.zone_id = 3 AND w.robot_id = 9 AND w.color = 16 AND x.zzz = 111 -- 특정 작업 추출 조건 ;
저 시간대 조건이 계속 변동 되어서 테이블로 관리하기 어렵고(혹은 테이블로 관리가 안 되고 있다든지)
파싱부하가 너무 심하다면
시간대를 10개 정도씩(성능이 괜찮다면 더 큰 크기로..) 가지고 오는 쿼리를 만드시고
리터럴로 처리할 게 아니라 바인드변수로 만드세요.
select ~
from table
where (시간대1바인드변수처리 or 시간대2바인드변수처리 or .. 시간대10바인드변수처리)
and 시간대최소~최대탐색조건
프로그램단에서 10개의 조건씩 끊어서 쿼리를 날리시고 결과 데이터셋에 계속 append해주시는 게 좋을 것 같습니다.
아.. 생각해보니 id 별 시간대가 많지 않을 것 같네요..
id별로 시간대가 아주 많을 경우에는 index로 access하는 게 효율적이지만 id별로 시간대 종류가 아주 작다면 수직탐색보다
그냥 filter하는 게 낫다고 옵티마이져가 판단한 것 같아 보이네요.
만약 id별로 시간대가 아주 많은데 filter 처리되었다면 통계정보가 실제와 다르거나..
------------------------------------------------------------------------------
실제로 10만 건 데이터를 생성하고 id를 제 각각 다르게 했을 때는 filter,
전부 동일하게 했을 때는 access 되네요.
------------------------------------------------------------------------------
시간대 or 조건을 5건만 해본다
-> 여전히 filter이지만 빨라졌다 -> 쿼리 길이 문제
-> 여전히 느리다 -> 통계정보 안 맞음