MySQL:连接3个表的UPDATE查询运行时间长(15M行表,索引)

时间:2012-10-09 11:50:09

标签: mysql sql sql-update

我在3个表中有15M行(一个表是原始CSV导入,另外两个是该CSV的标准化版本+其他一些数据)。

我只需要从原始CSV表中更新一个字段。加入这些表的更新查询现在在我的四核-8GB-ssd盒子上运行了30个小时。

  • 这是正常的吗?有没有更好的方法来执行这个简单的更新?

Tables: ti (the CSV dump, denormalized, ~13M rows)
        i (the primary, normalized table, ~17M rows)
        icm (a map of ti.raw_id to i.item_id, ~17M rows)

mysql> explain select * from item AS i, item_catalog_map AS icm, temp_input AS ti WHERE i.id=icm.item_id AND icm.catalog_unique_item_id=ti.productID;
+----+-------------+-------+--------+----------------------+----------------------+---------+------------+----------+-------------+
| id | select_type | table | type   | possible_keys        | key                  | key_len | ref        | rows     | Extra       |
+----+-------------+-------+--------+----------------------+----------------------+---------+------------+----------+-------------+
|  1 | SIMPLE      | i     | ALL    | PRIMARY              | NULL                 | NULL    | NULL       | 13652592 |             |
|  1 | SIMPLE      | icm   | ref    | IDX_ACD6184F126F525E | IDX_ACD6184F126F525E | 5       | frugg.i.id |        1 | Using where |
|  1 | SIMPLE      | ti    | eq_ref | PRIMARY              | PRIMARY              | 767     | func       |        1 | Using where |
+----+-------------+-------+--------+----------------------+----------------------+---------+------------+----------+-------------+
3 rows in set (0.06 sec)

mysql> UPDATE item AS i, item_catalog_map AS icm, temp_input AS ti
    -> SET i.name=ti.productName,
    ->     icm.price=ti.retailPrice,
    ->     icm.conversion_url=productURL
    -> WHERE i.id=icm.item_id AND icm.catalog_unique_item_id=ti.productID;

1 个答案:

答案 0 :(得分:1)

首先,如果你的非规范化数据有13M记录,但你的“规范化”表中的都有17M记录,那么你的规范化就不会得到很多压缩。

其次,您尝试在一个SQL语句中更新两个规范化表。我认为您应该首先更新映射表,然后在第二个SQL语句中更新数据表。

第三,进行内部联接可以加快速度,因为您的查询正在执行三向笛卡尔积。嗯,不完全是,因为你只是在加入旧学校,优化器应该选择它,但不过,使用JOIN语法。

UPDATE item_catalog_map AS icm
       INNER JOiN temp_input AS ti
          ON icm.catalog_unique_item_id = ti.productID
  SET icm.price = ti.retailPrice,
      icm.conversion_url = productURL;


UPDATE item AS i
       INNER JOIN temp_input AS ti
          ON i.id = icm.item_id
  SET i.name = ti.productName;

最后,确保你拥有的索引是:

CREATE INDEX IDX_CATALOG ON item_catalog_map (catalog_unique_item_id);
CREATE INDEX IDX_RAW_PRODUCT_ID ON temp_input (productID);
CREATE INDEX IDX_RAW_ITEM_ID ON temp_input (item_id);