2015-08-08 194 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