2012-11-06 14 views
6

Sto riscontrando un problema grave con MySQL (innoDB) 5.0.Controllo intervallo Mysql anziché utilizzo indice su join interno

Una query SQL molto semplice viene eseguita con un piano di query molto inaspettato.

La query:

SELECT 
SQL_NO_CACHE 
mbCategory.* 

FROM 
MBCategory mbCategory 

INNER JOIN ResourcePermission as rp 
    ON rp.primKey = mbCategory.categoryId 

where mbCategory.groupId = 12345 AND mbCategory.parentCategoryId = 0 
limit 20; 

MBCategory - contiene 216583 filari

ResourcePermission - contiene 3098354 righe.

In MBCategory ho più indici (colonne ordinano come nell'indice):

Primary (categoryId) 
A (groupId,parentCategoryId,categoryId) 
B (groupId,parentCategoryId) 

In ResourcePermission ho più indici (colonne ordine come nell'indice):

Primary - on some column 
A (primKey). 

Quando ho esamina il piano di query Mysql modifica la sequenza delle tabelle e seleziona le righe da ResourcePermission all'inizio e poi si unisce alla tabella MBCategory (idea pazza) e richiede anni. Così ho aggiunto STRAIGHT_JOIN di forzare il motore InnoDB di utilizzare la corretta sequenza tabella:

SELECT 

STRAIGHT_JOIN SQL_NO_CACHE 
mbCategory.* 

FROM 
MBCategory 
mbCategory 

INNER JOIN ResourcePermission as rp 
    ON rp.primKey = mbCategory.categoryId 

where mbCategory.groupId = 12345 AND mbCategory.parentCategoryId = 0 
limit 20; 

Ma ecco il secondo problema materialzie: A mio parere mysql dovrebbe usare index A (primKey) sul funzionamento unirsi invece esegue Gamma controllato per ogni record (indice: 0x400) e richiede ancora anni! L'indice di forza non aiuta, mysql sta ancora eseguendo Range controllato per ogni record.

Ci sono solo 23 righe nella categoria MBC che soddisfano i criteri, e dopo l'unione ci sono solo 75 righe. Come posso fare in modo che mysql scelga l'indice corretto su questa operazione?

+0

Penso che MySQL non possa determinare direttamente quante righe deve leggere per trovare 20 righe corrispondenti; quindi sceglie la tabella più grande per 20 partite, quindi esegue l'unione interna. Cosa succede se rimuovi il limite? –

+0

La rimozione del limite non modifica nulla. Ho semplicemente bisogno di mysql per utilizzare l'indice corretto e non il controllo di intervallo –

risposta

23

Ok, problema elementare. Mi devo una birra. Il sistema che sto ultimamente tunning non è un sistema che ho sviluppato - Sono stato assegnato dalla mia gestione per migliorare le prestazioni (originall team non ha conoscenza su questo argomento).

Dopo settimane di costi di miglioramento delle query SQL, degli indici, del numero di query SQL eseguite dall'applicazione, non ho verificato una delle cose più importanti in questo caso !!

I TIPI DI COLONNA SONO DIVERSI!

Lo sviluppatore che ha scritto che il tipo di codice dovrebbe ottenere una PARTE piuttosto grande.

Grazie per l'aiuto!

+0

Vale la pena sottolineare che MySQL 5.7 migliora questa situazione, dove verrà supportato un 'intervallo dinamico'. Si prega di consultare questo post del blog: http://mysqlserverteam.com/dynamic-range-access-and-recent-changes/ (che collega a qui.) –

+1

Anche io ti devo una birra –

+1

Molto utile, grazie per questa intuizione – udog