2014-04-02 1 views
0

일반적인 질문 제목의 약간 그러나 나는 다음과 같은 쿼리가 :MySQL의 성능 저하 - 향상시키는 방법?

SELECT t.from_number, COUNT(*) AS calls 
FROM t 
WHERE t.organisation_id = 999 
AND t.direction = 'inbound' 
AND t.start_time BETWEEN '2014-03-26' AND NOW() 
AND t.from_number != '' 
GROUP BY t.from_number 
ORDER BY calls DESC LIMIT 20 

을하고 488ms에서 실행됩니다.

그러나 그 테이블에서 데이터를 검색하는 것과 마찬가지로 해당 번호가 누구에게 속하는지 조회해야합니다. 해당가 12 초 그 수는, 내가 또 다른 필요 했어 속한 조직을 찾기 만의 가입 - 즉시 나는 JOIN 쿼리 실행 시간이 8에서 아무것도에 점프 추가로

SELECT t.from_number, COUNT(*) AS calls 
FROM t 
LEFT JOIN n on CONCAT('44', n.number) = t.from_number 
WHERE t.organisation_id = 999 
AND t.direction = 'inbound' 
AND t.start_time BETWEEN '2014-03-26' AND NOW() 
AND t.from_number != '' 
GROUP BY t.from_number 
ORDER BY calls DESC LIMIT 20 

조직 테이블에서 조직 이름을 검색하십시오.

t 저장 번호를 국가 번호부터 123456789 (로 :

t의 기수와 n은 위에서 추측 할 수로, 숫자가 각각 약간 다르게 저장되어있는 각각> 2,000,000 ~ 63,000이며, 44)은 별도의 열에 저장되어 있지만 은 CONCAT을 사용해야하는 이유는 44123456789으로 저장하지만 WHERE 절에 없으므로 성능에 영향을 미칠 것으로 생각하지 않았습니다.

내가 알 수있는 한, 각 테이블의 중요한 열을 인덱싱했습니다.

이 테이블과 관련하여 쿼리 성능을 향상시키는 방법에 대한 제안 사항이 있습니까?

LEFT JOIN n on CONCAT('44', n.number) = t.from_number 

그것은 기능 CONCAT('44', n.number)의 결과를 사용하여 테이블을 조인되어

업데이트

EXPLAIN 출력 문제는 JOIN 절에

id, select_type, table, possible_keys, key, key_len, ref, rows, Extra 

1 SIMPLE t index_merge organisation_id,start_time,direction,from_number organisation_id,direction 4,13 NULL 4174 Using intersect(organisation_id,direction); Using where; Using temporary; Using filesort 
1 SIMPLE n index NULL number 768 NULL 62759 Using index 
+1

테이블 구조 &'EXPLAIN' 출력을 넣어주세요. –

+2

cols에 색인이 붙어 있다면, 아마도 그 도끼가 훔쳐 갈 것입니다. 병목 목을 이해하려면 ** 설명 **을 시도하십시오.또 다른 옵션은 * contry code + number *를 가진 또 다른 col을 만들고 그와 결합하는 것입니다. – tuxuday

+0

질문이'EXPLAIN' 출력으로 업데이트되었습니다. – martincarlin87

답변

1

을 추가했다.

일부 데이터베이스 (오라클)는 기능을 기반으로 색인을 만들 수 있지만 다른 것은 (MySQL처럼) 작성할 수 없습니다. 따라서 테이블 n에 대한 인덱스를 사용하여 조인 할 수 없습니다.

해결책은 n에 사용 된 결과와 색인을 생성하는 것입니다.

당신은 유사한 코드를 사용할 수

:이 후

ALTER TABLE n ADD COLUMN extended_number varchar(128) null; 

UPDATE n 
    SET extended_number = CONCAT('44', number); 

CREATE INDEX ext_numb_idx 
      ON n.extended_number; 

는 쿼리의 JOIN 절을 수정

SELECT t.from_number, COUNT(*) AS calls 
    FROM t 
LEFT JOIN n on n.extended_number = t.from_number 
    WHERE t.organisation_id = 999 
     AND t.direction = 'inbound' 
     AND t.start_time BETWEEN '2014-03-26' AND NOW() 
     AND t.from_number != '' 
GROUP BY t.from_number 
ORDER BY calls DESC LIMIT 20 

그리고 MySQL은 새로 생성 된 인덱스를 사용하고 쿼리를 실행합니다 훨씬 더 빨리.