2015-02-23 64 views
0

我需要優化以下查詢,最多需要10分鐘才能運行。 執行解釋它似乎在「table_3」表的所有350815行上運行,其他所有行都運行1。 通用規則放置索引的方式?我應該考慮使用多維索引嗎?在JOINS,WHERE或GROUP BY中,我應該在哪裏使用它們,如果我沒有記錯的話,應該有一個層次結構。另外如果我有1行的所有表格,但一個(在說明表的行列中)我怎麼能優化通常我的優化包括結束所有列,但只有一行,但一個。 所有表平均從100k到1000k +行。每桌mysql大查詢優化

CREATE TABLE datab1.sku_performance 
SELECT 
     table1.sku, 
     CONCAT(table1.sku,' ',table1.fk_container) as sku_container, 
     table1.price as price, 
     SUM(CASE WHEN (table1.fk_table1_status = 82 
        OR table1.fk_table1_status = 119 
        OR table1.fk_table1_status = 124 
        OR table1.fk_table1_status = 141 
        OR table1.fk_table1_status = 131) THEN 1 ELSE 0 END) 
      /COUNT(DISTINCT id_catalog_school_class) as qty_returned, 
     SUM(CASE WHEN (table1.fk_table1_status In (23,13,44,65,6,75,8,171,12,166)) 
       THEN 1 ELSE 0 END) 
      /COUNT(DISTINCT id_catalog_school_class) as qt, 
     container.id_container as container_id, 
     container.idden as container_idden, 
     container.delivery_badge, 
     catalog_school.id_catalog_school, 
     LEFT(catalog_school.flight_fair,2) as departing_country, 
     catalog_school.weight, 
     catalog_school.flight_type, 
     catalog_school.price, 
     table_3.id_table_3, 
     table_3.fk_catalog_brand, 
     MAX(LEFT(table_3.note,3)) AS supplier, 
     GROUP_CONCAT(product_number, ' by ',FORMAT(catalog_school_class.quantity,0) 
      ORDER BY product_number ASC SEPARATOR ' + ') as supplier_prod, 
     Sum(distinct(catalog_school_class.purch_pri * catalog_school_class.quantity)) AS final_purch_pri, 
     catalog_groupp.idden as supplier_idden, 
     catalog_category_details.id_catalog_category, 
     catalog_category_details.cat1 as product_cat1, 
     catalog_category_details.cat2 as product_cat2, 
     COUNT(distinct catalog_school_class.id_catalog_school_class) as setinfo, 
     datab1.pageviewgrouped.pv as page_views, 
     Sum(distinct(catalog_school_class.purch_pri * catalog_school_class.quantity)) AS purch_pri, 
     container_has_table_3.position, 
     max(table1.created_at) as last_order_date 
    FROM 
     table1 
     LEFT JOIN container 
      ON table1.fk_container = container.id_container 
     LEFT JOIN catalog_school 
      ON table1.sku = catalog_school.sku 
      LEFT JOIN table_3 
       ON catalog_school.fk_table_3 = table_3.id_table_3 
       LEFT JOIN container_has_table_3 
        ON table_3.id_table_3 = container_has_table_3.fk_table_3 
       LEFT JOIN datab1.pageviewgrouped 
        on table_3.id_table_3 = datab1.pageviewgrouped.url 
        LEFT JOIN datab1.catalog_category_details 
        ON datab1.catalog_category_details.id_catalog_category = table_3_has_catalog_minority.fk_catalog_category 
       LEFT JOIN catalog_groupp 
        ON table_3.fk_catalog_groupp = catalog_groupp.id_catalog_groupp 
       LEFT JOIN table_3_has_catalog_minority 
        ON table_3.id_table_3 = table_3_has_catalog_minority.fk_table_3 
      LEFT JOIN catalog_school_class 
       ON catalog_school.id_catalog_school = catalog_school_class.fk_catalog_school 
    WHERE 
      table_3.status_ok = 1 
     AND catalog_school.status = 'active' 
     AND table_3_has_catalog_minority.is_primary = '1' 
    GROUP BY 
     table1.sku, 
     table1.fk_container; 

enter image description here

行:

.table1 960096 to 1.3mn rows 
.container 9275 to 13000 rows 
.catalog_school 709970 to 1 mn rows 
.table_3 709970 to 1 mn rows 
.container_has_table_3 709970 to 1 mn rows 
.pageviewgrouped 500000 rows 
.catalog_school_class 709970 to 1 mn rows 
.catalog_groupp 3000 rows 
.table_3_has_catalog_minority 709970 to 1 mn rows 
.catalog_category_details 659 rows 
+1

要優化查詢**,我們需要查看錶和索引定義**以及每個表的行數。也許你的表格定義不好。也許索引沒有正確創建。也許你沒有一個你認爲你做過的那個專欄的索引。沒有看到表和索引定義,我們不能說。我們還需要行計數,因爲這會大大影響查詢優化。如果你知道如何做一個'EXPLAIN'或者得到一個執行計劃,那就把結果也放在問題中。如果您沒有索引,請儘快訪問http://use-the-index-luke.com。 – 2015-02-23 19:57:40

+0

這裏發生了什麼? '... WHERE table_3.status_ok = AND ...'看起來有些東西丟失了。 – Turophile 2015-02-23 21:40:07

+0

當您爲每個表格提供「SHOW CREATE TABLE」時,請告訴我們每個表格有多大。 – 2015-02-25 05:22:33

回答

0

太多投入一個評論,所以我會在這裏補充和調整後爲可能需要的...你已經離開JOIN到處都有,但是WHERE子句是從Table_3,Catalog_School和Table_3_has_catalog_minority中具體限定的字段。這默認情況下將它們更改爲INNER JOIN。

對於您的where子句

WHERE 
      table_3.status_ok = 1 
     AND catalog_school.status = 'active' 
     AND table_3_has_catalog_minority.is_primary = '1' 

哪個表/列將具有基於這些標準的最小的結果。例如:Table_3.Status_ok = 1可能有500k記錄,但是table_3_has_catalog_minority.is_primary可能只有65k,而catalog_school.status ='active'可能有430k。

此外,您的某些列不符合他們來自的表格。你能否確認...如「id_catalog_school_class」和「product_number」

有時候,改變表的順序,熟悉數據構成,在MySQL中增加一個「STRAIGHT_JOIN」關鍵字可以提高性能。這是我過去曾與政府合同和贈款數據庫合作,擁有超過2000萬條記錄並加入了大約15個查詢表。它從掛起服務器到在不到2小時內完成查詢。考慮到我正在處理的數據量,那實際上是一個好時機。

解剖這個東西后,我爲了可讀性重新構造了一些,爲表引用添加了別名,並改變了查詢的順序並提供了一些建議的索引。爲了幫助查詢,我嘗試將Catalog_School表移到第一個位置並添加了STRAIGHT_JOIN。該索引基於STATUS首先匹配WHERE子句,然後我將SKU作爲GROUP BY的第一個元素包含在內,然後將其他列用於連接到後續表。通過在索引中包含這些列,它可以限定連接,而無需轉到原始數據。

通過將組更改爲Catalog_School.SKU而不是table_1.SKU,可以使用catalog_school中的索引來幫助優化該組。自從catalog_school.sku = table_1.sku加入後,它的值相同。我還爲table_1和table_3添加了索引引用,這些建議也是建議 - 再次,爲了預先限定連接而不必訪問表的原始數據頁。

我想知道你的數據的最終性能(好或壞)。

TABLE    INDEX ON... 
catalog_school (status, sku, fk_table_3, id_catalog_school) 
table_1   (sku, fk_container)  
table_3   (id_table_3, status_ok, fk_catalog_groupp) 

SELECT STRAIGHT_JOIN 
     CS.sku, 
     CONCAT(CS.sku,' ',T1.fk_container) as sku_container, 
     T1.price as price, 
     SUM(CASE WHEN (T1.fk_table1_status IN (82, 119, 124, 141, 131) 
       THEN 1 ELSE 0 END) 
      /COUNT(DISTINCT CSC.id_catalog_school_class) as qty_returned, 
     SUM(CASE WHEN (T1.fk_table1_status In (23,13,44,65,6,75,8,171,12,166)) 
       THEN 1 ELSE 0 END) 
      /COUNT(DISTINCT CSC.id_catalog_school_class) as qt, 
     CS.id_catalog_school, 
     LEFT(CS.flight_fair,2) as departing_country, 
     CS.weight, 
     CS.flight_type, 
     CS.price, 
     T3.id_table_3, 
     T3.fk_catalog_brand, 
     MAX(LEFT(T3.note,3)) AS supplier, 
     C.id_container as container_id, 
     C.idden as container_idden, 
     C.delivery_badge, 
     GROUP_CONCAT(product_number, ' by ',FORMAT(CSC.quantity,0) 
      ORDER BY product_number ASC SEPARATOR ' + ') as supplier_prod, 
     Sum(distinct(CSC.purch_pri * CSC.quantity)) AS final_purch_pri, 
     CGP.idden as supplier_idden, 
     CCD.id_catalog_category, 
     CCD.cat1 as product_cat1, 
     CCD.cat2 as product_cat2, 
     COUNT(distinct CSC.id_catalog_school_class) as setinfo, 
     PVG.pv as page_views, 
     Sum(distinct(CSC.purch_pri * CSC.quantity)) AS purch_pri, 
     CHT3.position, 
     max(T1.created_at) as last_order_date 
    FROM 
     catalog_school CS 

     JOIN table1 T1 
      ON CS.sku = T1.sku 
      LEFT JOIN container C 
       ON T1.fk_container = C.id_container 

     LEFT JOIN catalog_school_class CSC 
      ON CS.id_catalog_school = CSC.fk_catalog_school 

     JOIN table_3 T3 
      ON CS.fk_table_3 = T3.id_table_3 
      JOIN table_3_has_catalog_minority T3HCM 
       ON T3.id_table_3 = T3HCM.fk_table_3 
       LEFT JOIN datab1.catalog_category_details CCD 
        ON T3HCM.fk_catalog_category = CCD.id_catalog_category 

      LEFT JOIN container_has_table_3 CHT3 
       ON T3.id_table_3 = CHT3.fk_table_3 

      LEFT JOIN datab1.pageviewgrouped PVG 
       on T3.id_table_3 = PVG.url 

      LEFT JOIN catalog_groupp CGP 
       ON T3.fk_catalog_groupp = CGP.id_catalog_groupp 
    WHERE 
      CS.status = 'active' 
     AND T3.status_ok = 1 
     AND T3HCM.is_primary = '1' 
    GROUP BY 
     CS.sku, 
     T1.fk_container; 
+0

@MarkoC,很高興這個答案似乎已經工作/幫助...但是想知道基於這個輸入/建議對查詢的最後時間進行了優化......它也可以幫助其他人想知道哪些技術已經工作,太有效了。 – DRapp 2015-03-08 03:37:24

+0

再次感謝,當我完成我的優化後,我會發布時間!目前我正在處理它,並試圖進一步! – 2015-03-17 14:23:21