2017-12-08 26 views
0

쿼리를 최적화하려고하지만 쿼리가 mysql이 인덱스를 사용하지 않는다고 설명합니다.mysql 인덱스에 인덱스를 강제로 추가 할 수 없습니다.

explain 
SELECT t1.* 

    FROM crypto_screener.prices as t1 FORCE INDEX (PRIMARY) 

    where t1.id = (
     select t2.id 
     from (select * 
       from 
       crypto_screener.prices FORCE INDEX (allfilters) 
       where date > '2017-12-07' 
      ) as t2 
     where t2.symbol = t1.symbol 
     order by t2.id desc 
     limit 1 
    ) 
; 

show index from prices;

Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment 
prices 0 PRIMARY 1 id A 57718 NULL NULL  BTREE  
prices 0 priceid 1 id A 57718 NULL NULL  BTREE  
prices 1 pricefilters 1 symbol A 369 NULL NULL YES BTREE  
prices 1 pricefilters 2 date A 57718 NULL NULL YES BTREE  
prices 1 datefilters 1 date A 506 NULL NULL YES BTREE  
prices 1 symbolfilters 1 symbol A 421 NULL NULL YES BTREE  
prices 1 allfilters 1 id A 57718 NULL NULL  BTREE  
prices 1 allfilters 2 symbol A 57718 NULL NULL YES BTREE  
prices 1 allfilters 3 date A 57718 NULL NULL YES BTREE  

테이블 내의 데이터의 양을 지금 실행되지 않는 쿼리입니다 :

내 쿼리입니다. 이것을 어떻게 최적화 할 수 있습니까?

+0

여기에 'allfilters'를 사용할 수 없습니다 (3 열 이상의 색인으로 날짜가 색인의 첫 번째 열이 아니므로 기본적으로이 색인은 이미 색인에 대한 색인이 있으므로 쓸모가 없습니다). 'datefilters'? –

+0

@RolandStarke 네, datefilters는 t2에서 작동합니다. –

+1

좋아요. 성능을 향상시키는 것으로 충분합니까? 나는이 쿼리가 선택하고있는 것에 대해 머리를 감쌀 수 없다. 알고있는 것이 재미있을 것입니다. –

답변

1

특정 날짜 범위 내에서 각각 symbol 값의 가장 높은 값인 id 값을 원하는 것으로 보입니다.

다음은 그렇게하는 방법입니다. 먼저 하위 쿼리를 사용하여 각 날짜에 대해 id 값이 가장 높은 값인 symbol, id 목록을 가져옵니다. 원하는 날짜가있는 테이블의 하위 집합입니다.

    SELECT symbol, MAX(id) id 
        FROM prices 
        WHERE date > '2017-12-07' 
        GROUP BY symbol 

이 부질

date, symbol, id의 화합물 인덱스에 의해 최적화 될 수있다. 왜? 색인을 첫 번째 적격 날짜에 무작위로 액세스 한 다음 기호 및 ID의 고유 값을 순차적으로 검색합니다.

해당 하위 쿼리를 테스트 할 수 있습니다. 합리적인 결과를 제공하는지 확인하십시오.

는 다음과 같이, 메인 쿼리에서 사용 :

SELECT t1.* 
    FROM prices t1 
    JOIN (
       SELECT symbol, MAX(id) id 
        FROM prices 
        WHERE date > '2017-12-07' 
        GROUP BY symbol 
     ) t2 ON t1.id = t2.id AND t1.symbol = t2.symbol 

지금, 당신의 id 값은 모두 고유하기 때문에, 당신은 AND t1.symbol = t2.symbol을 떠나는하여 ON 조건을 단순화 할 수 있습니다.

적절한 혼합 지수로 매우 빠르게 실행되어야합니다.

프로 팁 1 : 좋은 측정을 위해 여분의 인덱스를 만들지 마십시오. 실행할 필요가있는 쿼리에 도움이되는지 확인하십시오.

프로 팁 2 : date > '2017-12-07'은 지정한 날짜의 자정에 행을 제외하지만 해당 날짜의 자정 이후 모든 행을 가져옵니다. date 열의 데이터 형식이 DATETIME 인 경우 >을 사용하는 것이 잘못된 것입니다. 데이터 유형이 DATE 인 경우 필터는 date >= '2017-12-08'과 동일한 의미입니다.

프로 팁 3 : MySQL의 쿼리 플래너가 특정 인덱스를 사용하도록 강제하는 것은 일반적으로 비생산적입니다. 훨씬 더 나은 것은 올바른 색인이 있는지 확인하는 것입니다.

+0

이 답변을 주셔서 감사합니다. 나는이 문제로 당분간 고심하고 있었다. 매우 인상적이고 우아한 솔루션. 축하한다, 나는 감동했다. –