2013-02-28 101 views
1

可否请你帮我一个怪物。MySQL查询优化提示需要

你是否看到这个问题?

想要在第二秒以下达到执行时间,有可能吗?

请查询您可能需要了解的数据库结构的任何其他数据。任何提示&招数是欢迎的!

SELECT 
    ORD_CLI.COD_AGE, 
    ORD_CLI_RIGHE.DOC_ID, 
    OFF_CLI.off_cli_id, 
    ORD_CLI_RIGHE.DOC_RIGA_ID, 
    ORD_CLI_RIGHE.COD_ART, 
    ART_PESO.PESO_ART, 
    ORD_CLI.ANNO_DOC, 
    ORD_CLI.NUM_DOC, 
    ORD_CLI.SERIE_DOC, 
    ORD_CLI.DATA_DOC, 
    CF.RAG_SOC_CF, 
    AGENTI.NOME_AGE, 
    ORD_CLI.COD_CF, 
    ORD_CLI.COD_IVA, 
    ORD_CLI.COD_DEP, 
    ORD_CLI_TOT.IMPONIBILE_V1 AS IMPONIBILE_ORDINE, 
    FATT_CLI_TOT.IMPONIBILE_V1 AS IMPONIBILE_FATTURA, 
    ORD_CLI_TOT.IVA_V1, 
    SUM(ART_PESO.PESO_ART) AS weight, 
    SUM(FATT_CLI_RIGHE.QUANT_RIGA) AS quantity, 
    SUM(FATT_CLI_RIGHE.QUANT_RIGA*FATT_CLI_RIGHE.PREZZO_LORDO_VU1) AS sell_price, 
    SUM(FATT_CLI_RIGHE.QUANT_RIGA*DDT_FOR_RIGHE.PREZZO_LORDO_VU1) AS acqisition_price1, 
    SUM(FATT_CLI_RIGHE.QUANT_RIGA*FATT_FOR_RIGHE.PREZZO_LORDO_VU1) AS acqisition_price2, 
    SUM(FATT_CLI_RIGHE.QUANT_RIGA*FATT_CLI_RIGHE_PROVV.IMPORTO_PROVV_VU1) AS agent_reward, 
    SUM(FATT_CLI_RIGHE.QUANT_RIGA*ART_PESO.PESO_ART * 0.13) AS transport_price, 
    SUM(FATT_CLI_RIGHE.QUANT_RIGA*(
      FATT_CLI_RIGHE.PREZZO_LORDO_VU1 
     - COALESCE(DDT_FOR_RIGHE.PREZZO_LORDO_VU1, 0) 
     - COALESCE(FATT_FOR_RIGHE.PREZZO_LORDO_VU1, 0) 
     - COALESCE(FATT_CLI_RIGHE_PROVV.IMPORTO_PROVV_VU1, 0) 
     - COALESCE(ART_PESO.PESO_ART, 0) * 0.13 
    )) AS net_earning, 
    OFF_CLI.stima_prezzo_acquisto, 
    OFF_CLI.stima_prezzo_trasporto, 
    OFF_CLI.stima_provvigioni_agenti, 
    OFF_CLI.stima_utile 

FROM ORD_CLI 

INNER JOIN ORD_CLI_RIGHE   
    ON ORD_CLI_RIGHE.DOC_ID = ORD_CLI.DOC_ID 

LEFT JOIN ORD_CLI_RIGHE_SPEC 
    ON ORD_CLI_RIGHE.DOC_RIGA_ID = ORD_CLI_RIGHE_SPEC.DOC_RIGA_ID 

INNER JOIN ART_PESO 
    ON ART_PESO.COD_ART = ORD_CLI_RIGHE.COD_ART 

INNER JOIN ORD_CLI_TOT 
    ON ORD_CLI.DOC_ID = ORD_CLI_TOT.DOC_ID 

INNER JOIN AGENTI 
    ON AGENTI.COD_AGE = ORD_CLI.COD_AGE 

INNER JOIN CF 
    ON CF.COD_CF = ORD_CLI.COD_CF 

LEFT JOIN FATT_CLI_RIGHE_SPEC 
    ON ORD_CLI_RIGHE.DOC_RIGA_ID = FATT_CLI_RIGHE_SPEC.ORD_RIGA_ID 

LEFT JOIN FATT_CLI_RIGHE   
    ON FATT_CLI_RIGHE.DOC_RIGA_ID = FATT_CLI_RIGHE_SPEC.DOC_RIGA_ID 

LEFT JOIN FATT_CLI_TOT 
    ON FATT_CLI_RIGHE.DOC_ID = FATT_CLI_TOT.DOC_ID 

LEFT JOIN FATT_CLI_RIGHE_PROVV 
    ON FATT_CLI_RIGHE_PROVV.DOC_RIGA_ID = FATT_CLI_RIGHE_SPEC.DOC_RIGA_ID 

LEFT JOIN FATT_CLI_RIGHE_LOTTI 
    ON FATT_CLI_RIGHE_LOTTI.DOC_RIGA_ID = FATT_CLI_RIGHE_SPEC.DOC_RIGA_ID 

LEFT JOIN DDT_FOR_RIGHE_LOTTI 
    ON DDT_FOR_RIGHE_LOTTI.COD_LOT = FATT_CLI_RIGHE_LOTTI.COD_LOT 

LEFT JOIN DDT_FOR_RIGHE   
    ON DDT_FOR_RIGHE.DOC_RIGA_ID = DDT_FOR_RIGHE_LOTTI.DOC_RIGA_ID 

LEFT JOIN FATT_FOR_RIGHE   
    ON FATT_FOR_RIGHE.DOC_RIGA_ID = FATT_CLI_RIGHE_LOTTI.COD_LOT 

LEFT JOIN OFF_CLI_RIGHE 
    ON OFF_CLI_RIGHE.DOC_RIGA_ID = ORD_CLI_RIGHE_SPEC.OFF_RIGA_ID 

LEFT JOIN OFF_CLI 
    ON OFF_CLI.DOC_ID = OFF_CLI_RIGHE.DOC_ID 

WHERE 
    ORD_CLI.COD_BUSN_UN='P' 
AND OFF_CLI_RIGHE.DOC_RIGA_ID IS NOT NULL 

AND ORD_CLI.DATA_DOC >= '2012-11-29' 
AND ORD_CLI.DATA_DOC <= '2013-02-28' 
GROUP BY ORD_CLI.DOC_ID 
ORDER BY ORD_CLI.DATA_DOC 
DESC LIMIT 30 OFFSET 0 

执行的时间

Showing rows 0 - 29 (30 total, Query took 6.3458 sec) 

解释查询

+----+-------------+----------------------+--------+-----------------------------------------------------------------------------+----------------------------------+---------+--------------------------------------------+------+----------+----------------------------------------------+ 
| id | select_type | table    | type | possible_keys                | key        | key_len | ref          | rows | filtered | Extra          | 
+----+-------------+----------------------+--------+-----------------------------------------------------------------------------+----------------------------------+---------+--------------------------------------------+------+----------+----------------------------------------------+ 
| 1 | SIMPLE  | ORD_CLI    | range | PRIMARY,ORD_CLI_DATA_DOC,ORD_CLI_COD_CF,ORD_CLI_COD_BUSN_UN,ORD_CLI_COD_AGE | ORD_CLI_DATA_DOC     | 4  | NULL       | 3728 | 100.00 | Using where; Using temporary; Using filesort | 
| 1 | SIMPLE  | AGENTI    | eq_ref | PRIMARY                  | PRIMARY       | 38  | ORD_CLI.COD_AGE     | 1 | 100.00 | Using where         | 
| 1 | SIMPLE  | CF     | eq_ref | PRIMARY                  | PRIMARY       | 38  | ORD_CLI.COD_CF     | 1 | 100.00 |            | 
| 1 | SIMPLE  | ORD_CLI_TOT   | eq_ref | PRIMARY                  | PRIMARY       | 62  | ORD_CLI.DOC_ID     | 1 | 100.00 |            | 
| 1 | SIMPLE  | ORD_CLI_RIGHE  | ref | PRIMARY,ORD_CLI_RIGHE_DOC_ID,ORD_CLI_RIGHE_COD_ART       | ORD_CLI_RIGHE_DOC_ID    | 62  | ORD_CLI_TOT.DOC_ID    | 2 | 100.00 | Using where         | 
| 1 | SIMPLE  | ART_PESO    | eq_ref | PRIMARY                  | PRIMARY       | 92  | ORD_CLI_RIGHE.COD_ART   | 1 | 100.00 |            | 
| 1 | SIMPLE  | ORD_CLI_RIGHE_SPEC | eq_ref | PRIMARY,ORD_CLI_RIGHE_SPEC_OFF_RIGA_ID          | PRIMARY       | 92  | ORD_CLI_RIGHE.DOC_RIGA_ID  | 1 | 100.00 | Using where         | 
| 1 | SIMPLE  | OFF_CLI_RIGHE  | ref | DOC_RIGA_ID                 | DOC_RIGA_ID      | 92  | ORD_CLI_RIGHE_SPEC.OFF_RIGA_ID | 1 | 100.00 | Using where         | 
| 1 | SIMPLE  | OFF_CLI    | ref | DOC_ID                  | DOC_ID       | 63  | OFF_CLI_RIGHE.DOC_ID    | 1 | 100.00 |            | 
| 1 | SIMPLE  | FATT_CLI_RIGHE_SPEC | ref | FATT_CLI_RIGHE_SPEC_ORD_RIGA_ID            | FATT_CLI_RIGHE_SPEC_ORD_RIGA_ID | 93  | ORD_CLI_RIGHE.DOC_RIGA_ID  | 1 | 100.00 | Using index         | 
| 1 | SIMPLE  | FATT_CLI_RIGHE  | eq_ref | PRIMARY                  | PRIMARY       | 92  | FATT_CLI_RIGHE_SPEC.DOC_RIGA_ID | 1 | 100.00 |            | 
| 1 | SIMPLE  | FATT_CLI_TOT   | eq_ref | PRIMARY                  | PRIMARY       | 62  | FATT_CLI_RIGHE.DOC_ID   | 1 | 100.00 |            | 
| 1 | SIMPLE  | FATT_CLI_RIGHE_PROVV | ref | FATT_CLI_RIGHE_PROVV_DOC_RIGA_ID           | FATT_CLI_RIGHE_PROVV_DOC_RIGA_ID | 92  | FATT_CLI_RIGHE_SPEC.DOC_RIGA_ID | 1 | 100.00 |            | 
| 1 | SIMPLE  | FATT_CLI_RIGHE_LOTTI | ref | FATT_CLI_RIGHE_LOTTI_DOC_RIGA_ID           | FATT_CLI_RIGHE_LOTTI_DOC_RIGA_ID | 92  | FATT_CLI_RIGHE_SPEC.DOC_RIGA_ID | 1 | 100.00 |            | 
| 1 | SIMPLE  | DDT_FOR_RIGHE_LOTTI | ref | DDT_FOR_RIGHE_LOTTI_COD_LOT             | DDT_FOR_RIGHE_LOTTI_COD_LOT  | 92  | FATT_CLI_RIGHE_LOTTI.COD_LOT | 1 | 100.00 |            | 
| 1 | SIMPLE  | DDT_FOR_RIGHE  | eq_ref | PRIMARY                  | PRIMARY       | 92  | DDT_FOR_RIGHE_LOTTI.DOC_RIGA_ID | 1 | 100.00 |            | 
| 1 | SIMPLE  | FATT_FOR_RIGHE  | eq_ref | PRIMARY                  | PRIMARY       | 92  | FATT_CLI_RIGHE_LOTTI.COD_LOT | 1 | 100.00 |            | 
+----+-------------+----------------------+--------+-----------------------------------------------------------------------------+----------------------------------+---------+--------------------------------------------+------+----------+----------------------------------------------+ 

以下的是查询后excatly被执行

Handler_commit, 2 
Handler_delete, 0 
Handler_discover, 0 
Handler_prepare, 0 
Handler_read_first, 0 
Handler_read_key, 421001 
Handler_read_last, 0 
Handler_read_next, 240344 
Handler_read_prev, 0 
Handler_read_rnd, 30 
Handler_read_rnd_next, 2412 
Handler_rollback, 0 
Handler_savepoint, 0 
Handler_savepoint_rollback, 0 
Handler_update, 31846 
Handler_write, 2409 

数据的show status like 'Handler%'结果基部结构:https://gist.github.com/moiseevigor/4988fc8868f92643c9fb

EDIT 1

创建索引的后

ALTER TABLE `TCross5_NP`.`ORD_CLI` 
ADD INDEX `ORD_CLI_MULTI` (`COD_BUSN_UN` ASC, `DATA_DOC` ASC, `DOC_ID` ASC) ; 

执行时间去下降2倍,但仍击中ORD_CLI_MULTI索引

+1

可以将LEFT JOIN OFF_CLI_RIGHE的连接更改为INNER JOIN(因为您在WHERE子句中检查该表的列为非null)。你可以发布表格声明:因为你的一些密钥看起来只是ID字段,似乎很长。 – Kickstart 2013-02-28 14:46:19

+0

是的,感谢关于左连接的提示!就在一会儿我会提取一个文件,这太可怕了,所以没有把它放在这里;)它是由OmnisStudio自动生成的结构。我确认这些ID是复合的。 – Igor 2013-02-28 14:54:41

回答

1

首先,(并且具有在许多其他类似的查询中,您似乎正在处理大量的“查找”次表引用),将查询的开始更改为

SELECT STRAIGHT_JOIN 

指示引擎按照您列出的确切顺序运行查询。这将防止它尝试使用查找表作为主要考虑因素,并尝试使用后端语言或结束语来获取数据。有时候工作得很好,其他时间(很少以我的经验)妨碍表现。

接下来,由于您正在查找“AND OFF_CLI_RIGHE.DOC_RIGA_ID IS NOT NULL”,因此加入时我会将您的左连接更改为INNER JOIN。

INNER JOIN ORD_CLI_RIGHE_SPEC 
    ON ORD_CLI_RIGHE.DOC_RIGA_ID = ORD_CLI_RIGHE_SPEC.DOC_RIGA_ID 

    INNER JOIN OFF_CLI_RIGHE 
     ON ORD_CLI_RIGHE_SPEC.OFF_RIGA_ID = OFF_CLI_RIGHE.DOC_RIGA_ID 

因此消除了WHERE子句中的“AND ... is null”。

最后,我想有一个指标是可以优化 对于查询多个零件...

CREATE index MultipleParts on ORD_CLI (COD_BUSN_UN, DATA_DOC, DOC_ID); 

的多指数将帮助WHERE,GROUP BY和ORDER BY查询。

+0

谢谢你会尝试你的提示,并会发布更新! 'STRAIGHT_JOIN'已经尝试过并且在性能上获得相同的结果。我很担心'ORD_CLI_DATA_DOC'索引看起来过热,您怎么看? 'INNER JOIN'不会产生任何区别,但无论如何它都更加正确。 – Igor 2013-02-28 15:04:20

+0

我想'filesort'和/或'temparary'是不可能消除的?你能告诉这件事吗?谢谢。 – Igor 2013-02-28 16:36:17