无论如何都要优化此查询?
我知道它在子查询中被阻止了:
(SELECT IFNULL(max(datetimesql),'NS') FROM storeCheckRecords
WHERE store_id=@storeid AND upc=855555000032)
如果没有IFNULL子查询,它会在不到1秒的时间内执行。这个例子与subquerys相比需要20秒,而且只有54行。无论如何要改写它以加快它?感谢您的帮助。
SELECT
SQL_CALC_FOUND_ROWS @storeid:=z.id
,z.biz_name
,z.wf_store_name
,z.e_address
,z.e_city
,z.e_state
,z.e_postal
,IFNULL(total_sales - prev_total_sales,'CV') as diff_total_sales
,IFNULL(d_source,'N/A') as d_source
,IFNULL(unit_sales1 - prev_unit_sales1 , (SELECT IFNULL(max(datetimesql),'NS')
FROM storeCheckRecords
WHERE store_id=@storeid AND upc=855555000032)
) as diff_unit_sales1
,IFNULL(unit_sales2 - prev_unit_sales2, (SELECT IFNULL(max(datetimesql),'NS')
FROM storeCheckRecords
WHERE store_id=@storeid AND upc=855555000033)
) as diff_unit_sales2
,IFNULL(unit_sales3 - prev_unit_sales3, (SELECT IFNULL(max(datetimesql),'NS')
FROM storeCheckRecords
WHERE store_id=@storeid AND upc=855555000034)
) as diff_unit_sales3
,IFNULL(unit_sales4 - prev_unit_sales4, (SELECT IFNULL(max(datetimesql),'NS')
FROM storeCheckRecords
WHERE store_id=@storeid AND upc=855555000035)
) as diff_unit_sales4
,IFNULL(unit_sales5 - prev_unit_sales5, (SELECT IFNULL(max(datetimesql),'NS')
FROM storeCheckRecords
WHERE store_id=@storeid AND upc=855555000036)
) as diff_unit_sales5
,IFNULL(unit_sales6 - prev_unit_sales6, (SELECT IFNULL(max(datetimesql),'NS')
FROM storeCheckRecords
WHERE store_id=@storeid AND upc=855555000038)
) as diff_unit_sales6
FROM
(SELECT s1.id,s1.biz_name as biz_name
,s1.wf_store_name as wf_store_name
,s1.e_address as e_address
,s1.e_city as e_city
,s1.e_state as e_state
,s1.e_postal as e_postal
,sum(s2.unit_sales) as total_sales
,sum(s2.unit_sales/4.28571428571) as week_avg
,group_concat(DISTINCT s2.d_source separator ',') as d_source
,SUM(CASE u.id WHEN 1 THEN s2.unit_sales ELSE NULL END) AS unit_sales1
,SUM(CASE u.id WHEN 2 THEN s2.unit_sales ELSE NULL END) AS unit_sales2
,SUM(CASE u.id WHEN 3 THEN s2.unit_sales ELSE NULL END) AS unit_sales3
,SUM(CASE u.id WHEN 4 THEN s2.unit_sales ELSE NULL END) AS unit_sales4
,SUM(CASE u.id WHEN 5 THEN s2.unit_sales ELSE NULL END) AS unit_sales5
,SUM(CASE u.id WHEN 6 THEN s2.unit_sales ELSE NULL END) AS unit_sales6
FROM allStores as s1
INNER JOIN storeCheckRecords AS s2
ON s1.id = s2.store_id
AND s2.datetimesql BETWEEN '2015-07-01' AND '2015-07-31'
AND s1.key_retailer LIKE 'WHOLE FOODS'
AND s1.wf_region LIKE 'Midwest'
INNER JOIN (SELECT 1 AS id
,'855555000032' AS upc
UNION
SELECT 2
,'855555000033'
UNION
SELECT 3
,'855555000034'
UNION
SELECT 4
,'855555000035'
UNION
SELECT 5
,'855555000036'
UNION
SELECT 6
,'855555000038') u
ON u.upc = s2.upc
GROUP BY s1.id) x
LEFT OUTER JOIN
(SELECT s1.id,s1.biz_name as prev_biz_name
,s1.wf_store_name as prev_wf_store_name
,s1.e_address as prev_e_address
,s1.e_city as prev_e_city
,s1.e_state as prev_e_state
,s1.e_postal as prev_e_postal
,sum(s2.unit_sales) as prev_total_sales
,sum(s2.unit_sales/4.28571428571) as prev_week_avg
,group_concat(DISTINCT s2.d_source separator ',') as prev_d_source
,SUM(CASE u.id WHEN 1 THEN s2.unit_sales ELSE 0 END) AS prev_unit_sales1
,SUM(CASE u.id WHEN 2 THEN s2.unit_sales ELSE 0 END) AS prev_unit_sales2
,SUM(CASE u.id WHEN 3 THEN s2.unit_sales ELSE 0 END) AS prev_unit_sales3
,SUM(CASE u.id WHEN 4 THEN s2.unit_sales ELSE 0 END) AS prev_unit_sales4
,SUM(CASE u.id WHEN 5 THEN s2.unit_sales ELSE 0 END) AS prev_unit_sales5
,SUM(CASE u.id WHEN 6 THEN s2.unit_sales ELSE 0 END) AS prev_unit_sales6
FROM allStores as s1
INNER JOIN storeCheckRecords AS s2
ON s1.id = s2.store_id
AND s2.datetimesql BETWEEN '2015-06-01' AND '2015-06-30'
AND s1.key_retailer LIKE 'WHOLE FOODS'
AND s1.wf_region LIKE 'Midwest'
INNER JOIN (SELECT 1 AS id
,'855555000032' AS upc
UNION
SELECT 2
,'855555000033'
UNION
SELECT 3
,'855555000034'
UNION
SELECT 4
,'855555000035'
UNION
SELECT 5
,'855555000036'
UNION
SELECT 6
,'855555000038') u
ON u.upc = s2.upc
GROUP BY s1.id) y
ON x.id = y.id
RIGHT JOIN
(SELECT s1.id
,s1.biz_name
,s1.wf_store_name
,s1.e_address
,s1.e_city
,s1.e_state
,s1.e_postal
FROM allStores as s1
WHERE 1
AND s1.key_retailer LIKE 'WHOLE FOODS'
AND s1.wf_region LIKE 'Midwest') z
ON y.id = z.id
ORDER BY wf_store_name ASC
LIMIT 0, 1000
谢谢亨利。我索引了upc,store_id和datetimsql。这减少了一半,但我想进一步降低它。这是解释,我试图在sql中完成所有事情,因为我将结果提供给数据表。
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived22> ALL NULL NULL NULL NULL 54 Using temporary; Using filesort
1 PRIMARY <derived8> ALL NULL NULL NULL NULL 6
1 PRIMARY <derived15> ALL NULL NULL NULL NULL 6
22 DERIVED s1 ALL NULL NULL NULL NULL 64121 Using where
15 DERIVED <derived16> ALL NULL NULL NULL NULL 6 Using temporary; Using filesort
15 DERIVED s2 ref upc,store_id,upc_2,store_id_2,datetimesql,datetime... upc 47 u.upc 2159 Using where
15 DERIVED s1 eq_ref PRIMARY PRIMARY 4 dpalame_foodiecpg.s2.store_id 1 Using where
16 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
17 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
18 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
19 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
20 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
21 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union16,17,18,19,20,21> ALL NULL NULL NULL NULL NULL
8 DERIVED <derived9> ALL NULL NULL NULL NULL 6 Using temporary; Using filesort
8 DERIVED s2 range upc,store_id,upc_2,store_id_2,datetimesql,datetime... datetimesql 3 NULL 1810 Using where; Using join buffer
8 DERIVED s1 eq_ref PRIMARY PRIMARY 4 dpalame_foodiecpg.s2.store_id 1 Using where
9 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
10 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
11 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
12 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
13 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
14 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union9,10,11,12,13,14> ALL NULL NULL NULL NULL NULL
7 UNCACHEABLE SUBQUERY storeCheckRecords index upc,upc_2 datetimesql_3 53 NULL 60452 Using where; Using index
6 UNCACHEABLE SUBQUERY storeCheckRecords index upc,upc_2 datetimesql_3 53 NULL 60452 Using where; Using index
5 UNCACHEABLE SUBQUERY storeCheckRecords index upc,upc_2 datetimesql_3 53 NULL 60452 Using where; Using index
4 UNCACHEABLE SUBQUERY storeCheckRecords index upc,upc_2 datetimesql_3 53 NULL 60452 Using where; Using index
3 UNCACHEABLE SUBQUERY storeCheckRecords index upc,upc_2 datetimesql_3 53 NULL 60452 Using where; Using index
2 UNCACHEABLE SUBQUERY storeCheckRecords index upc,upc_2 datetimesql_3 53 NULL 60452 Using where; Using index
答案 0 :(得分:1)
首先尝试使用内置查询分析器的mysql
http://dev.mysql.com/doc/refman/5.0/en/explain-extended.html
explain [your_query]
然后回来结果。 我的猜测是查询的这一部分
INNER JOIN (SELECT 1 AS id
,'855555000032' AS upc
UNION
SELECT 2
,'855555000033'
UNION
SELECT 3
,'855555000034'
UNION
SELECT 4
,'855555000035'
UNION
SELECT 5
,'855555000036'
UNION
SELECT 6
,'855555000038') u
如果这个子查询是静态的,那么应该更好地创建一个myisam表,并为列id和列upc创建索引
您的查询工作方式,将使用很多临时表。 对于每个子查询,mysql都会创建一个临时表。 如果查询的结果足够大,性能将会降低。
https://dev.mysql.com/doc/refman/5.6/en/subquery-optimization.html
您可以将查询重新设计为单独的视图
另外,慢查询可能是由unindex参数列(在查询中使用的列)
引起的一个方便的性能方法是为针对表使用的查询的每个“where”参数创建一个set column(s)索引,为每个“order”设置一个列的索引
尝试查看表“storeCheckRecords”中的“storeId”和“upc”列是否已作为集合编入索引。
还要查看你的mysql配置中是否设置了“innodb_file_per_table = 1”。 单独的表空间对涉及大表数据的性能有积极影响。 但是,如果之前innodb_file_per_table设置为0,则需要重新创建整个数据库。