Ich habe gerade ein Protokollierungssystem eingerichtet, das aus mehreren Tabellen mit demselben Layout besteht.
Für jede Datenquelle gibt es eine Tabelle.
Für den Log Viewer möchte ich
- UNION alle Protokolltabellen ,
- filtern Sie sie nach Konto ,
- Fügen Sie eine Pseudospalte zur Identifizierung der Quelle hinzu.
- sortiere sie nach Zeit ,
- und begrenzen sie für die Paginierung .
Alle Tabellen enthalten ein Feld mit dem Namen zeitpunkt
indizierte Datums- / Uhrzeitspalte.
Mein erster Versuch war:
(SELECT l.id, l.account_id, l.vnum, l.count, l.preis, l.zeitpunkt AS zeit,
'hp' AS source FROM is_log AS l WHERE l.account_id = 730)
UNION
(SELECT l.id, l.account_id, l.vnum, l.count, l.preis, l.zeitpunkt,
'ig' AS source FROM ig_is_log AS l WHERE l.account_id = 730)
ORDER BY zeit DESC LIMIT 10;
Der Optimierer kann die Indizes hier nicht verwenden, da alle Zeilen aus beiden Tabellen von den Unterabfragen zurückgegeben und nach dem sortiert werden UNION
.
Meine Problemumgehung war folgende:
(SELECT l.id, l.account_id, l.vnum, l.count, l.preis, l.zeitpunkt AS zeit,
'hp' AS source FROM is_log AS l WHERE l.account_id = 730
ORDER BY l.zeitpunkt DESC LIMIT 10)
UNION
(SELECT l.id, l.account_id, l.vnum, l.count, l.preis, l.zeitpunkt,
'ig' AS source FROM ig_is_log AS l WHERE l.account_id = 730
ORDER BY l.zeitpunkt DESC LIMIT 10)
ORDER BY zeit DESC LIMIT 10;
Ich hatte erwartet, dass die Abfrage-Engine die Indizes hier verwenden würde, da beide Unterabfragen bereits vor dem sortiert und begrenzt werden sollten UNION
, wodurch die Zeilen zusammengeführt und sortiert werden.
Ich dachte wirklich, das wäre es, aber EXPLAIN
wenn ich die Abfrage ausführe, werden die Unterabfragen immer noch in beiden Tabellen durchsucht.
EXPLAINing
Die Unterabfragen selbst zeigen mir die gewünschte Optimierung, aber UNIONing
zusammen nicht.
Habe ich etwas verpasst?
Ich weiß, dass ORDER BY
Klauseln in UNION
Unterabfragen ohne a ignoriert werden LIMIT
, aber es gibt eine Grenze.
Bearbeiten:
Eigentlich wird es wahrscheinlich auch Abfragen ohne dieaccount_id
Bedingung geben.
Die Tabellen existieren bereits und sind mit Daten gefüllt. Abhängig von der Quelle kann es zu Änderungen im Layout kommen, daher möchte ich sie geteilt halten. Darüber hinaus verwenden die Protokollierungsclients aus einem bestimmten Grund unterschiedliche Anmeldeinformationen.
Ich muss eine Art Schicht zwischen den Protokolllesern und den tatsächlichen Tabellen halten.
Hier sind die Ausführungspläne für die gesamte Abfrage und die erste Unterabfrage sowie das Tabellenlayout im Detail:
UNION DISTINCT
? Es ist nicht erforderlich, dort eine Sortierung und Unterscheidung zu erzwingen, da die Ergebnisse aufgrund der zusätzlichen Identifikationsspalte je nach Unterabfrage unterschiedlich sind. Verwenden Sie UNION ALL
.
source
Spalte in derselben Tabelle zu haben ? Auf diese Weise können Sie UNION
s vermeiden und Indizes für alle Ihre Daten verwenden.
UNION ALL
anderen Ausführungsplan führt.
(account_id, zeitpunkt)
. Haben Sie einen solchen Index? Das zweitbeste wäre (glaube ich) die Single(zeitpunkt)
- aber die Effizienz, wenn dies verwendet wird, hängt davon ab, wie oft Zeilen mitaccount_id=730
erscheinen.