2012-11-29 9 views
28

Sto lavorando a un sistema di tracciamento eventi che utilizza una manciata di tabelle di ricerca e la tabella di registrazione principale. In una relazione che sto scrivendo, è possibile selezionare un oggetto per visualizzare le statistiche. L'interfaccia mostra tutti gli oggetti in ordine di importanza decrescente (es. Colpi).Uso dell'indice, usando temporaneamente, usando filesort - come risolvere questo problema?

Lo schema per le due tabelle (scarsamente tagliati giù, ma si ottiene il succo):

CREATE TABLE IF NOT EXISTS `event_log` (
    `event_id` int(11) NOT NULL AUTO_INCREMENT, 
    `user_id` int(5) DEFAULT NULL, 
    `object_id` int(5) DEFAULT NULL, 
    `event_date` datetime DEFAULT NULL, 
    PRIMARY KEY (`event_id`), 
    KEY `user_id` (`user_id`), 
    KEY `object_id` (`object_id`) 
); 

CREATE TABLE IF NOT EXISTS `lookup_event_objects` (
    `object_id` int(11) NOT NULL AUTO_INCREMENT, 
    `object_desc` varchar(255) NOT NULL, 
    PRIMARY KEY (`object_id`) 
); 

La query Ho problemi con è al di sotto. Funziona perfettamente con la mia tabella di ~ 100 voci, ma la SPIEGAZIONE mi preoccupa un po '.

explain SELECT 
      el.object_id, 
      leo.object_desc, 
      COUNT(el.object_id) as count_rows 
     FROM 
      event_log el 
      LEFT JOIN lookup_event_objects leo ON leo.object_id = el.object_id 
     GROUP BY 
      el.object_id 
     ORDER BY 
      count_rows DESC, 
      leo.object_desc ASC 

Returns: Using index; Using temporary; Using filesort

Quindi - cosa c'è di sbagliato con il mio schema e/o query per MySQL a ripiegare su temporary e filesort? O è ottimizzato in quanto può utilizzare ORDER BY?

risposta

63

Beh, the doc dà le ragioni esatte quando "Utilizzo temporaneo" apparirà:

tabelle temporanee possono essere creati in condizioni come queste:

Se c'è una clausola ORDER BY e un diverso Clausola GROUP BY, oppure se l'ORDER BY o GROUP BY contiene colonne da tabelle diverse dalla prima tabella nella coda di join, viene creata una tabella temporanea.

DISTINCT combinato con ORDER BY può richiedere una tabella temporanea.

Se si utilizza l'opzione SQL_SMALL_RESULT, MySQL utilizza un tabella temporanea in memoria, a meno che la query contiene anche elementi (descritti tardi) che richiedono memorizzazione su disco.

Una scansione rapida indica che si soffre di # 1.

E this blog dal 2009 dice che "using filesort" significa che l'ordinamento non può essere eseguito con un indice. Dato che stai ordinando da un campo calcolato, anche quello sarà vero.

Quindi, questo è "sbagliato".

+0

Il numero massimo di oggetti che avessi mai ritorno da questa query è <300, anche se devo avere potenzialmente milioni di righe nel event_log. Ho confermato che 'utilizzando temporaneamente' e' using filesort' scompaiono quando rimuovo ORDER BY. Cercherò di cambiare questo in modo che io faccia l'ordine (in un array) con il linguaggio di scripting (PHP). Grazie per la tua risposta e link. –

+1

Potrebbe essere ancora più efficiente eseguire l'ordinamento in MySQL: ha già i dati caricati in una struttura dati, ecc. –

+0

Sarebbe certamente più pulito. Grazie per il feedback. –

1

Queste sono le seguenti condizioni in cui vengono create le tabelle temporanee. Le query UNION utilizzano tabelle temporanee.

Alcune viste richiedono tabelle temporanee, quali quelle valutate utilizzando l'algoritmo TEMPTABLE o che utilizzano UNION o aggregazione.

Se è presente una clausola ORDER BY e una clausola GROUP BY diversa, oppure se ORDER BY o GROUP BY contiene colonne di tabelle diverse dalla prima tabella nella coda di join, viene creata una tabella temporanea.

DISTINCT combinato con ORDER BY può richiedere una tabella temporanea.

Se si utilizza l'opzione SQL_SMALL_RESULT, MySQL utilizza una tabella temporanea in memoria, a meno che la query contenga anche elementi (descritti in seguito) che richiedono l'archiviazione su disco.

Segui questo link per mysql: http://dev.mysql.com/doc/refman/5.1/en/internal-temporary-tables.html

1

aggiornamento per MySQL 5.7 (src):

Il server crea tabelle temporanee in condizioni come queste:

  • Valutazione delle Dichiarazioni UNION, con alcune eccezioni descritte in seguito.

  • Valutazione di alcune viste, come quelle che utilizzano l'algoritmo TEMPTABLE, UNION o aggregazione.

  • Valutazione delle tabelle derivate (sottoquery nella clausola FROM).

  • Tabelle create per la materializzazione di subquery o semi-join (vedere Sezione 8.2.2, "Ottimizzazione delle sottoquery, delle tabelle derivate e dei riferimenti di vista").

  • Valutazione di dichiarazioni che contengono una clausola ORDER BY e una clausola GROUP BY diversa o per le quali ORDER BY o GROUP BY contiene colonne di tabelle diverse dalla prima tabella nella coda di join.

  • La valutazione di DISTINCT combinata con ORDER BY può richiedere una tabella temporanea.

  • Per le query che utilizzano il modificatore SQL_SMALL_RESULT, MySQL utilizza una tabella temporanea in memoria, a meno che la query contenga anche elementi (descritti in seguito) che richiedono l'archiviazione su disco.

  • Per valutare istruzioni INSERT ... SELECT che selezionano e inseriscono nella stessa tabella, MySQL crea una tabella temporanea interna per contenere le righe da SELECT, quindi inserisce tali righe nella tabella di destinazione. Vedere la Sezione 13.2.5.1, "INSERT ... SELECT Syntax".

  • Valutazione di istruzioni UPDATE a più tabelle.

  • Valutazione di espressioni GROUP_CONCAT() o COUNT (DISTINCT).

Problemi correlati