Ich habe eine große Tabelle, aus der ich große Mengen von Zeilen auswählen muss.MySQL Compound-Index wird nicht verwendet
Die Tabelle speichert Anrufdetailsätze (CDRs). Beispiel:
+-------------+--------------+------+-----+---------------------+----------------+
| 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 | | | |
Da meine Anfragen für einen Kunden Anrufe in bestimmten Terminen suchen, ich indiziert calldate und account zusammen in einem Clustered-Index wie folgt:
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
Wenn jedoch die folgende Abfrage ausgeführt wird, die EXPLAIN Ergebnis zeigt, daß nur die Datumzeit Teil des Schlüssels verwendet wird:
Abfrage:
SELECT *
FROM cdr
WHERE calldate > '2010-12-01'
AND accountcode = 'xxxxxx';
EXPLAIN Ergebnis:
+----+-------------+-------+-------+---------------+----------+---------+------+---------+----------+-------------+
| 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 |
+----+-------------+-------+-------+---------------+----------+---------+------+---------+----------+-------------+
Es scheint nur die ersten 8 Bytes (das Datum Teil des Schlüssels) verwendet wird. Die WHERE-Klausel verweist jedoch explizit auf beide Teile des Schlüssels mit einem AND, sodass theoretisch der vollständige Schlüssel verwendet werden sollte.
Sollte ich separate Indizes für Calldate und Accountcode erstellen und sie vom Abfrageoptimierer zusammenführen lassen? Warum wird der vollständige Index nicht verwendet?
Danke für die Hilfe!
Es scheint, als ob es 100% aller Zeilen mit dieser Abfrage gefiltert hat. Ist das nicht der Wert der gefilterten Spalte? Können Sie ein Beispiel angeben, das diese Filterung nicht bietet? Ich stimme einer der Antworten unten zu, Sie sollten zuerst den Filter und dann die Sortierung haben. Index Kontocode, Anruf. Sie sollten ein viel besseres Ergebnis erhalten. – TheJacobTaylor