Ho testato diverse idee per ottimizzare alcuni dei tavoli che abbiamo nel nostro sistema al lavoro. Oggi mi sono imbattuto in un tavolo che traccia ogni vista su ogni veicolo nel nostro sistema. Crea la tabella qui sotto.MySQL EXPLAIN "type" cambia da "range" a "ref" quando la data nell'istruzione where viene modificata?
SHOW CREATE TABLE vehicle_view_tracking;
CREATE TABLE `vehicle_view_tracking` (
`vehicle_view_tracking_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`public_key` varchar(45) NOT NULL,
`vehicle_id` int(10) unsigned NOT NULL,
`landing_url` longtext NOT NULL,
`landing_port` int(11) NOT NULL,
`http_referrer` longtext,
`created_on` datetime NOT NULL,
`created_on_date` date NOT NULL,
`server_host` longtext,
`server_uri` longtext,
`referrer_host` longtext,
`referrer_uri` longtext,
PRIMARY KEY (`vehicle_view_tracking_id`),
KEY `vehicleViewTrackingKeyCreatedIndex` (`public_key`,`created_on_date`),
KEY `vehicleViewTrackingKeyIndex` (`public_key`)
) ENGINE=InnoDB AUTO_INCREMENT=363439 DEFAULT CHARSET=latin1;
Mi stavo giocando con indici a colonne multiple e singole colonne. Ho eseguito la seguente query:
EXPLAIN EXTENDED SELECT dealership_vehicles.vehicle_make, dealership_vehicles.vehicle_model, vehicle_view_tracking.referrer_host, count(*) AS count
FROM vehicle_view_tracking
LEFT JOIN dealership_vehicles
ON dealership_vehicles.dealership_vehicle_id = vehicle_view_tracking.vehicle_id
WHERE vehicle_view_tracking.created_on_date >= '2011-09-07' AND vehicle_view_tracking.public_key IN ('ab12c3')
GROUP BY (dealership_vehicles.vehicle_make) ASC , dealership_vehicles.vehicle_model, referrer_host
+----+-------------+-----------------------+--------+----------------------------------------------------------------+------------------------------------+---------+----------------------------------------------+-------+----------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------------------+--------+----------------------------------------------------------------+------------------------------------+---------+----------------------------------------------+-------+----------+----------------------------------------------+
| 1 | SIMPLE | vehicle_view_tracking | range | vehicleViewTrackingKeyCreatedIndex,vehicleViewTrackingKeyIndex | vehicleViewTrackingKeyCreatedIndex | 50 | NULL | 23086 | 100.00 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | dealership_vehicles | eq_ref | PRIMARY | PRIMARY | 8 | vehicle_view_tracking.vehicle_id | 1 | 100.00 | |
+----+-------------+-----------------------+--------+----------------------------------------------------------------+------------------------------------+---------+----------------------------------------------+-------+----------+----------------------------------------------+
(tempo di esecuzione per la effettiva query di selezione è stato .309 secondi)
poi a cambiare la data nella clausola WHERE da '2011-09-07' a '2011- 07-07' e preso i seguenti spiegare i risultati
EXPLAIN EXTENDED SELECT dealership_vehicles.vehicle_make, dealership_vehicles.vehicle_model, vehicle_view_tracking.referrer_host, count(*) AS count
FROM vehicle_view_tracking
LEFT JOIN dealership_vehicles
ON dealership_vehicles.dealership_vehicle_id = vehicle_view_tracking.vehicle_id
WHERE vehicle_view_tracking.created_on_date >= '2011-07-07' AND vehicle_view_tracking.public_key IN ('ab12c3')
GROUP BY (dealership_vehicles.vehicle_make) ASC , dealership_vehicles.vehicle_model, referrer_host
+----+-------------+-----------------------+--------+----------------------------------------------------------------+-----------------------------+---------+----------------------------------------------+-------+----------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------------------+--------+----------------------------------------------------------------+-----------------------------+---------+----------------------------------------------+-------+----------+----------------------------------------------+
| 1 | SIMPLE | vehicle_view_tracking | ref | vehicleViewTrackingKeyCreatedIndex,vehicleViewTrackingKeyIndex | vehicleViewTrackingKeyIndex | 47 | const | 53676 | 100.00 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | dealership_vehicles | eq_ref | PRIMARY | PRIMARY | 8 | vehicle_view_tracking.vehicle_id | 1 | 100.00 | |
+----+-------------+-----------------------+--------+----------------------------------------------------------------+-----------------------------+---------+----------------------------------------------+-------+----------+----------------------------------------------+
(tempo di esecuzione per la query di selezione effettivo era .670 secondi)
vedo 4 cambiamenti principali:
0.123.- tipo cambiato da gamma al rif
- chiave cambiato da vehicleViewTrackingKeyCreatedIndex a vehicleViewTrackingKeyIndex
- key_len passa da 50 47 (causata dal cambiamento di chiave)
- righe modificate da 23086 a 53676 (causato dal cambio di chiave)
A questo punto, il tempo di esecuzione è di soli 6 secondi per la query lenta, tuttavia nel nostro database abbiamo solo il 10% circa dei nostri veicoli.
Si sta facendo tardi e potrei aver trascurato qualcosa nei documenti mysql ma non riesco a trovare il motivo per cui la chiave (ea sua volta il tipo e le righe) cambiano quando la data viene modificata nella clausola where.
L'aiuto è molto apprezzato. Ho cercato qualcuno che avesse lo stesso problema/simile a una data che causava questo cambiamento e non è stato in grado di trovare nulla. Se ho perso un post precedente, per favore collegami :-)
Quindi, in poche parole, l'ottimizzatore mysql ha ritenuto che fosse meglio/più veloce apportare la modifica e utilizzare l'altro indice. Ho eseguito un altro test e rimosso il secondo indice (vehicleViewTrackingKeyIndex) e il tempo di query era compreso tra 0,01 secondi. Sembra che con l'aumentare del set di risultati, si è reso conto che non aveva senso utilizzare l'indice a 2 colonne. – CriticalSpeak
@CriticalSpeak: Sì, in poche parole. Spesso devi giocare con gli indici (e riscrivere le query) molto più di quanto dovresti avere in MySQL perché il suo ottimizzatore ha molte lacune. Se ti senti male, prova PostgreSQL. – derobert