2

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

我需要简单地更新原始 CSV 表中的一个字段。加入这些表的更新查询现在在我的四核 8GB 固态硬盘上运行了 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;
4

1 回答 1

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);
于 2012-10-09T12:32:16.093 回答