2014-02-12 98 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