如何更新巨大的表列?

时间:2014-08-11 10:59:53

标签: mysql sql

我的表中有 9918751 记录,请在下面找到数据结构,

+--------------------+--------------+------+-----+-------------------+----------------+
| Field              | Type         | Null | Key | Default           | Extra          |
+--------------------+--------------+------+-----+-------------------+----------------+
| id                 | int(11)      | NO   | PRI | NULL              | auto_increment |
| start_ip           | varchar(32)  | YES  | UNI | NULL              |                |
| end_ip             | varchar(32)  | YES  | UNI | NULL              |                |
| country            | varchar(255) | YES  |     | NULL              |                |
| region             | varchar(255) | YES  |     | NULL              |                |
| city               | varchar(255) | YES  |     | NULL              |                |
| country_conf       | varchar(255) | YES  |     | NULL              |                |
| region_conf        | varchar(255) | YES  |     | NULL              |                |
| city_conf          | varchar(255) | YES  |     | NULL              |                |
| country_code       | int(11)      | YES  |     | NULL              |                |
| region_code        | int(11)      | YES  |     | NULL              |                |
| city_code          | int(11)      | YES  |     | NULL              |                |
| two_letter_country | varchar(20)  | YES  |     | NULL              |                |
| creation_datetime  | timestamp    | NO   |     | CURRENT_TIMESTAMP |                |
+--------------------+--------------+------+-----+-------------------+----------------+

在我的表中,start_ipend_ip列包含有效的IPv4 IP地址(如192.168.1.112.23.34.22等),现在我要更新所有行(9918751)使用INET_ATON()函数将IP地址转换为整数。当我在查询

下运行时
update geo_location_info set start_ip = INET_ATON(start_ip);

此查询花费了太多时间来更新9918751行并且未完成更新。请让我知道任何替代方案(商店程序?)

1 个答案:

答案 0 :(得分:2)

基本思想是使用循环进行更新。问题是函数调用需要一段时间,查询可能会超时。此外,更新近1000万行会给维护数据完整性的日志记录机制带来一定的负担。假设id是逐步填充的,您可以在10,000或100,000的组中执行此操作。不幸的是,你无法真正使用@Stewarts的想法,但几乎一半的行都可能以1开头。

基本循环是:

set @len := 10000, @i := 1;

while @i * @len < 10000000 do
     update geo_location_info
        set start_ip = INET_ATON(start_ip)
        where id between @len*@i and @len*(@i + 1) - 1;
     set @i := @i + 1;
end while;

不幸的是,在MySQL中,您需要将其放入存储过程中 - 因为控制流机制(例如while)仅在存储的程序中允许。所以,更像是:

delimiter $$
create procedure do_update ()
begin
    set @len := 10000, @i := 1;
    select @max := max(id) from geo_location_info;

    while @i * @len <= @max do
         update geo_location_info
            set start_ip = INET_ATON(start_ip)
            where id between @len*@i and @len*(@i + 1) - 1;
         set @i := @i + 1;
    end while;
end $$
delimiter ;