ottimizzare la query SQL
-
22-08-2019 - |
Domanda
Che altro posso fare per ottimizzare questa ricerca?
SELECT * FROM
(SELECT `item`.itemID, COUNT(`votes`.itemID) AS `votes`,
`item`.title, `item`.itemTypeID, `item`.
submitDate, `item`.deleted, `item`.ItemCat,
`item`.counter, `item`.userID, `users`.name,
TIMESTAMPDIFF(minute,`submitDate`,NOW()) AS 'timeMin' ,
`myItems`.userID as userIDFav, `myItems`.deleted as myDeleted
FROM (votes `votes` RIGHT OUTER JOIN item `item`
ON (`votes`.itemID = `item`.itemID))
INNER JOIN
users `users`
ON (`users`.userID = `item`.userID)
LEFT OUTER JOIN
myItems `myItems`
ON (`myItems`.itemID = `item`.itemID)
WHERE (`item`.deleted = 0)
GROUP BY `item`.itemID,
`votes`.itemID,
`item`.title,
`item`.itemTypeID,
`item`.submitDate,
`item`.deleted,
`item`.ItemCat,
`item`.counter,
`item`.userID,
`users`.name,
`myItems`.deleted,
`myItems`.userID
ORDER BY `item`.itemID DESC) as myTable
where myTable.userIDFav = 3 or myTable.userIDFav is null
limit 0, 20
Sto usando MySQL
Grazie
Soluzione
Naturalmente, come @theomega detto, guarda il piano di esecuzione.
Ma mi piacerebbe anche suggerire per cercare di "ripulire" la sua dichiarazione. (Non so che uno è più veloce -. Che dipende dalle dimensioni delle tabelle) Di solito, mi piacerebbe provare a iniziare con una dichiarazione pulito e iniziare a ottimizzare da lì. Ma di solito, una dichiarazione pulito rende più facile per l'ottimizzatore a venire con un buon piano di esecuzione.
Quindi, ecco alcune osservazioni circa la sua dichiarazione che potrebbe fare le cose con calma:
- un paio di outer join (rende difficile per l'optimzer per capire un indice da utilizzare)
- un gruppo da
- un sacco di colonne per raggruppare da
Per quanto ho capito la tua SQL, questa affermazione dovrebbe fare la maggior parte di ciò che il vostro è facendo:
SELECT `item`.itemID, `item`.title, `item`.itemTypeID, `item`.
submitDate, `item`.deleted, `item`.ItemCat,
`item`.counter, `item`.userID, `users`.name,
TIMESTAMPDIFF(minute,`submitDate`,NOW()) AS 'timeMin'
FROM (item `item` INNER JOIN users `users`
ON (`users`.userID = `item`.userID)
WHERE
Naturalmente, questo non trova l'informazioni dalle tabelle si è unito esterno, io suggerirei di provare ad aggiungere le colonne necessarie tramite una selezione secondaria:
SELECT `item`.itemID,
(SELECT count (itemID)
FROM votes v
WHERE v.itemID = 'item'.itemID) as 'votes', <etc.>
In questo modo, si può sbarazzarsi di un outer join e il raggruppamento. L'outer join è sostituito dal subselect, per cui v'è un trade-off che può essere un male per la dichiarazione "pulito".
A seconda della cardinalità tra la voce e myItems, si può fare lo stesso o che avrebbe dovuto rimanere con l'outer join (ma non c'è bisogno di reintrodurre il gruppo da).
Spero che questo aiuti.
Altri suggerimenti
Che cosa significa l'analizzatore dire di questa ricerca? Senza conoscenza di quante righe ci sono nella tabella non puoi dire alcuna ottimizzazione. Quindi eseguire l'analizzatore e vedrete che cosa costa parti che cosa.
Alcuni rapidi pensieri semi-casuali:
sono indicizzati i tuoi Itemid e userID colonne?
Che cosa succede se si aggiunge "spiegare" l'inizio della query ed eseguirlo? La usa indici? Sono sensibile?
Avete bisogno di eseguire l'intera query interna e filtrare su di esso, oppure si potrebbe mettere muovere la parte where myTable.userIDFav = 3 or myTable.userIDFav is null
nella query interna?
Non sembrano avere troppi campi del Gruppo By lista, dal momento che uno di loro è itemID, ho il sospetto che si potrebbe usare un SELEZIONA interna per preforme il raggruppamento e una SELEZIONE esterna per restituire l'insieme di campi desiderato.
Non puoi aggiungere la clausola WHERE myTable.userIDFav = 3 o myTable.userIDFav è nullo a dove (item
.deleted = 0) ?
Saluti
Lieven
Guardate il modo in cui la query è costruito. Si entra in un sacco di roba, quindi limitare l'output a 20 righe. Si dovrebbe avere il join esterno su oggetti e myitems, dal momento che le vostre condizioni valgono solo per queste due tabelle, limitare l'output alle prime 20 righe, quindi unire e di aggregazione. Qui si sta eseguendo un sacco di lavoro che sta per essere scartato.