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?
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? –
La rimozione del limite non modifica nulla. Ho semplicemente bisogno di mysql per utilizzare l'indice corretto e non il controllo di intervallo –