sql >> Database >  >> RDS >> Mysql

Mysql trage zoekopdracht:JOIN + meerdere WHERES + ORDER BY

Indices maken een enorm verschil in mysql, een zoekopdracht die 15 minuten duurde met een verkeerde set indices duurde 0,2 seconden met de juiste, maar het vinden van de juiste balans is over het algemeen het probleem. Zonder enkele voorbeeldgegevens is het natuurlijk moeilijk te zeggen of de onderstaande oplossing u tijd zal besparen, maar in theorie zou dat wel moeten.

Om uw vragen te beantwoorden, zou ik de tabellen als volgt opnieuw ontwerpen:

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        

De prestatiewinst hier wordt behaald door het indexeren van de belangrijkste velden waaraan wordt deelgenomen en die voorkomen in de waar-clausule. Persoonlijk zou ik gaan met je eerste vraag, want als je erover nadenkt, zou dat beter moeten presteren.

Voor zover ik begrijp wat er gebeurt in de eerste en tweede vraag:

  • De eerste query wordt gefilterd door een subquery voordat de natuurlijke join wordt uitgevoerd, wat betekent dat deze alleen wordt toegevoegd aan de resulterende gegevens en niet aan de hele tabel.
  • De tweede vraag is het samenvoegen van de hele tweede tabel en vervolgens filteren van de resulterende rijen van de hele partij terug naar wat je wilt.

Als vuistregel wilt u normaal gesproken indices toevoegen aan uw belangrijkste samenvoegingsvelden en ook aan de velden die u het meest gebruikt in waar-clausules. Ik heb ook enkele unieke indices op sommige van de velden gezet die u regelmatig wilt opvragen, zoals prod_id_name_Index.

Als dit je prestaties niet verbetert, als je misschien wat dummy-gegevens zou kunnen posten om mee te spelen, kan ik misschien een snellere oplossing krijgen die ik kan benchmarken.

Hier is een artikel dat indexeert voor prestaties in mysql, het lezen waard als je meer wilt weten.

Veel succes!

EDIT:je laatste vraag die ik de eerste keer heb gemist, het antwoord is dat als je de belangrijkste samenvoegingsvelden indexeert, verandert in de waar de algehele prestaties slechts een klein beetje worden beïnvloed, maar de unieke indices die ik op de tabellen heb gezet, moeten rekening houden met de de meeste dingen waarop u uw zoekopdrachten wilt baseren. Het belangrijkste om te onthouden is dat als u regelmatig een zoekopdracht uitvoert of deelneemt aan een veld, het echt moet worden geïndexeerd, maar kleine zoekopdrachten en wijzigingen in de volgorde door u hoeft zich geen zorgen te maken over het opnieuw afstemmen van uw indexeringsstrategie.



  1. 2 manieren om te controleren of gegevenstoegang is ingeschakeld in SQL Server (T-SQL-voorbeelden)

  2. een limiet van het aantal SQL Server-verbindingen?

  3. Hoe gebruik ik PHP op de juiste manier om MySQL-object in JSON te coderen?

  4. Codeigniter ActiveRecord:doe mee met backticking