2014-02-12 99 views
0

這個查詢極其緩慢花費大量的時間來執行:的MySQL更新查詢使用索引

UPDATE facturacion2013_full a, facturacion2013_contadores b SET a.B1 = b.consumo WHERE a.contador = b.contador 

這裏我表結構:

CREATE TABLE IF NOT EXISTS `facturacion2013_full` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `poliza` int(8) NOT NULL, 
    `contador` varchar(12) NOT NULL, 
    `B1` int(11) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `fields_idx` (`contador`), 
    KEY `fields_iidx2` (`poliza`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ; 

CREATE TABLE IF NOT EXISTS `facturacion2013_contadores` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `poliza` int(8) NOT NULL, 
    `contador` varchar(12) NOT NULL, 
    `consumo` int(8) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `idx1` (`contador`), 
    KEY `idx2` (`poliza`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ; 

我試着改變小事情,沒有運氣。還嘗試改變一些參數,如緩衝區大小,max_heap_table_size的mysql配置...我錯過了什麼?提前致謝!

+0

首先使用'EXPLAIN'找出數據庫正在做什麼。 – 2014-02-12 19:16:11

+0

我安裝了5.1版本我無法使用EXPLAIN UPDATE ... –

回答

1

我在MySQL 5.6上測試了這個,它支持EXPLAIN for UPDATE語句。

mysql> explain UPDATE facturacion2013_full a JOIN facturacion2013_contadores b 
    ON a.contador = b.contador 
    SET a.B1 = b.consumo\G 

*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: a 
     type: ALL 
possible_keys: fields_idx 
      key: NULL 
     key_len: NULL 
      ref: NULL 
     rows: 1 
     Extra: NULL 
*************************** 2. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: b 
     type: ref 
possible_keys: idx1 
      key: idx1 
     key_len: 14 
      ref: test.a.contador 
     rows: 1 
     Extra: NULL 

您可以看到它讀取表a的所有行。我從表名中可以看出a中的行數多於b中的行數。因此它讀取a中的所有行,無論b中是否有匹配的行。

也許這會節省MySQL一些工作來重新排序表,以便它讀取較小表的所有行,並且只讀取較大表中的行。

mysql> explain UPDATE facturacion2013_contadores b JOIN facturacion2013_full a 
    ON a.contador = b.contador 
    SET a.B1 = b.consumo\G 

*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: b 
     type: ALL 
possible_keys: idx1 
      key: NULL 
     key_len: NULL 
      ref: NULL 
     rows: 1 
     Extra: NULL 
*************************** 2. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: a 
     type: ref 
possible_keys: fields_idx 
      key: fields_idx 
     key_len: 14 
      ref: test.b.contador 
     rows: 1 
     Extra: NULL 

的順序不應該的事情,因爲優化器應該能夠通過自身重新排序表,閱讀他們在一個更好的訂單,如果必要的。但是有時優化器並不像我們想的那樣聰明。或者它甚至可能會重新排列表格,導致查詢變得更糟。您正在使用MySQL 5.1,它相當陳舊(實際上其支持的生命週期截止於2013年12月31日),所以優化器可能不如新版本。

您可以覆蓋優化和強制表在你給他們在查詢的順序讀取,使用STRAIGHT_JOIN關鍵字:

mysql> explain UPDATE facturacion2013_contadores b STRAIGHT_JOIN facturacion2013_full a 
    ON a.contador = b.contador 
    SET a.B1 = b.consumo\G 

對於它的價值,你也可以測試MySQL 5.1上的UPDATE語句的優化。將任何UPDATE語句重寫爲等效的SELECT非常簡單,以便查看優化器如何分析它。只需將SET表達式移動到選擇列表中。

mysql> explain SELECT a.B1 = b.consumo FROM facturacion2013_full a 
    JOIN facturacion2013_contadores b ON a.contador = b.contador\G