2014-10-16 2 views
1

처음 사용 된 용어가 옳지 않다면 죄송합니다. 나는 mySQL 전문가가 아니다.생성 된 열에 색인 추가

CREATE TABLE `accesses` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `time` int(11) DEFAULT NULL, 
    `accessed_at` datetime DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `index_accesses_on_accessed_at` (`accessed_at`) 
) ENGINE=InnoDB AUTO_INCREMENT=9278483 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 

이 표는 그것에 10.000.000 행이 :

는이 같은 테이블이 있습니다. 다음과 같은 쿼리를 사용하여 차트를 생성하는 데 사용합니다.

SELECT SUM(time) AS value, DATE(created_at) AS date 
FROM `accesses` 
GROUP BY date; 

이 쿼리는 매우 길며 (1 분 이상). 나는 그것을 최적화 할

(AVG, MIN 또는 MAX 대신 SUM, 또는과 특정 일 또는 월에 WHERE, 또는 GROUP BY HOUR(created_at), 등등 ...과) 다른 쿼리를 많이하고 있어요. 내가 가지고있는 가장 좋은 아이디어는 DATE(created_at), HOUR(created_at), MONTH(created_at)과 같이 중복성이있는 여러 열을 추가 한 다음 인덱스를 추가하는 것입니다.

...이 해결책이 좋습니까? 아니면 다른 것이 있습니까?

감사

+0

출력의 전체 테이블 선언을 제공하는 것이 현명 할 수 있습니다 : 'SHOW CREATE TABLE accesses' – NDM

+0

당신이 가지고있는 레코드의 양과 함께, 간단한 선택 쿼리에 대해 1 분은 hella long입니다. 나는이 질문을 [DatabaseAdministrators] (http://dba.stackexchange.com/)에게 가져다 줄 것이다. – Alternatex

+0

음, 결과 집합을 제한하지 않고 10mil 레코드에'group'과'sum'을합니다 ... – NDM

답변

2

예, 특정 쿼리를 최적화하기 위해 인덱스 영구 컬럼에 중복 데이터를 저장하기 위해 최적화 할 수 있습니다. 이것은 의 비정규 화의 한 예입니다.

데이터의 양과 쿼리 빈도에 따라 이것은 중요한 속도 향상이 될 수 있습니다 (@Marshall Tigerus는 너무 많이 무시합니다, IMHO).

나는 EXPLAIN 실행하여이를 테스트 :
mysql> explain SELECT SUM(time) AS value, DATE(created_at) AS date FROM `accesses` GROUP BY date\G      *************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: accesses 
    partitions: NULL 
     type: ALL 
possible_keys: NULL 
      key: NULL 
     key_len: NULL 
      ref: NULL 
     rows: 1 
    filtered: 100.00 
     Extra: Using temporary; Using filesort 

테이블 내 시험에서 비어 있다는 사실을 무시한다. 중요한 부분은 비싼 연산 인 Using temporary; Using filesort입니다. 특히 임시 테이블이 커져서 MySQL이 메모리에 맞지 않을 경우 특히 그렇습니다.

나는 그들에 약간의 열 및 인덱스를 추가 : MySQL은 올바른 순서로 행을 처리하는 인덱스 스캔을 할 수있는 알고 있기 때문에

mysql> alter table accesses add column cdate date, add key (cdate), 
    add column chour tinyint, add key (chour), 
    add column cmonth tinyint, add key (cmonth); 

mysql> explain SELECT SUM(time) AS value, cdate FROM `accesses` GROUP BY cdate\G 
*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: accesses 
    partitions: NULL 
     type: index 
possible_keys: cdate 
      key: cdate 
     key_len: 4 
      ref: NULL 
     rows: 1 
    filtered: 100.00 
     Extra: NULL 

은 임시 테이블과 filesort가 멀리 갔다.

+0

이 답변을 주셔서 감사합니다. 내 쿼리는 400ms 이내에 수행됩니다. 좋았어! – pierallard

+0

도와 드리겠습니다! 이제 삽입 및 업데이트시 생성 된 열을 created_date와 동기화하도록 트리거를 작성해야합니다. –