2013-03-19 159 views
1

你好,我試圖運行這個選擇語句使用這個查詢,它需要2個多小時才能運行。我已經設置了所有的索引是正確的。但是,它仍然需要永遠存在的東西我缺少或更有效的方式將表連接在一起,這將加快此查詢?Mysql加入查詢優化

我有索引設置爲所有項目被連接在一起,他們是相同的長度和數據類型。

SELECT 
    p.sap_article_id, 
    p.numeric_line_code, 
    p.uag_linecode, 
    p.uag_partnum, 
    p.part_description, 
    p.jobber_price, 
    p.jobber_core, 
    p.discount1, 
    p.discount2, 
    p.uom, 
    p.product_category, 
    w.as400_warehouse, 
    w.atp_qty, 
    p.updated, 
    t.regular_discount  
FROM part p 
     LEFT JOIN tabjbmaw t ON t.accountnum  = '73050' 
          AND p.numeric_line_code = t.numeric_line_code 
          AND p.sub_code   = t.sub_code  
     JOIN warehouse w ON w.sap_article_id = p.sap_article_id; 

+----+-------------+-----------+------+--------------------------------------------------+-----------------------+---------+----------------------------------+--------+-------------+ 
| id | select_type | table  | type | possible_keys         | key     | key_len | ref        | rows | Extra  | 
+----+-------------+-----------+------+--------------------------------------------------+-----------------------+---------+----------------------------------+--------+-------------+ 
| 1 | SIMPLE  | part  | ALL | PRIMARY,sap_article,part_sap_article_id_fk  | NULL     | NULL | NULL        | 389309 |    | 
| 1 | SIMPLE  | warehouse | ref | article           | article    | 130  | inventory.part.sap_article_id |  5 | Using where | 
| 1 | SIMPLE  | tabjbmaw | ref | numeric_line_code_idx,subcode_idx,accountnum_idx | numeric_line_code_idx | 5  | inventory.part.numeric_line_code |  19 |    | 
+----+-------------+-----------+------+--------------------------------------------------+-----------------------+---------+----------------------------------+--------+-------------+ 

謝謝您的幫助

+-----------------------------+--------------+------+-----+---------------------+-----------------------------+ 
| Field      | Type   | Null | Key | Default    | Extra      | 
+-----------------------------+--------------+------+-----+---------------------+-----------------------------+ 
| sap_article_id    | varchar(24) | NO | PRI |      |        | 
| sap_brand_id    | varchar(20) | NO |  | NULL    |        | 
| uag_partnum     | varchar(20) | NO | MUL | NULL    |        | 
| uag_linecode    | varchar(5) | NO | MUL | NULL    |        | 
| cag_partnum     | varchar(20) | NO | MUL | NULL    |        | 
| cag_linecode    | varchar(5) | NO |  | NULL    |        | 
| product_category_legacy  | varchar(20) | NO |  | NULL    |        | 
| part_description   | varchar(128) | NO |  | NULL    |        | 
| abc_indicator    | varchar(8) | NO |  | NULL    |        | 
| pack_code     | varchar(8) | NO |  | NULL    |        | 
| case_qty     | int(11)  | NO |  | NULL    |        | 
| per_car_qty     | int(11)  | NO |  | NULL    |        | 
| uom       | varchar(6) | NO |  | NULL    |        | 
| upc_code     | varchar(128) | NO |  | NULL    |        | 
| jobber_price    | float(14,4) | YES |  | NULL    |        | 
| jobber_core     | float(14,4) | YES |  | NULL    |        | 
| date_last_price_change  | timestamp | NO |  | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | 
| weight      | float(14,4) | YES |  | NULL    |        | 
| weight_unit     | varchar(6) | NO |  | NULL    |        | 
| dimension_type    | varchar(6) | NO |  | NULL    |        | 
| length      | float(14,4) | YES |  | NULL    |        | 
| width      | float(14,4) | YES |  | NULL    |        | 
| height      | float(14,4) | YES |  | NULL    |        | 
| updated      | tinyint(1) | NO |  | 0     |        | 
| superseded_sap_article_id | varchar(24) | YES |  | NULL    |        | 
| last_updated    | timestamp | NO |  | 0000-00-00 00:00:00 |        | 
| hour_updated    | int(11)  | YES |  | NULL    |        | 
| discount1     | float  | YES |  | NULL    |        | 
| discount2     | float  | YES |  | NULL    |        | 
| product_category   | varchar(3) | YES |  | NULL    |        | 
| superseded_part_number  | varchar(20) | YES |  | NULL    |        | 
| sub_code     | varchar(3) | YES | MUL | NULL    |        | 
| date_effective_price_change | date   | YES |  | NULL    |        | 
| numeric_line_code   | varchar(3) | YES | MUL | NULL    |        | 
| list      | float  | YES |  | NULL    |        | 
+-----------------------------+--------------+------+-----+---------------------+-----------------------------+ 
+0

什麼樣的JOIN你要對倉庫表?您是否嘗試將'73050'= tabjbmaw.accountnum移至WHERE子句? – Melanie 2013-03-19 19:24:24

+2

不,如果從LEFT JOIN部分刪除該語句將是一個可怕的錯誤。首先,優化器在JOIN和WHERE子句中工作相同,其次插入到WHERE子句中的篩選器使關聯的表INNER加入,在這種情況下這是不正確的,因爲他希望進行OUTER連接。 – Sebas 2013-03-19 19:28:50

+0

我們需要空值返回折扣不存在,所以移動到最後並沒有幫助我們。它需要留在那裏 – user1863457 2013-03-19 19:29:38

回答

1

我已經建立了對所有項目指標結合在一起

是的,但我從索引名稱猜測每個索引只有一個字段。

讓我們看看描述中的幾列。

| table  | possible_keys         | key     
+-----------+--------------------------------------------------+---------------- 
| part  | PRIMARY,sap_article,part_sap_article_id_fk  | NULL     
| warehouse | article           | article    
| tabjbmaw | numeric_line_code_idx,subcode_idx,accountnum_idx | numeric_line_code_idx 

它可以使用索引來numeric_line_code,子碼和accountnum,但只有每個字段的一個三項指標,並具有所有的字段沒有索引。您正在使優化器選擇一個字段索引中的一個,而不是提供可用於所有三個字段的索引。

使用三個字段numeric_line_code,subcode和accountnum在表tabjbmaw上添加索引。

+0

我現在正在測試這個 – user1863457 2013-03-19 19:41:29

+0

添加新索引後速度有多快? – 2013-03-19 19:50:27

0

擴展@Sebas的答案,你應該首先選擇tabjbmaw:

SELECT 
    p.sap_article_id, 
    p.numeric_line_code, 
    p.uag_linecode, 
    p.uag_partnum, 
    p.part_description, 
    p.jobber_price, 
    p.jobber_core, 
    p.discount1, 
    p.discount2, 
    p.uom, 
    p.product_category, 
    w.as400_warehouse, 
    w.atp_qty, 
    p.updated, 
    t.regular_discount  
FROM tabjbmaw t 
     LEFT JOIN parts p ON p.numeric_line_code = t.numeric_line_code 
          AND p.sub_code  = t.sub_code  
     JOIN warehouse w ON w.sap_article_id = p.sap_article_id 
WHERE t.accountnum = '73050' 
; 
+0

如果是這樣,那將是一個非常糟糕的功能錯誤:D但我同意你的看起來更合理 – Sebas 2013-03-19 19:42:44

+0

這當然會給出不同的結果,因爲它會錯過任何與tabjbmaw不匹配的部分。此外,它還包含不匹配的tabjbmaw記錄,當它不是之前結果的一部分時。也許將LEFT JOIN改爲INNER JOIN會刪除缺少的部分,但不會引入缺少的tabjbmaw記錄。 – 2013-03-19 19:45:18

+0

這不會產生與原始查詢相同的結果。這裏的'LEFT'表是'tabjbmaw',而不是原始查詢中的'parts'。另外,我不認爲這會有很大的區別。它仍然需要對'parts'進行全表掃描。 – 2013-03-19 19:46:03

0

您可以嘗試將您的左連接放入SELECT部分​​作爲子選擇。這可能會加快一點。

像這樣:

SELECT 
    p.sap_article_id, 
    p.numeric_line_code, 
    p.uag_linecode, 
    p.uag_partnum, 
    p.part_description, 
    p.jobber_price, 
    p.jobber_core, 
    p.discount1, 
    p.discount2, 
    p.uom, 
    p.product_category, 
    w.as400_warehouse, 
    w.atp_qty, 
    p.updated, 
    (SELECT t.regular_discount FROM tabjbmaw t WHERE t.accountnum = '73050' AND p.numeric_line_code = t.numeric_line_code AND p.sub_code = t.sub_code LIMIT 1)  
FROM 
    part p 
    JOIN warehouse w ON w.sap_article_id = p.sap_article_id; 
+0

這隻允許來自'tabjbmaw'的一個結果,但原始查詢允許多個。另外,'JOIN'幾乎總是比子查詢更快。 – 2013-03-19 19:57:12