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é zeitpunktqui 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 EXPLAINde la requête me dit que les sous-requêtes recherchent toujours les deux tables.
EXPLAINingles sous-requêtes elles-mêmes me montrent l'optimisation souhaitée mais UNIONingelles ne le font pas ensemble.
Ai-je oublié quelque chose?
Je sais que les ORDER BYclauses à l'intérieur des UNIONsous-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_idcondition.
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.
sourcecolonne? De cette façon, vous pouvez éviter les UNIONs et utiliser des index dans toutes vos données.
UNION ALLdonne 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=730apparition des lignes avec .