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

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top