2016-02-10 34 views
0

加入我有3個表:提高性能時,將多個在MySQL

Nutritions_facts表,它是具有全部營養nutrition_id和nutrition_ename Products_info表,有產品信息和列PRODUCT_ID,product_ename靜電工作臺,品牌 product_nutrition_facts 這是中介表,將產品與其營養成分與其價值聯繫起來。結構是product_id,nutrition_id,nutrition_value ..每個產品可以有一排或更多,具體取決於它的營養成分數量。 這裏是一個真正的測試例子

Nutrition_facts表

nutrition_id |nutrition_ename 
     1 | caloreis  
     2 | fat  
     3 | sugar  
     4 | salt 

Products_info表

product_id| product_ename   | brand 
    1 | Nutella Hazelnut Cocoa | Nutella  
    2 | Nutella Jar   | Nutella 

product_nutrition_facts表

product_id | nutrition_id | nutrition_value 
    1 |   1 |    200 
    1 |   2 |    15 
    1 |   3 |    2 
    1 |   4 |    11 
    2 |   1 |    200 
    2 |   2 |    15 
    2 |   3 |    12 
    2 |   4 |    11 

我需要查詢,返回我的產品的名稱糖的價值小於或等於qula 15和salt小於或等於140

我構建了一個查詢,它返回正確的值但處理時間很長。可有人提出修改建議,以提高性能,請..

SELECT DISTINCT p.product_id, p.brand, p.e_name, p.image_low 
FROM products_info p 
JOIN product_nutrition_facts pn ON p.product_id = pn.product_id 
WHERE p.brand = 'AL MARAI' 
AND (
(
p.product_id 
IN (

SELECT product_id 
FROM product_nutrition_facts pn 
WHERE pn.nutrition_id =3 
AND pn.nutrition_value <=15 
) 
) 
AND (
p.product_id 
IN (

SELECT product_id 
FROM product_nutrition_facts pn 
WHERE pn.nutrition_id =4 
AND pn.nutrition_value <=140 
) 
) 
) 
AND (
pn.nutrition_id =3 
OR pn.nutrition_id =4 
) 

編輯

CREATE TABLE `products_info` (
`product_id` int(11) NOT NULL AUTO_INCREMENT, 
`image_low` varchar(400) DEFAULT NULL, 
    `e_name` varchar(200) DEFAULT NULL, 
PRIMARY KEY (`product_id`), 
UNIQUE KEY `product_id_UNIQUE` (`product_id`) 
) ENGINE=InnoDB AUTO_INCREMENT=249292 DEFAULT CHARSET=utf8 


CREATE TABLE `product_nutrition_facts` (
`prod_nut_id` int(11) NOT NULL AUTO_INCREMENT, 
`product_id` int(11) DEFAULT NULL, 
`nutrition_id` int(11) DEFAULT NULL, 
`nutrition_value` varchar(25) DEFAULT NULL, 
`unit_id` int(11) DEFAULT NULL, 
`parent` int(11) DEFAULT NULL, 
`serving_size` varchar(145) DEFAULT NULL, 
`serving_size_unit` int(11) DEFAULT NULL, 
`no_nutrition_facts` int(11) NOT NULL, 
`added_by` varchar(145) DEFAULT NULL, 
`last_update` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
`inserted_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
`updated_by` varchar(150) NOT NULL, 
PRIMARY KEY (`prod_nut_id`), 
UNIQUE KEY `prod_nut_id_UNIQUE` (`prod_nut_id`), 
KEY `nutrition_id_fk_idx` (`nutrition_id`), 
KEY `unit_Fk_idx` (`unit_id`), 
KEY `unit_fk1_idx` (`serving_size_unit`), 
KEY `product_idFK` (`product_id`) 
) ENGINE=InnoDB AUTO_INCREMENT=580809 DEFAULT CHARSET=utf8 

CREATE TABLE `nutrition_facts` (
`nutrition_id` int(11) NOT NULL AUTO_INCREMENT, 
`nutrition_aname` varchar(145) DEFAULT NULL, 
`nutrition_ename` varchar(145) DEFAULT NULL, 
`alternative_name` varchar(145) DEFAULT NULL, 
    `unit` varchar(8) NOT NULL, 
`daily_value` int(11) NOT NULL, 
`nut_order` int(2) NOT NULL, 
`is_child` int(1) NOT NULL, 
`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
PRIMARY KEY (`nutrition_id`) 
) ENGINE=InnoDB AUTO_INCREMENT=53 DEFAULT CHARSET=utf8 
+0

添加表格描述'show create table Nutritions_facts','show create table Products_info','show create table product_nutrition_facts' –

+0

@MaxP。我添加它們,但是products_info表非常大,所以我只放了它的一部分。 – palAlaa

回答

1

嘗試添加索引product_nutrition_facts (nutrition_id,nutrition_value,product_id)product_nutrition_facts (product_id,nutrition_id,nutrition_value)products_info (brand)和perfom查詢

SELECT p.* 
FROM products_info p 
join product_nutrition_facts pn1 on 
    pn1.product_id=p.product_id 
    AND pn1.nutrition_id=3 
    AND pn1.nutrition_value<=15 
join product_nutrition_facts pn2 on 
    pn2.product_id=p.product_id 
    AND pn2.nutrition_id=4 
    AND pn2.nutrition_value<=140 
where 
    p.brand = 'AL MARAI' 
0

IN (SELECT ...) - 不能很好地優化;變成JOIN(如Max建議)

「Overnormalization」 - Nutrition_facts可以被消除;只需使用nutrition_names代替nutrition_id即可。