2015-08-08 260 views
-1

反正是有优化这个查询?优化MYSQL子查询

我知道它是在子查询得到举起:

(SELECT IFNULL(max(datetimesql),'NS') FROM storeCheckRecords 
    WHERE [email protected] AND upc=855555000032) 

没有它在不到1秒的执行IFNULL子查询。这个例子用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 [email protected] AND upc=855555000032) 
    ) as diff_unit_sales1 
    ,IFNULL(unit_sales2 - prev_unit_sales2, (SELECT IFNULL(max(datetimesql),'NS') 
              FROM storeCheckRecords 
              WHERE [email protected] AND upc=855555000033) 
    ) as diff_unit_sales2 
    ,IFNULL(unit_sales3 - prev_unit_sales3, (SELECT IFNULL(max(datetimesql),'NS') 
              FROM storeCheckRecords 
              WHERE [email protected] AND upc=855555000034) 
    ) as diff_unit_sales3 
    ,IFNULL(unit_sales4 - prev_unit_sales4, (SELECT IFNULL(max(datetimesql),'NS') 
              FROM storeCheckRecords 
              WHERE [email protected] AND upc=855555000035) 
    ) as diff_unit_sales4 
    ,IFNULL(unit_sales5 - prev_unit_sales5, (SELECT IFNULL(max(datetimesql),'NS') 
              FROM storeCheckRecords 
              WHERE [email protected] AND upc=855555000036) 
    ) as diff_unit_sales5 
    ,IFNULL(unit_sales6 - prev_unit_sales6, (SELECT IFNULL(max(datetimesql),'NS') 
              FROM storeCheckRecords 
              WHERE [email protected] 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

我想使这一水平滚动条上可能会有帮助。谁想要编辑? – Drew

+0

对于恰到好处的问题http://sqlformat.org/ – Mihai

+0

THX米哈伊,有所帮助。然后再次也许还原比较好:>然后我把它变成崇高和被吓坏了 – Drew

回答

1

首先尝试使用内置的查询分析器

http://dev.mysql.com/doc/refman/5.0/en/explain-extended.html

explain [your_query] 

MySQL和回来与结果。 我的猜测是查询

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”参数创建设置列索引,针对每个“订单”设置列索引

尝试查看表中的“storeId”和“upc”列“storeCh eckRecords“已被编入索引。

也看到,如果你有“innodb_file_per_table = 1”,在你的MySQL配置设置。在涉及大表数据的情况下,单独的表空间会对性能产生积极影响。 但是,如果innodb_file_per_table之前设置为0,则需要重新创建整个数据库。

+0

谢谢亨利。我索引upc,store_id和datetimsql。这削减了一半,但我想进一步降低。这里是解释,我想在sql中完成所有事情,因为我将结果提供给数据表。 – Damon

+0

mysql查询分析器对你的查询说了什么? –

+0

我将它添加到问题中,因为它很长。 – Damon