2015-06-04 16 views
7

sto cercando di interpretare il explain di mysql in una query (scritto in due modi diversi), questo è il tavolo:Capire spiegare in una query mysql

create table text_mess(
    datamess timestamp(3) DEFAULT 0, 
    sender bigint , 
    recipient bigint , 
    roger boolean, 
    msg char(255), 
    foreign key(recipient) 
      references users (tel) 
         on delete cascade 
         on update cascade, 
primary key(datamess,sender) 
) 
engine = InnoDB 

Questo è il primo tipo di query:

EXPLAIN 
    select /*!STRAIGHT_JOIN*/datamess, sender,recipient,roger,msg 
    from text_mess join (select max(datamess)as dmess 
        from text_mess 
        where roger = true 
        group by sender,recipient) as max 
        on text_mess.datamess=max.dmess ; 

e questo è il secondo:

EXPLAIN 
    select /*!STRAIGHT_JOIN*/datamess, sender,recipient,roger,msg 
    from (select max(datamess)as dmess 
        from text_mess 
        where roger = true 
        group by sender,recipient) as max 
     join 
    text_mess 
    on max.dmess = text_mess.datamess ; 

le due query si chiedono la stessa cosa, l'unica la differenza è l'ordine di ref_table (driving_table), nel primo caso è text_mess, nel secondo caso è una query secondaria. primo risultato:

id select_type  table  type possible_keys key  key_len  ref       rows  Extra 
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
    1 PRIMARY  text_mess  ALL  PRIMARY   null  null null       294225  null 
    1 PRIMARY  derived2  ref  auto_key0  auto_key0 7  inextremis.text_mess.datamess 10   Using index 
    2 DERIVED  text_mess  ALL  recipient  null  null null       294225  Using where; Using temporary; Using filesort 

secondo risultato:

id select_type  table  type possible_keys key   key_len ref  rows Extra 
    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 
    1 PRIMARY  <derived2>  ALL  null   null   null  null  294225 Using where 
    1 PRIMARY  text_mess  ref  PRIMARY   PRIMARY   6  max.dmess 1 null 
    2 DERIVED  text_mess  ALL  recipient  null   null  null  294225 Using where; Using temporary; Using filesort 

Come si può vedere la differenza è nell'ordine delle prime due linee, la mia domanda, in particolare, si trova al secondo (la query più veloce) la seconda riga dovrebbe essere la tabella interna, ma in tal caso, perché la colonna ref mi dice: max.dmess, che dovrebbe essere la colonna della tabella di riferimento (sottoquery).

L'ultima riga si riferisce a come viene costruito il primo? Alla fine, pensi che ci sia una query più efficiente?

+0

Su 'INNER JOIN's si consiglia di mettere la tabella con meno righe a sinistra (vale a dire la prima tabella). Il pianificatore di query MySQL è in grado di scambiare le tabelle per te se inserisci prima la tabella più grande (produce lo stesso risultato su 'EXPLAIN', indipendentemente dalla tabella che hai inserito per primo). In questo caso non può eseguire questa magia perché nelle tue query una delle tabelle 'JOIN'ed non è una tabella ma una sottoquery e questo impedisce di sapere quale tabella è più piccola. – axiac

+0

La mia domanda è stata il risultato di spiegare: in particolare le righe con id 1, ed è la seguente: è giusto interpretare la prima riga del risultato di spiegare come "elaborazione" della tabella a sinistra del join e la seconda riga come "elaborazione" della tabella che si trova a destra del join, infine l'ultima riga è "elaborazione" della tabella . e interpretare giustamente (nella seconda query spiegare) il parametro max.dmess della colonna ref della seconda riga, come colonna da cui ogni riga viene confrontata con le righe della tabella text_mess (trovata tramite chiave: PRIMARY) – emacos

+0

Per prestazioni migliori , crea l'indice 'roger asc, sender asc, recipient asc, datamess desc' (o tutto desc). – Toni

risposta

0

Penso che la risposta sia la scansione della tabella rispetto alla chiave primaria. Se si vede, per la prima query, MySQL non fa uso di alcun tasto ma pronto ogni riga della tabella "text_mess":

id select_type  table  type possible_keys key  key_len  ref       rows  Extra 
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

    1 PRIMARY  text_mess  ALL  PRIMARY   null  null null       294225  null 

Ma si utilizza un "ON" dichiarazione sul tavolo "derived2" e MySQL creare una chiave di auto:

id select_type  table  type possible_keys key  key_len  ref       rows  Extra 
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
    1 PRIMARY  derived2  ref  auto_key0  auto_key0 7  inextremis.text_mess.datamess 10   Using index 

Questa chiave non è presente, in modo da MySQL dovrebbe crearlo.

Se si prende il secondo esempio, la scansione completa della tabella avviene sul tavolo "derived2", e la vostra chiave primaria della "text_mess" è in uso:

id select_type  table  type possible_keys key   key_len ref  rows Extra 
    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 
    1 PRIMARY  <derived2>  ALL  null   null   null  null  294225 Using where 
    1 PRIMARY  text_mess  ref  PRIMARY   PRIMARY   6  max.dmess 1 null 

La risposta è, che in tale una situazione MySQL ha deciso di creare e utilizzare un indice, ma generalmente esegue una scansione completa della tabella ed è semplicemente più veloce.

Immaginate che la chiave auto_key0 includa di nuovo l'unica colonna di questa subquery. Questo processo extra non è necessario. Questo è il motivo per cui la seconda query è più veloce.