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

Mysql langsom forespørgsel:JOIN + flere HVOR + BESTIL EFTER

Indekser gør en enorm forskel i mysql, en forespørgsel, der tog 15 minutter med et forkert sæt indekser, tog 0,2 sekunder med de rigtige, men det er at finde den rigtige balance, hvilket generelt er problemet. Uden nogle prøvedata er det naturligvis svært at sige, om nedenstående løsning vil spare dig nogen tid, men i teorien burde den det.

For at besvare dine spørgsmål ville jeg omdesigne tabellerne sådan:

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        

Ydeevnegevinsten her er opnået ved at indeksere de vigtigste felter, der bliver tilsluttet, og som er vist i where-klausulen. Personligt ville jeg gå med din første forespørgsel, som når du tænker over det, der burde fungere bedre.

Så vidt jeg forstår, hvad der sker i den første og anden forespørgsel:

  • Den første forespørgsel bliver filtreret af en underforespørgsel, før den naturlige joinforbindelse udføres, hvilket betyder, at den kun slutter sig til de resulterende data og ikke hele tabellen.
  • Den anden forespørgsel forbinder hele den anden tabel og filtrerer derefter de resulterende rækker af hele partiet tilbage til det, du ønsker.

Som en tommelfingerregel vil du normalt tilføje indekser på dine store sammenføjningsfelter og også de felter, som du bruger mest i where-klausuler. Jeg har også sat nogle unikke indekser på nogle af de felter, som du gerne vil forespørge på regelmæssigt, såsom prod_id_name_Index.

Hvis dette ikke forbedrer din ydeevne, hvis du måske kunne poste nogle dummy-data at lege med, kan jeg muligvis få en hurtigere løsning, som jeg kan benchmarke.

Her er en artikel, der gennemgår indeksering for ydeevne i mysql, som er værd at læse, hvis du vil vide mere.

Held og lykke!

EDIT:Dit sidste spørgsmål, som jeg gik glip af første gang, svaret er, at hvis din indeksering af de vigtigste sammenføjningsfelter ændres til hvor, vil det kun påvirke den overordnede ydeevne en smule, men de unikke indekser, jeg har lagt på tabellerne, bør tage højde for de fleste ting, du ønsker at basere forespørgsler på. Det vigtigste at huske er, at hvis du ofte forespørger eller tilslutter dig et felt, så skal det virkelig indekseres, men mindre forespørgsler og ændringer i rækkefølgen fra dig bør bare ikke bekymre dig om at tilpasse din indekseringsstrategi.



  1. meget stor mysql-tabel og rapportering

  2. Optælling baseret på tilstand i SQL Server

  3. Hvad er et fuldtekstindeks, og hvornår skal jeg bruge det?

  4. pt-table-sync, mærkelige problemer vedrørende værtsnavn