2017-10-24 5 views
2

나는 100M 레코드를 가진 MySQL (InnoDB 엔진) 테이블을 가지고있다. 구조는 다음과 같습니다 :MySQL 테이블의 인덱스가 사용되지 않는 이유는 무엇입니까?

CREATE TABLE LEDGER_AGR (
    ID BIGINT(20) NOT NULL AUTO_INCREMENT, 
    `Booking` int(11) NOT NULL, 
    `LType` varchar(5) NOT NULL, 
    `PType` varchar(5) NOT NULL, 
    `FType` varchar(5) DEFAULT NULL, 
    `TType` varchar(10) DEFAULT NULL, 
    `AccountCode` varchar(55) DEFAULT NULL, 
    `AgAccountId` int(11) DEFAULT '0', 
    `TransactionDate` date NOT NULL, 
    `DebitAmt` decimal(37,6) DEFAULT '0.000000', 
    `CreditAmt` decimal(37,6) DEFAULT '0.000000', 
    KEY `TRANSACTION_DATE` (`TransactionDate`) 
) 
ENGINE=InnoDB; 

내가 뭐하는 거지 때 : 그것은 TRANSACTION_DATE 인덱스를 사용하지 않는

EXPLAIN 
SELECT * FROM LEDGER_AGR 
WHERE TransactionDate >= '2000-08-01' 
    AND TransactionDate <= '2017-08-01' 

. 그러나 나는 뭐하는 거지 때

EXPLAIN 
SELECT * FROM LEDGER_AGR 
WHERE TransactionDate = '2000-08-01' 

입니다TRANSACTION_DATE 인덱스를 사용. 누군가 제발 설명해 주시겠습니까?

답변

1

범위 쿼리 # 1의 선택도가 낮습니다. 균등 질의 # 2는 탁월한 선택성을 갖는다. 옵티마이 저는 결과 행이 표의 총 행의 1 % 인 < 일 때 색인 액세스 경로를 선택하게됩니다. 백엔드 옵티마이 저는 결과 행이 전체 행의 절반, 예를 들어 모든 행의 4 분의 1 일 때 인덱스를 선호하지 않습니다.

'2000-08-01'에서 '2000-08-03'의 범위는 색인을 악용 할 가능성이 큽니다.

cf : mysql not using index?

+0

답장을 보내 주셔서 감사합니다. 그러나 아래의 쿼리조차도 전체 테이블 스캔을 수행합니다. EXPLAIN SELECT * FROM LEDGER_AGR WHERE TransactionDate> = '2017-08-01' AND TransactionDate <= '2017-09-01'이 출력은 총, 따라서 TRANSACTION_DATE 인덱스를 사용하여 해당 계획을 설명하고 있지만, 불행히도 그것은 여전히 ​​전체 테이블을 스캔하고있다. – Mukta

+0

"작은"분율을 정의하십시오. 즉, 8 월 ~ 32 일에 이진 검색을 수행하고 며칠에 걸쳐 얼마나 많은 행이 테이블 스캔에서 전환되는지 알려줍니다. 또한 커버 링 인덱스 (https://en.wikipedia.org/wiki/Database_index#Covering_index)를 통해 더 좁은 조각을 요청하는 것을 고려해보십시오. 예 : 그 순서대로 (TransactionDate, DebitAmt)에 새 색인을 작성하고 "select *"대신 "select TransactionDate, DebitAmt ..."를 요청하십시오. –