sql >> Databasteknik >  >> RDS >> Mysql

Mysql långsam fråga:JOIN + flera VAR + BESTÄLL EFTER

Index gör en enorm skillnad i mysql, en fråga som tog 15 minuter med en felaktig uppsättning index tog 0,2 sekunder med de rätta, men att hitta den rätta balansen som generellt är problemet. Naturligtvis utan några exempeldata är det verkligen svårt att säga om lösningen nedan kommer att spara dig någon tid, men i teorin borde det göra det.

För att svara på dina frågor skulle jag designa om tabellerna så här:

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        

Prestandavinsten här uppnås genom att indexera de viktigaste fälten som ansluts till och som visas i where-klausulen. Personligen skulle jag gå med din första fråga som när du tänker på det som borde fungera bättre.

Såvitt jag förstår vad som händer i den första och andra frågan:

  • Den första frågan filtreras av en underfråga innan den naturliga kopplingen görs, det betyder att den bara ansluts i den resulterande informationen och inte hela tabellen.
  • Den andra frågan sammanfogar hela den andra tabellen och filtrerar sedan de resulterande raderna av hela partiet tillbaka till vad du vill ha.

Som en tumregel vill du normalt lägga till index på dina stora kopplingsfält och även de fält som du använder mest i where-klausuler. Jag har också satt några unika index på några av fälten som du vill fråga regelbundet, som prod_id_name_Index.

Om detta inte förbättrar din prestanda om du kanske kan lägga upp lite dummydata att leka med, kanske jag kan få en snabbare lösning som jag kan jämföra.

Här är en artikel som går igenom indexering för prestanda i mysql, värd att läsa om du vill veta mer.

Lycka till!

EDIT:Din sista fråga som jag missade första gången, svaret är att om din indexering av de viktigaste sammanfogningsfälten ändras till var kommer det bara att påverka det övergripande resultatet något, men de unika indexen jag har lagt på tabellerna bör stå för de flesta saker du vill basera frågor på. Det viktigaste att komma ihåg är att om du frågar eller ansluter dig till ett fält ofta så borde det verkligen indexeras, men mindre frågor och ändringar av ordningen av dig bör bara inte oroa dig för när det gäller att anpassa din indexeringsstrategi.



  1. Hämta rader i en MySQL-databastabell med MySQL C API och C++

  2. Vad är det för fel på denna PL/SQL? Bindningsvariabel * DEKLARAS INTE

  3. MySQL-frågan returnerar dubbletter av rader

  4. Ansluter .NET på Linux till en ODBC-datakälla