Ho appena impostato un sistema di registrazione composto da più tabelle con lo stesso layout.
C'è una tabella per ogni origine dati.
Per il visualizzatore di log, voglio farlo
- UNIONE tutte le tabelle di registro ,
- filtrali per account ,
- aggiungere una pseudo colonna per l'identificazione della fonte,
- ordinali per tempo ,
- e limitarli per l'impaginazione .
Tutte le tabelle contengono un campo chiamato zeitpunkt
che è una colonna data / ora indicizzata.
Il mio primo tentativo è stato:
(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;
L'ottimizzatore non può utilizzare gli indici qui perché tutte le righe di entrambe le tabelle vengono restituite dalle sottoquery e ordinate dopo il UNION
.
La mia soluzione alternativa era la seguente:
(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;
Mi aspettavo che il motore di query avrebbe usato gli indici qui poiché entrambe le sottoquery dovrebbero essere ordinate e limitate già prima di UNION
, che quindi unisce e ordina le righe.
Pensavo davvero che sarebbe successo, ma l'esecuzione EXPLAIN
sulla query mi dice che le sottoquery continuano a cercare entrambe le tabelle.
EXPLAINing
le subquery stesse mi mostrano l'ottimizzazione desiderata ma UNIONing
loro insieme no.
Ho dimenticato qualcosa?
So che le ORDER BY
clausole all'interno delle UNION
sottoquery vengono ignorate senza un LIMIT
, ma esiste un limite.
Modifica: in
realtà, probabilmente ci saranno anche query senza laaccount_id
condizione.
Le tabelle esistono già e sono piene di dati. Potrebbero esserci cambiamenti nel layout a seconda della fonte, quindi voglio tenerli divisi. Inoltre, i client di registrazione utilizzano credenziali diverse per un motivo.
Devo mantenere una sorta di livello tra i lettori di log e le tabelle effettive.
Ecco i piani di esecuzione per l'intera query e la prima sottoquery, nonché il layout della tabella in dettaglio:
UNION DISTINCT
? Non è necessario forzare una sorta e distinguere lì, poiché i risultati saranno diversi tra le sottoquery, a causa della colonna di identificazione aggiuntiva. Usa UNION ALL
.
source
colonna? In questo modo potresti evitare di UNION
usare gli indici su tutti i tuoi dati.
UNION ALL
piano di esecuzione diverso.
(account_id, zeitpunkt)
. Hai un tale indice? Il secondo migliore sarebbe (penso) il singolo(zeitpunkt)
- ma l'efficienza se utilizzata dipende dalla frequenza con cuiaccount_id=730
appaiono le righe .