[Db] Subquery MySQL e full-scan della tabella principale

Cesare D'Amico cesare a ngi.it
Gio 5 Lug 2007 11:30:17 CEST


Hola todos, ho una tabella articoli con campo (indicizzato) codice_ean;
la seguente query mi prende un sacco di tempo a causa di un full scan:

mysql> select codice_ean, anno, colore, taglia 
       from articoli 
       where codice_ean in (
           select codice_ean 
           from articoli 
           group by codice_ean 
           having count(*) > 1
       )

Il problema è che ho 3 cavolo di codici articolo che sono entrati con uguale
codice_ean ma diversi campi identificativi (mi avevano ovviamente promesso
che  era una cosa che non si sarebbe MAI verificata, cretino io a credergli)
per un totale di 52 codici a barre (campo codice_ean) doppi.

Ora, la query sopra dovrebbe darmi un po' di dati che mi interessano, ma 
ci impiega una vita. La subquery da sola impiega 0.10 secondi netti. Se
faccio una EXPLAIN scopro che viene fatto un full table scan per la
prima query:

mysql> explain select codice_ean, anno, colore, taglia from articoli 
where codice_ean = any (select codice_ean from articoli group by 
codice_ean having count(*) > 1);
+----+--------------------+----------+-------+---------------+------------+---------+------+-------+-------------+
| id | select_type        | table    | type  | possible_keys | key        | key_len | ref  | rows  | Extra       |
+----+--------------------+----------+-------+---------------+------------+---------+------+-------+-------------+
|  1 | PRIMARY            | articoli | ALL   | NULL          | NULL       | NULL    | NULL | 27281 | Using where |
|  2 | DEPENDENT SUBQUERY | articoli | index | NULL          | codice_ean | 16      | NULL | 27281 | Using index |
+----+--------------------+----------+-------+---------------+------------+---------+------+-------+-------------+

Il "type" ALL dice che non userà nessun indice.

Se sostituisco "= ANY" con "IN" la EXPLAIN non cambia. Qualcuno mi sa
spiegare il perché di questo risultato? (io mi aspettavo che PRIMA 
trovasse il set della subquery, e poi usasse l'indice su codice_ean per
fare lo scan, al limite uno per uno, dei risultati della subquery).

Per la cronaca:

mysql> show index from articoli;
+----------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table    | Non_unique | Key_name    | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+----------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| articoli |          0 | PRIMARY     |            1 | id          | A         |       27059 |     NULL | NULL   |      | BTREE      |         |
| articoli |          0 | fornitore   |            1 | fornitore   | A         |           3 |     NULL | NULL   | YES  | BTREE      |         |
| articoli |          0 | fornitore   |            2 | codice      | A         |        4509 |     NULL | NULL   | YES  | BTREE      |         |
| articoli |          0 | fornitore   |            3 | colore      | A         |       13529 |     NULL | NULL   | YES  | BTREE      |         |
| articoli |          0 | fornitore   |            4 | taglia      | A         |       27059 |     NULL | NULL   | YES  | BTREE      |         |
| articoli |          0 | fornitore   |            5 | anno        | A         |       27059 |     NULL | NULL   | YES  | BTREE      |         |
| articoli |          0 | fornitore   |            6 | collezione  | A         |       27059 |     NULL | NULL   | YES  | BTREE      |         |
| articoli |          1 | codice_ean  |            1 | codice_ean  | A         |       27059 |     NULL | NULL   | YES  | BTREE      |         |
| articoli |          1 | codice      |            1 | codice      | A         |        4509 |     NULL | NULL   | YES  | BTREE      |         |
| articoli |          1 | anno        |            1 | anno        | A         |           1 |     NULL | NULL   | YES  | BTREE      |         |
| articoli |          1 | taglia      |            1 | taglia      | A         |          57 |     NULL | NULL   | YES  | BTREE      |         |
| articoli |          1 | colore      |            1 | colore      | A         |         966 |     NULL | NULL   | YES  | BTREE      |         |
| articoli |          1 | campionario |            1 | campionario | A         |           9 |     NULL | NULL   | YES  | BTREE      |         |
| articoli |          1 | fornitore_2 |            1 | fornitore   | A         |           1 |     NULL | NULL   | YES  | BTREE      |         |
| articoli |          1 | collezione  |            1 | collezione  | A         |           7 |     NULL | NULL   | YES  | BTREE      |         |
+----------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

Grazie per una qualsiasi info!

Ciaps
     ce
-- 
Cesare D'Amico      |  Gruppo Volta
Area tecnica        |  Web & Mkt Solutions
Tel: 045 21 000 84  |  Via Leida 8 - Verona
Fax: 045 21 000 85  |  http://www.gruppovolta.it


Maggiori informazioni sulla lista Db