2017-10-24 17 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 ..."を要求してください –

関連する問題