Sto passando attraverso il log delle query lente per cercare di determinare il motivo per cui alcune query si comportano in modo errato. Per motivi di coerenza, le query non sono state memorizzate nella cache e lo svuotamento è stato effettuato per cancellare la cache di sistema prima di eseguire il test. La query più o meno così:Perché aumentare il tempo di query nonostante un numero simile di righe esaminate?
SELECT P.id, P.name, P.lat, P.lng, P.price * E.rate AS 'ask' FROM Property P
INNER JOIN Exchange E ON E.currency = P.currency
WHERE P.floor_area >= k?
AND P.closing_date >= CURDATE() // this and key_buffer_size=0 prevents caching
AND P.type ='c'
AND P.lat BETWEEN v? AND v?
AND P.lng BETWEEN v? AND v?
AND P.price * E.rate BETWEEN k? AND k?
ORDER BY P.floor_area DESC LIMIT 100;
L'k?
sono definiti dall'utente costanti valori; v?
sono variabili che cambiano mentre l'utente trascina o ingrandisce una mappa. 100 risultati vengono estratti dal tavolo e ordinati in base all'area del piano in ordine decrescente.
Un tasto PRIMARIO su id
e un INDICE su floor_area
è impostato solo. Nessun altro indice viene creato in modo che MySQL utilizzi costantemente floor_area
come unica chiave. I tempi di query e righe esaminati sono rilevati come segue:
query number 1 2 3 4 5 6 7 8 9 10
user action on map start > + + < ^ + > v +
time in seconds 138 0.21 0.43 32.3 0.12 0.12 36.3 4.33 0.33 2.00
rows examined ('000) 43 43 43 60 43 43 111 139 133 176
La query piano di esecuzione è il seguente:
+----+-------------+-------+--------+---------------+---------+---------+--------------------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+--------------------+---------+-------------+
| 1 | SIMPLE | P | range | id_flA | id_flA | 3 | NULL | 4223660 | Using where |
| 1 | SIMPLE | E | eq_ref | PRIMARY | PRIMARY | 3 | BuySell.P.currency | 1 | Using where |
+----+-------------+-------+--------+---------------+---------+---------+--------------------+---------+-------------+
La prova viene eseguita diverse volte ed i risultati sono abbastanza coerenti con quanto sopra . Quale potrebbe essere il motivo/i per il picco nei tempi di interrogazione nella query numero 4 e numero 7 e come posso farlo?
UPDATE:
Risultati di rimozione ORDER BY
come suggerito da Digital Precision:
query number 1 2 3 4 5 6 7 8 9 10
user action on map start > + + < ^ + > v +
time in seconds 255 3.10 3.16 3.08 3.18 3.21 3.32 3.18 3.17 3.80
rows examined ('000) 131 131 131 131 136 136 136 136 136 157
La query piano di esecuzione è la stessa di cui sopra anche se sembra più simile a una scansione di tabella. Si noti che sto usando il motore MyISAM, versione 5.5.14.
come richiesto, sotto è lo schema:
| Property | CREATE TABLE `Property` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`type` char(1) NOT NULL DEFAULT '',
`lat` decimal(6,4) NOT NULL DEFAULT '0.0000',
`lng` decimal(7,4) NOT NULL DEFAULT '0.0000',
`floor_area` mediumint(8) unsigned NOT NULL DEFAULT '0',
`currency` char(3) NOT NULL DEFAULT '',
`price` int(10) unsigned NOT NULL DEFAULT '0',
`closing_date` date NOT NULL DEFAULT '0000-00-00',
`name` char(25) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `id_flA` (`floor_area`)
) ENGINE=MyISAM AUTO_INCREMENT=5000000 DEFAULT CHARSET=latin1
| Exchange | CREATE TABLE `Exchange` (
`currency` char(3) NOT NULL,
`rate` decimal(11,10) NOT NULL DEFAULT '0.0000000000',
PRIMARY KEY (`currency`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
2 ° UPDATE:
ho pensato che sarebbe stato opportuno inserire i parametri non predefiniti nel file di configurazione my.cnf
poiché due dei answerers menzionano i parametri:
max_heap_table_size = 1300M
key_buffer_size = 0
read_buffer_size = 1300M
read_rnd_buffer_size = 1024M
sort_buffer_size = 1300M
Ho 2 GB di RAM sul mio server di prova.
Puoi provare ad aggiungere un indice su '(type, closing_date)' o '(type, floor_area)' - assumendo che siano nella stessa tabella (non è ovvio senza i dettagli delle tabelle - per favore aggiungili). Questo può aiutare la query in generale, non i picchi. –
@ypercude: ci sono molte altre condizioni nelle colonne 'WHERE'. Sono d'accordo che sarebbe d'aiuto, ma in piccola parte a causa del problema di intervallo e della bassa cardinalità della colonna 'type'. È necessario risolvere il problema dell'indice semplice prima di provare l'indice composito. –
'type' può avere una bassa cardinalità ma l'indice per aiutarlo dipenderà dalla cardinalità composta di' (type, floor_area) '. Se quasi tutte le tue file che sono state controllate ogni volta hanno 'type = 'condominium' allora non sarà di grande aiuto. Ma aiuterà occasionalmente. –