2014-06-06 2 views
0

MySQL 데이터베이스에서 70 초 이상 실행되는 쿼리를 실행하려고합니다. 인덱스가 사용되지 않는 이유에 대해 머리를 쓰고 있습니다.MySQL의 느린 쿼리 - 파일롯 ​​사용

다음은 쿼리 :

SELECT PriceId, InstrumentId, Date, Open, High, Low, Close, Volume, UnadjustedClose 
FROM price 
ORDER BY InstrumentId, Date DESC 

가격 테이블 (기타 인덱스 사이) InstrumentId와 인덱스, 날짜가 있습니다. 테이블 자체는 8 천만 개의 행을 가지며 2 개의 정수, 날짜, 5 자리 및 5 자리로 구성됩니다.

Explain 명령은 가능한 키, key 및 ref에 대해 ALL, Null 유형을 가지고 있으며 시스템이 filesort를 사용한다고 알려줍니다.

시스템에서 얻을 수있는 가장 좋은 방법인가요? 정렬을 더 빨리 수행하기 위해 색인이 사용될 것으로 예상했습니다.

추가 :

다음은 테이블 정의입니다 :

PriceId int PK, NN, AI 
InstrumentId int NN 
Date Date NN 
Open Decimal(12,4) 
High Decimal(12,4) 
Low Decimal(12,4) 
Close Decimal(12,4) 
UnadjustedClose Decimal(12,4) 
Volume BigInt 

Indexes: 

Primary -> PriceId 
IX_InstrumentId -> InstrumentId 
IX_Date -> Date 
IX_InstrumentDate -> InstrumentId, Date 

설명 출력은 다음과 같습니다

id: 1 
select_type: Simple 
table: price 
type: ALL 
possible_keys: NULL 
key: NULL 
key_len: NULL 
ref: NULL 
rows: 77926335 
Extra: using filesort 
+1

당신은 8 천만 개의 행을 가지고 있습니다. 정상입니다 ... 그리고 대역폭이 영향을 미칠 수 있습니다. 코어 수와 데이터 센터 프로세서도 – angel

+0

입니다. 테이블 정의와 'EXPLAIN' 출력을 게시 할 수 있습니까? – Xint0

+0

80 백만 행을 모두 한꺼번에 가져와야합니까? – newtover

답변

1

옵티마이 저는 모든 행을 검색 중이며 얻으려고하는 모든 열이 색인에 들어 있지 않기 때문에 색인을 사용하지 않습니다. 즉, 인덱스는 커버 인덱스가 아닙니다.

는 대부분의 경우 (당신이 검색하는 모든 것을) 전체 테이블을 스캔하는 것보다 당신은 몇 가지 옵션이 추가 열을 검색 할 수

를 인덱스를 기반으로 레코드에 대한 인덱스 및 조회를 사용하는 것이 덜 효과적이다 :

  • 색인에 필요한 모든 열을 포함하십시오. 더 많은 공간이 필요하고 쓰기 작업이 느려집니다.
  • 인덱스의 첫 번째 열을 기반으로 쿼리에 필터를 추가합니다. 필터가 충분히 선택적인 경우 (필요한 행 수를 적당한 수준으로 줄임) 서버는 색인을 사용합니다.
  • 이 마지막 옵션

    에 대해 (InstrumentID ASC, Date DESC)

편집 더에 기본 키 (클러스터링)을 수정 응용 프로그램에서 정렬을 수행합니다 적당한 크기

  • 에 데이터를 필터링

    테이블이 로그 테이블처럼 보입니다. 로그 테이블에서 중복을 제거하기 위해 각 레코드에 고유 한 정수 ID를 추가하는 것이 좋습니다 (대부분의 경우 그렇지 않습니다). 그러나 대부분의 경우 해당 ID를 사용하지 않습니다. MySQL에서 기본 키는 클러스터링 키입니다 (즉, 데이터가 디스크에서 순서대로 정렬 됨 - 더 많거나 적음). 단편화를 용서하십시오.)

    로그 테이블에서 로그 된 엔티티의 ID와 타임 스탬프 (InstrumentID, 귀하의 경우 날짜)를 클러스터 된 색인 (MySQL의 기본 키)으로 사용하는 것이 좋습니다. 이렇게하면 데이터 순서가 일반적인 비즈니스 요구에 맞춰 지므로 쿼리 성능이 향상됩니다.

    InstrumentID와 Date가 고유하면 (필자는 악기가 여러 가격을 동시에 가질 수없고 1 초 이내에 가격을 변경하는 것이 거의 불가능하다고 생각합니다), 복합 색인은 나아지 다. (자동 생성 된 정수 값보다 테이블을 분할하는 더 좋은 옵션이 추가되었습니다).

    사이드 노트 : 필터 ID를 사용하는 것보다 날짜별로 필터링하거나 정렬하는 경우 PK의 열 순서를 변경할 수 있습니다. 편집

    당신이 당신의 목표를 실현하려 더 나은 방법을 찾기 위해 대답해야합니다 몇 가지 질문의

    END :

    • 왜 당신이 테이블의 모든 80M의 레코드를 검색해야합니까?
    • 응용 프로그램이 실제로 모든 응용 프로그램을 사용합니까?
    • 그렇다면 데이터베이스 수준이 아닌 응용 프로그램 수준에서 정렬을 수행 할 수 있습니까?
    • 실제로 레코드 수의 순서는 무엇입니까?
  • +0

    고마워요. 머리에 못을 박았다고 생각합니다. 제 기본 키가 잘못되었습니다. 나는 변화를 만들고 또 가도록 할 것이다. – Liam

    0

    당신 때문에 행의 많은 수의를 가속화 할 수 없다. 이 쿼리에서 Materialized View을 만들고 일단 만들어지면 액세스가 빨라집니다.

    MySQL은 Materialized View을 지원하지 않으므로 튜토리얼 here을 사용하여 직접 구현할 수 있습니다.