Sélectionnez uniquement les enregistrements les plus récents de la table et de faire ce FAST, comment?
-
19-09-2019 - |
Question
Bonjour, j'ai une question que je me bats avec beaucoup, espère que quelqu'un a déjà trouvé une solution intelligente à ce (j'utilise MySQL).
Je table comme ceci:
Table `log`
----------
id
inserted
message
user_id
Mon but est de sélectionner le dernier enregistrement inséré pour l'utilisateur et faire vite. Table Log est énorme (environ 900k records), Ma première approche était:
SELECT * FROM `log`
LEFT JOIN `users` ON `users`.`id` = `log`.`user_id`
WHERE `id` IN
(
SELECT MAX(`id`) FROM `log` GROUP BY `user_id`
)
Mais il semble que ce calcul sous-requête pour chaque ligne (EXPLAIN QUERY DEPENDANT). Lorsque je partage cette requête pour deux:
SELECT MAX(`id`) FROM `log` GROUP BY `user_id`
et
SELECT * FROM `log`
LEFT JOIN `users` ON `users`.`id` = `log`.`user_id`
WHERE `id` IN (....ids from first query...)
Il est acceptable de fonctionner. Cela peut-il être achived par une requête?
La solution
En plus d'utiliser le groupe pour aller chercher par le maximum de groupe sage, vous voulez probablement faire une sous-requête décorrélée chercher des champs supplémentaires pour les lignes spécifiques de la table.
SELECT
la.user_id,la.message
FROM
`log` as la
INNER JOIN
(
SELECT
user_id, MAX(id) AS maxid
FROM
`log`
GROUP BY
user_id
) as lb
ON
la.id = lb.maxid
Cela fonctionne mieux / plus rapide si vous avez un indice
KEY `foo` (`user_id`,`id`)
mais même sans cette touche la performance est la descente.
Autres conseils
Qu'en est-
SELECT user_id, max(id) FROM `log` GROUP BY user_id
vous obtiendrez l'id maximum pour chaque utilisateur dans la table de journal, en une seule requête!
Si vous êtes à la recherche toujours pour le journal pour un utilisateur particulier, le partitionnement du fichier journal par user_id accélérerait les choses beaucoup. Si la table est partagée par l'utilisateur et indexé par identifiant, la requête sera exécutée très rapidement.
EDIT: voir la requête de Dominik
En outre, je voudrais vous assurer que vous avez un index sur user_id.
EDIT: généralisée