Sembra che, per qualche motivo, MySQL
sceglie di utilizzare l'indice SIL
sulla prima tabella e lo usa entrambi per la ricerca (WHERE sil_id = 4601038
) e raggruppamento (GROUP BY cu.Id
).
Puoi dirgli di usare il PK
della tavola
SELECT cu.Href, COUNT(p.CatUrlId) FROM cat_urls cu
USE INDEX FOR JOIN (PRIMARY)
JOIN products p ON p.CatUrlId=cu.Id
WHERE sil_id=4601038
GROUP by cu.Id
e produrrà questo piano di esecuzione:
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
---+-------------+-------+-------+---------------+---------+---------+------------------+------+-------------
1 | SIMPLE | cu | index | PRIMARY | PRIMARY | 4 | NULL | 1 | Using where
1 | SIMPLE | p | ref | CatUrl | CatUrl | 4 | cbs-test-1.cu.Id | 1 | Using index
Ignora i valori riportati nella colonna rows
; non sono corretti perché le mie tabelle sono vuote.
Nota il Extra
la colonna ora contiene solo Using where
ma nota anche che il join type
colonna modificata da ref
(molto bene) per index
(scansione completa dell'indice, non del tutto buona).
Una soluzione migliore è aggiungere un indice nella colonna SIL_Id
. Lo so, SIL_Id
è un prefisso dell'indice SIL(SIL_Id, AsCatId)
e in teoria un altro indice nella colonna SIL_Id
è del tutto inutile. Ma sembra che risolva il problema in questo caso.
ALTER TABLE cat_urls
ADD INDEX (SIL_Id)
;
Ora usalo nella query:
SELECT cu.Href, COUNT(p.CatUrlId) FROM cat_urls cu
USE INDEX FOR JOIN (SIL_Id)
JOIN products p ON p.CatUrlId=cu.Id
WHERE sil_id=4601038
GROUP by cu.Id
Il piano di esecuzione delle query ora sembra molto migliore:
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
---+-------------+-------+------+---------------+--------+---------+------------------+------+-------------
1 | SIMPLE | cu | ref | SIL_Id | SIL_Id | 4 | const | 1 | Using where
1 | SIMPLE | p | ref | CatUrl | CatUrl | 4 | cbs-test-1.cu.Id | 1 | Using index
Lo svantaggio è che abbiamo un indice aggiuntivo che è (teoricamente) inutile. Occupa spazio di archiviazione e consuma cicli del processore ogni volta che una riga viene aggiunta, eliminata o ha il suo SIL_Id
campo modificato.