Seleziona solo i record più recenti dalla tabella e rendilo VELOCE, come?
-
19-09-2019 - |
Domanda
Buongiorno, ho una domanda con cui sto lottando molto, spero che qualcuno abbia già trovato una soluzione intelligente a questo (uso MySQL).
Ho una tabella come questa:
Table `log`
----------
id
inserted
message
user_id
Il mio obiettivo è selezionare l'ultimo record inserito per l'utente e renderlo veloce.La tabella dei registri è enorme (circa 900k record), quindi il mio primo approccio è stato:
SELECT * FROM `log`
LEFT JOIN `users` ON `users`.`id` = `log`.`user_id`
WHERE `id` IN
(
SELECT MAX(`id`) FROM `log` GROUP BY `user_id`
)
Ma sembra che calcoli la sottoquery per ogni riga (EXPLAIN mostra DEPENDENT QUERY).Quando divido questa query per due:
SELECT MAX(`id`) FROM `log` GROUP BY `user_id`
E
SELECT * FROM `log`
LEFT JOIN `users` ON `users`.`id` = `log`.`user_id`
WHERE `id` IN (....ids from first query...)
È accettabile correre.È possibile ottenere questo risultato con una query?
Soluzione
Oltre a utilizzare gruppo per andare a prendere il massimo gruppo-saggio probabilmente si desidera per renderlo un sottoquery non correlato a prendere i campi aggiuntivi per le righe specifiche della tabella.
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
Questo funziona meglio / più veloce se si dispone di un indice
KEY `foo` (`user_id`,`id`)
, ma anche senza quella chiave la prestazione è discesa.
Altri suggerimenti
Come su
SELECT user_id, max(id) FROM `log` GROUP BY user_id
In questo modo ottenere il massimo id per ogni utente nella tabella del registro, il tutto in una query!
Se avete sempre alla ricerca per il registro per un particolare utente, partizionare il file di log da user_id sarebbe accelerare le cose un sacco. Se la tabella è partizionata per utente e indicizzato da id, la query verrà eseguita molto velocemente.
EDIT: vedi interrogazione di Dominik
Inoltre, mi assicurerei che tu abbia un indice su user_id.
MODIFICARE:generalizzato