sql >> Databáze >  >> RDS >> Mysql

Pomalý dotaz Mysql:JOIN + více WHERES + ORDER BY

Indexy mají obrovský rozdíl v mysql, jeden dotaz, který trval 15 minut se špatnou sadou indexů, trval 0,2 sekundy se správnými, ale obecně jde o nalezení správné rovnováhy. Přirozeně bez některých ukázkových dat je opravdu těžké říci, zda vám níže uvedené řešení ušetří čas, ale teoreticky by mělo.

Abych odpověděl na vaše otázky, přepracoval bych tabulky takto:

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        

Zisk výkonu je zde dosažen indexováním hlavních polí, která jsou spojena a jsou uvedena v klauzuli where. Osobně bych šel s vaším prvním dotazem, jako když o tom přemýšlíte, že by měl fungovat lépe.

Pokud rozumím tomu, co se děje v prvním a druhém dotazu:

  • První dotaz je před provedením přirozeného spojení filtrován dílčím dotazem, což znamená jeho jediné spojení s výslednými daty a nikoli celou tabulkou.
  • Druhým dotazem je spojení celé druhé tabulky a následné filtrování výsledných řádků celé šarže zpět na to, co chcete.

Zpravidla chcete přidat indexy do svých hlavních spojovacích polí a také do polí, která v klauzulích where používáte nejčastěji. Do některých polí jsem také vložil několik jedinečných indexů, na která se budete chtít pravidelně dotazovat, jako například prod_id_name_Index.

Pokud to nezlepší váš výkon, pokud byste mohli zveřejnit nějaká falešná data, s nimiž si budete hrát, možná budu moci získat rychlejší řešení, které mohu porovnat.

Zde je článek, který prochází indexováním výkonu v mysql, stojí za přečtení, pokud se chcete dozvědět více.

Hodně štěstí!

EDIT:Vaše poslední otázka, kterou jsem poprvé přehlédl, odpověď je, že pokud se vaše indexování hlavních spojovacích polí změní na kde, ovlivní celkový výkon pouze mírně, ale jedinečné indexy, které jsem dal do tabulek, by měly odpovídat většinu věcí, na kterých budete chtít zakládat dotazy. Hlavní věc, kterou je třeba si zapamatovat, je, že pokud se často dotazujete na pole nebo se k němu připojujete, mělo by být skutečně indexováno, ale s drobnými dotazy a změnami v pořadí byste si neměli dělat starosti, pokud jde o přeladění vaší strategie indexování.



  1. Výkon UUID v MySQL?

  2. Nastavení hodnot sloupců jako názvů sloupců ve výsledku dotazu SQL

  3. Oracle 11g:Výchozí statická hodnota, když dotaz nevrací nic

  4. PŘIPOJTE SE ke třem stolům