das fühlt sich an wie eine "mach meine Hausaufgaben für mich" Art von Frage, aber ich bin wirklich fest hier, versuchen diese Abfrage schnell gegen einen Tisch mit vielen vielen Zeilen zu laufen. Hier ist eine SQLFiddle , die das Schema (mehr oder weniger) zeigt.
Ich habe mit den Indizes gespielt und versucht, etwas zu bekommen, das alle erforderlichen Spalten zeigt, aber nicht viel Erfolg hatte. Hier ist das create
:
Und (eine Version von) select
:
Ich habe am Ende auch "Temporary verwenden" und "Filesort verwenden". Ich habe versucht, die count(*)
und stattdessen select distinct
zu löschen, was nicht den 'Using filesort' verursacht. Dies wäre wahrscheinlich in Ordnung, wenn es einen Weg zu join
zurück gäbe, um die Anzahl zu erhalten.
Ursprünglich wurde die Entscheidung getroffen, den target1Name und target2Name der Ziele so zu verfolgen, wie sie bei der Erstellung des Prüfprotokolls vorlagen. Ich brauche auch diese Namen (die neuesten werden es tun).
Momentan wird die Abfrage (oben, mit den fehlenden Spalten target1Name und target2Name) in etwa 5 Sekunden bei ~ 24 Millionen Datensätzen ausgeführt. Unser Ziel liegt bei Hunderten von Millionen und wir möchten, dass die Abfrage weiterhin in diese Richtung geht (in der Hoffnung, es unter 1-2 Minuten zu halten, aber wir hätten es gerne viel besser), aber meine Angst ist einmal Wir haben diese größere Menge an Daten erreicht, die es nicht tun wird (es wird daran gearbeitet, zusätzliche Zeilen zu simulieren).
Ich bin mir nicht sicher über die beste Strategie, um die zusätzlichen Felder zu bekommen. Wenn ich die Spalten direkt zu select
hinzufüge, verliere ich den 'Using Index' der Abfrage. Ich habe versucht, ein join
zurück auf die Tabelle, die den 'Using Index' aber dauert etwa 20 Sekunden.
Ich habe versucht, die eventTime-Spalte in einen int-Wert anstatt in einen datetime-Wert zu ändern, aber das schien die Verwendung des Indexes oder die Zeit nicht zu beeinflussen.
Wie Sie wahrscheinlich verstehen, besteht das Problem hier in der Bereichsbedingung ae.eventTime between '2011-09-01 03:00:00' and '2012-09-30 23:57:00'
, die (wie immer) die effiziente Verwendung von Transactions
index unterbricht (dh der Index wird nur für clientId
equation und den ersten Teil von Die Bereichsbedingung und der Index werden nicht zum Gruppieren verwendet.
In den meisten Fällen besteht die Lösung darin, die Bereichsbedingung durch eine Gleichheitsprüfung zu ersetzen (in Ihrem Fall fügen Sie eine Spalte period
, Gruppe eventTime
in Perioden ein und ersetzen die Klausel BETWEEN
durch period IN (1,2,3,4,5)
). Aber das könnte zu einem Overhead für Ihren Tisch werden.
Eine andere Lösung, die Sie vielleicht versuchen, ist, einen weiteren Index hinzuzufügen (wahrscheinlich ersetzen Transactions
, wenn es nicht mehr verwendet wird): (clientId, target1Id, type, eventTime)
, und verwenden Sie die folgende Abfrage:
Auf diese Weise werden Sie a) die Bereichsbedingung an das Ende verschieben, b) erlauben, den Index für die Gruppierung zu verwenden, c) den Index zu dem deckenden Index für die Abfrage machen (das ist die Abfrage benötigt keine Festplatten-IO-Operationen)
UPD1:
Es tut mir leid, yesterday Ich habe Ihren Beitrag nicht sorgfältig gelesen und nicht bemerkt, dass Ihr Problem darin besteht, target1Name
und target2Name
abzurufen. Vor allem bin ich mir nicht sicher, ob Sie die Bedeutung von Using index
richtig verstanden haben. Das Fehlen von Using index
bedeutet nicht, dass kein Index für die Abfrage verwendet wird, Using index
bedeutet, dass der Index selbst genügend Daten enthält, um eine Unterabfrage auszuführen (dh der Index deckt ab). Da target1Name
und target2Name
in keinem Index enthalten sind, enthält die Unterabfrage, die sie abruft, nicht Using index
.
Wenn Sie fragen, wie Sie diese zwei Felder zu Ihrer Abfrage hinzufügen (was Sie für schnell genug halten), dann versuchen Sie Folgendes:
%Vor%Tags und Links mysql query-optimization