Ich habe Artikel über FORCE
Index gelesen , aber wie kann ich MySQL zu IGNORE ALL
Indizes zwingen ?
Ich habe es versucht SELECT * FROM tbl IGNORE INDEX(*)
, aber ich war nicht erfolgreich.
Warum ich (und andere) dies tun müssen: Zum Beispiel musste ich die Referenzstatistiken wie folgt zusammenfassen:
SELECT
count(*) as c,
SUBSTRING
(
domain_name,
LENGTH(domain_name) - LOCATE('.', REVERSE(domain_name)) + 2
) as tld
FROM `domains_import`
IGNORE INDEX(domain_name)
GROUP BY tld
ORDER BY c desc
LIMIT 100
... aber ich muss immer schauen, welche Indizes definiert sind oder bestimmen, welcher Index über Explain verwendet wird. Es wäre sehr praktisch, einfach zu schreiben IGNORE INDEX ALL
und sich einfach nicht darum zu kümmern.
Kennt jemand die Syntax oder einen Hack? (Dutzende Zeilen über MySQL-Definitionstabellen sind wirklich keine Abkürzung).
Aus der Chat-Diskussion hinzugefügt :
Bechmark:
kein Index = 148,5 Sekunden
mit Index = 180 Sekunden und immer noch mit Daten senden Das SSD-Array ist so leistungsfähig, dass Sie sich fast nicht um den Datencache kümmern ...
Definition für Benchmark:
CREATE TABLE IF NOT EXISTS `domains_import` (
`domain_id` bigint(20) unsigned NOT NULL,
`domain_name` varchar(253) CHARACTER SET ascii COLLATE ascii_bin NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `domains_import`
ADD PRIMARY KEY (`domain_id`),
ADD UNIQUE KEY `domain_name` (`domain_name`);
ALTER TABLE `domains_import`
MODIFY `domain_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT;
InnoDB, der Test mit Index (kein USE INDEX () oder ähnliches) läuft noch, 250 Sekunden, ich habe ihn gerade beendet.
LEFT JOIN
mir vorhandenen entfernt wurden. `USE INDEX ()` hat MySQL veranlasst, einen Tabellenscan für eine 20K-Zeilentabelle und 1-zu-1-JOIN
s durchzuführen, anstatt 500 Zeilen zwischen zwei Indizes zu kreuzen. 20x schneller geworden.Sie können auch einbetten
WHERE 1=1
ypercube hat mich gerade gefragt
Ja, aber Sie haben MySQL eine wirklich dumme Frage gestellt.
1=1
würde zum Clustered Index zurückkehren. Trotzdem gibt es noch einen anderen Weg, aber es erfordert, dass der Optimierer ein wenig bösartig ist.Dies wird sicher jeden Index unter den Bus werfen, da der Wert jeder Zeile für
domain_name
vieles überprüft werden muss. Wenndomain_name
indiziert ist, müssen Sie eine Spalte für die auswählenWHERE column_name=column_name
, die überhaupt nicht indiziert ist.Ich habe es gerade an einem großen Tisch in einem Staging-Server versucht
Es werden keine Indizes ausgewählt
quelle
WHERE id+0 = id*1
der Index weiterhin verwendet und ein zusätzlichesUsing where
wird angezeigt.Angenommen, Sie haben diese beiden Indizes:
Dann spielt es keine Rolle, was der Optimierer tut; Es muss im Wesentlichen eine identische Menge an Material scannen.
Fall 1: Es führt einen Tabellenscan durch (oder verwendet domain_id): Es scannt (ID, Name) Paare, sucht alle Namen, führt den SUBSTRING..LOCATE, GROUP BY und schließlich ORDER BY aus. Das GROUP BY und das ORDER BY benötigen wahrscheinlich jeweils eine tmp-Tabelle und einen Dateisort. Überprüfen Sie
EXPLAIN SELECT ...
, ob dies der Fall ist.Fall 2: Es wird ein Index-Scan (von Domänenname) durchgeführt: Dieser Index enthält tatsächlich (Name, ID) Paare - da InnoDB die PK implizit an das Ende eines Sekundärschlüssels setzt. Der Rest der Verarbeitung entspricht Fall 1.
Eines könnte anders sein - die Größe der beiden BTrees. Hat
SHOW TABLE STATUS LIKE domains_import
die Data_length (für Fall 1) und Index_length (für Fall 2) zu sehen. Der größere BTree wird langsamer sein.Eine andere Sache könnte anders sein - Caching. Was ist der Wert von
innodb_buffer_pool_size
? Wie viel RAM hast du? Können die Daten (oder der Index) im Pufferpool enthalten sein? (Oder sind es 37% davon, da es sich um einen Tabellen- / Index-Scan handelt?) Wenn dies passt, führen Sie die Abfrage zweimal aus. Das zweite Mal ist ungefähr zehnmal so schnell, da die Festplatte nicht getroffen wird (Caching).Wenn dies eine einmalige Aufgabe ist, hilft SSD. Wenn nicht, und Sie können die gesamte Tabelle zwischenspeichern, hilft dies nicht, nachdem der buffer_pool geladen wurde.
quelle