2017-12-28 3 views
0

다음 쿼리를 최적화 할 작업을했습니다.`from_unixtime`이 쿼리를 느리게 할 수 있습니까?

select 
c.account_key, 
c.cohort, 
date(concat(year(from_unixtime(min(f.processdate_est_key))), '-', 
month(from_unixtime(min(f.processdate_est_key))), '-1')) as 
customer_conversion_month 
from 
bidw_stage.cohort c left join 
bidw.fact f 
on 
c.account_key = f.account_key and 
f.usage_dollars != 0 and 
12 * (year(from_unixtime(f.processdate_est_key)) - year(c.cohort)) + 
(month(from_unixtime(f.processdate_est_key)) - month(c.cohort)) >= 2 
group by c.account_key, c.cohort; 

지난 1 월 완료까지 30 초가 걸렸습니다. 이제는 거의 3 분이 걸립니다. 사실 테이블에는 약 3 천만 개의 레코드가 포함되어 있으며, 코호트 테이블은 약 20k입니다. 사실 테이블 속성 'account_key'가 인덱싱되었지만 'cohort'테이블에 없습니다. 나는이 쿼리 원래 코더를 작성하지 않은

이 아래 쿼리를 둔화 될 수이

12 * (year(from_unixtime(f.processdate_est_key)) - year(c.cohort)) + 
    (month(from_unixtime(f.processdate_est_key)) - month(c.cohort)) 

이유에 관해서는 어떤 문서를 남아 있지? 어떻게 최적화 할 수 있습니까?

+1

열에 함수를 사용하면 인덱스를 사용할 수 없습니다. 인덱스는 원시 (조작되지 않은) 열 데이터에만 적용됩니다. –

+0

계산 열에 'WHERE'가있는 것은 대개 테이블 스캔이 필요하므로 성능이 잔인합니다. 이 칼럼들을 네이티브'DATETIME' 포맷으로 바꿀 수 있다면 반으로 갈 것입니다. 이 값 대신에 ['DATE_SUB()'] (https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_date-sub)를 사용할 수 있습니다. 이 공식. – tadman

+0

참고로, 그 조건은'processdate_est_key'가 적어도'cohort' 다음에 두 번째 달에 있는지 확인하는 것입니다. 따라서'cohort'가 2017 년 2 월에 있다면, 2017 년 4 월 이후에'processdate_est_key'에 적용될 것입니다. – Barmar

답변

0

인덱싱 된 열에서 함수를 호출하면 인덱스가 도움이되지 않습니다. 인덱싱 된 열의 수정되지 않은 값을 무언가와 비교하는 조건을 작성해야합니다.

processdate_est_key은 적어도 cohort 이후 두 번째 달에 있습니다. 이 칼럼을 날짜로 변환하고 년과 월을 추출하는 대신, 그 달의 시작 부분에 대해 유닉스 타임 스탬프를 생성하고 비교해야합니다.

AND f.processdate_est_key >= 
     UNIX_TIMESTAMP(CONCAT(YEAR(c.cohort + INTERVAL 2 MONTH), 
           MONTH(c.cohort + INTERVAL 2 MONTH), '01')) 

연결은, 그 해 달 추출 2 개월 c.cohort 후 날짜를 가져 그 달의 첫 날을 참조 01을 추가합니다. 그런 다음 f.processdate_est_key과 비교하기 위해 숫자 형식으로 변환하려면 UNIX_TIMESTAMP을 호출합니다.

+0

그 말이 틀림 없습니다! 고맙습니다. 너무 나쁜데 나는 당신을 투표 할 수 없다. –

+0

답변을 수락하는 것은 upvote보다 낫습니다. – Barmar