Mysql
 sql >> Database >  >> RDS >> Mysql

Query lenta di Mysql:JOIN + multiple WHERE + ORDER BY

Gli indici fanno un'enorme differenza in mysql, una query che ha impiegato 15 minuti con un set di indici sbagliato ha impiegato 0,2 secondi con quelli giusti, ma in genere il problema è trovare il giusto equilibrio. Naturalmente senza alcuni dati di esempio è davvero difficile dire se la soluzione seguente ti farà risparmiare tempo, ma in teoria dovrebbe.

Per rispondere alle tue domande, riprogetterei i tavoli in questo modo:

CREATE TABLE `product_all` ( 
`prod_id` INT( 10 ) NOT NULL, 
`ref_id` INT( 10) NOT NULL, 
`date` DATE NOT NULL , 
`buy_link` BLOB NOT NULL , 
`sale_price` FLOAT NOT NULL,
PRIMARY KEY (prod_id, ref_id) ,
INDEX date_Index (`date` ASC),
UNIQUE INDEX prod_price_Index (prod_id ASC, sale_price ASC)
) ENGINE = MYISAM ; 


CREATE TABLE `product_info` ( 
`prod_id` INT( 10 ) NOT NULL AUTO_INCREMENT, 
`prod_name` VARCHAR( 200 ) NOT NULL, 
`brand` VARCHAR( 50 ) NOT NULL, 
`retail_price` FLOAT NOT NULL, 
`category` INT( 3 ) NOT NULL, 
`gender` VARCHAR( 1 ) NOT NULL, 
`type` VARCHAR( 10 ) NOT NULL,
PRIMARY KEY (prod_id) ,
UNIQUE INDEX prod_id_name_Index (prod_id ASC, prod_name ASC),
INDEX category_Index (category ASC),
INDEX gender_Index (gender ASC)
) ENGINE = MYISAM ;

SELECT product_info.*, MIN(product_all.sale_price) as sale_price, product_all.buy_link         
FROM product_info         
NATURAL JOIN (SELECT * FROM product_all WHERE product_all.date = '2010-09-30') as product_all         
WHERE (product_info.category = 2           
AND product_info.gender = 'W' )         
GROUP BY product_all.prod_id         
ORDER BY MIN(product_all.sale_price) ASC LIMIT 13        

Il guadagno in termini di prestazioni qui è ottenuto dall'indicizzazione dei campi principali che vengono uniti e sono presenti nella clausola where. Personalmente andrei con la tua prima domanda come quando ci pensi che dovrebbe funzionare meglio.

Per quanto ho capito cosa sta succedendo nella prima e nella seconda query:

  • La prima query viene filtrata da una sottoquery prima di eseguire l'unione naturale, ciò significa che si unisce solo ai dati risultanti e non all'intera tabella.
  • La seconda query è unire l'intera seconda tabella e quindi filtrare le righe risultanti dell'intero lotto in base a ciò che desideri.

Come regola generale, normalmente vuoi aggiungere indici sui tuoi campi di unione principali e anche sui campi che usi di più nelle clausole where. Ho anche inserito alcuni indici univoci su alcuni dei campi che vorrai interrogare regolarmente, come prod_id_name_Index.

Se questo non migliora le tue prestazioni, se potessi pubblicare alcuni dati fittizi con cui giocare, potrei essere in grado di ottenere una soluzione più veloce che posso confrontare.

Qui è un articolo che passa attraverso l'indicizzazione per le prestazioni in mysql, vale la pena leggerlo se vuoi saperne di più.

Buona fortuna!

EDIT:la tua ultima domanda che mi è sfuggita la prima volta, la risposta è che se indicizzi i campi di unione principali poi cambia in dove influirà solo leggermente sulle prestazioni complessive, ma gli indici univoci che ho inserito nelle tabelle dovrebbero tenere conto del la maggior parte delle cose su cui vorrai basare le query. La cosa principale da ricordare è che se esegui query o ti unisci frequentemente a un campo, dovrebbe essere davvero indicizzato, ma le query minori e le modifiche all'ordine da parte tua non dovrebbero semplicemente preoccuparti in termini di riallineamento della tua strategia di indicizzazione.