大量の行を選択する必要がある大きなテーブルがあります。MySQLの複合インデックスが使用されていません
テーブルにはコール詳細レコード(CDR)が格納されます。例:
+-------------+--------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------------------+----------------+
| id | int(45) | NO | PRI | NULL | auto_increment |
| calldate | datetime | NO | MUL | 0000-00-00 00:00:00 | |
| accountcode | varchar(100) | NO | | | |
| other... | varchar(45) | NO | | | |
私のクエリは、特定の日付の顧客の呼び出しを探しているので、私はそうのようなクラスタ化インデックスで一緒にcalldateとaccountcodeをインデックス化:
CREATE TABLE `cdr` (
`id` int(45) NOT NULL AUTO_INCREMENT,
`calldate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`accountcode` varchar(100) NOT NULL DEFAULT '',
other fields...
PRIMARY KEY (`id`),
KEY `date_acc` (`calldate`,`accountcode`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=latin1
ただし、次のクエリを実行する場合、結果はキーのみ日時部分が使用されていることを示して説明します
クエリ:
最初の8バイト(キーの日付部分)が使用されていると思わ+----+-------------+-------+-------+---------------+----------+---------+------+---------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+-------+---------------+----------+---------+------+---------+----------+-------------+
| 1 | SIMPLE | cdr | range | date_acc | date_acc | 8 | NULL | 3312740 | 100.00 | Using where |
+----+-------------+-------+-------+---------------+----------+---------+------+---------+----------+-------------+
:
結果を説明しています。しかし、WHERE節はANDの両方の部分を明示的に参照するため、理論的には完全キーを使用する必要があります。
calldateとaccountcodeのインデックスを別々に作成し、クエリオプティマイザでそれらをマージさせる必要がありますか?なぜフルインデックスが使用されていないのですか?
ありがとうございました!
そのクエリですべての行の100%がフィルタされているようです。それはフィルタリングされた列の値は何ですか?そのフィルタリングをしていないサンプルを提供できますか?私は以下の答えの1つに同意する、あなたは最初にフィルタを持っている必要がありますし、並べ替え。インデックスaccountcode、calldateはるかに良い結果が得られるはずです。 – TheJacobTaylor