使用索引,MySQL更新查询速度极慢

时间:2014-02-12 19:12:22

标签: mysql database performance indexing

此查询需要花费大量时间才能执行:

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  ;

我尝试过改变一些没有运气的小东西。还尝试更改mysql配置中的一些参数,如缓冲区大小,max_heap_table_size ...我缺少什么?提前谢谢!

1 个答案:

答案 0 :(得分:2)

我在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