Je viens de mettre en place un système d'enregistrement qui se compose de plusieurs tables avec la même disposition.
Il existe une table pour chaque source de données.
Pour la visionneuse de journaux, je veux
- UNION toutes les tables de log ,
- les filtrer par compte ,
- ajouter une pseudo colonne pour l'identification de la source,
- les trier par temps ,
- et les limiter pour la pagination .
Toutes les tables contiennent un champ appelé zeitpunkt
qui est une colonne date / heure indexée.
Ma première tentative a été:
(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'optimiseur ne peut pas utiliser les index ici car toutes les lignes des deux tables sont renvoyées par les sous-requêtes et triées après le UNION
.
Ma solution de contournement était la suivante:
(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;
Je m'attendais à ce que le moteur de requête utilise les index ici car les deux sous-requêtes devraient être triées et limitées déjà avant le UNION
, qui fusionne et trie ensuite les lignes.
Je pensais vraiment que ce serait le cas, mais l'exécution EXPLAIN
de la requête me dit que les sous-requêtes recherchent toujours les deux tables.
EXPLAINing
les sous-requêtes elles-mêmes me montrent l'optimisation souhaitée mais UNIONing
elles ne le font pas ensemble.
Ai-je oublié quelque chose?
Je sais que les ORDER BY
clauses à l'intérieur des UNION
sous-requêtes sont ignorées sans a LIMIT
, mais il y a une limite.
Edit:
En fait, il y aura probablement aussi des requêtes sansaccount_id
condition.
Les tableaux existent déjà et sont remplis de données. Il peut y avoir des changements dans la mise en page selon la source, donc je veux les garder divisés. En outre, les clients de journalisation utilisent des informations d'identification différentes pour une raison.
Je dois garder une sorte de couche entre les lecteurs de journaux et les tables réelles.
Voici les plans d'exécution de la requête entière et de la première sous-requête ainsi que la disposition du tableau en détail:
UNION DISTINCT
? Il n'est pas nécessaire de forcer un tri et de les distinguer, car les résultats seront différents d'une sous-requête à l'autre en raison de la colonne d'identification supplémentaire. Utilisez UNION ALL
.
source
colonne? De cette façon, vous pouvez éviter les UNION
s et utiliser des index dans toutes vos données.
UNION ALL
donne un plan d'exécution différent.
(account_id, zeitpunkt)
. Avez-vous un tel indice? Le deuxième meilleur serait (je pense) le single(zeitpunkt)
- mais l'efficacité si elle est utilisée dépend de la fréquence d'account_id=730
apparition des lignes avec .