更新查询的1.1亿条记录将无法完成

时间:2014-03-05 16:03:01

标签: mysql

我们正在使用MySQL。 我们有一个非常长的表(110m * 7),我们经常在这个表中添加新记录(当这样做时,我们上传csv文件,所以从来不会是一个非常痛苦的过程甚至大量的记录)。

现在我们需要在此表中添加一个新列,以某种方式区分记录。具体而言,最近添加的约1000万条记录将被标记为类型2,所有旧记录将被标记为类型1.并且将来,我们将为这两种类型添加新记录。

首先,我们尝试了如下方法1,但它运行了超过24小时而没有任何抱怨,主机服务器始终响应。

-- ====================================================
-- start of approach 1
-- ====================================================

-- Add column.
ALTER TABLE 
  bond_price 
ADD 
  bp_name_version SMALLINT 
;


-- Set value 1 for BOND_CHARACTER types.
UPDATE 
  bond_price 
SET 
  bp_name_version = 1 
WHERE 
  bp_serial_id < 107480325 
;


-- Set value 2 for BOND_CHARACTER_EIKON types.
UPDATE 
  bond_price 
SET 
  bp_name_version = 2 
WHERE 
  bp_serial_id >= 107480325 
;


-- Set a NOT NULL constrain on the new column
ALTER TABLE 
  bond_price 
ALTER 
  bp_name_version SET NOT NULL 
;


-- ====================================================
-- END of approach 1
-- ====================================================

我们在24小时后失去了信仰,认为设定条件条款可能会让这么长的桌子变得困难。所以我们尝试了方法2,即逐步进行方法1,没有条件子句。

所以我们首先执行以下查询,并在几秒钟内完成。

-- Add column.
ALTER TABLE 
  bond_price 
ADD 
  bp_name_version SMALLINT 
;

然后我们执行以下查询将值1放到所有记录中,希望稍后我们可以将只有1000万条记录的值更改为2。

-- Set value 1 for all records.
UPDATE 
  bond_price 
SET 
  bp_name_version = 1;

但是这个查询已经运行了24个小时到现在,再次没有抱怨任何事情。

我们一直在监控服务器:

select * from pg_stat_activity;

“设置值1”查询仍处于活动状态,服务器仍然非常敏感。

我们的问题:

  1. 考虑到创纪录的人数超过1亿,这个速度是否应该达到预期?
  2. 这个查询是否有可能不起作用但是永远陷入困境?无论如何要告诉?
  3. 无论如何都要提高速度?或者以不同的方式做到这一点?
  4. 非常感谢提前!

1 个答案:

答案 0 :(得分:1)

我不知道这些数据的基础,但一次推出的记录超过了一万两千万。

为什么不尝试找到其他一些标准,做一个循环,然后在较小的块中进行...可能基于一些“添加”日期或结构中的其他一些字段。或者,只使用bp_serial_id,例如(再次由循环处理)

一次最多更新100万的伪代码

maxSerialForType1 = 107480325 

for cycle = 0 to 110
   startSerialID = cycle * 1000000
   endSerialID = (cycle +1 ) * 1000000

   if startSerialID < maxSerialForType1
      UPDATE bond_price 
         SET bp_name_version = 1
         WHERE bp_serial_id < maxSerialForType1
           AND bp_serial_id >= startSerialID
           AND bp_serial_id < endSerialID
   end for update type 1

   if startSerialID > maxSerialForType1
      UPDATE bond_price 
         SET bp_name_version = 2
         WHERE bp_serial_id > maxSerialForType1
           AND bp_serial_id >= startSerialID
           AND bp_serial_id < endSerialID
   end for update type 2
end of loop

所以这个,如果像存储过程一样,将为你更新1.1亿。

然后我会建议,当将新记录导入到临时表中并在其中分配bp_name_version值时,然后将它们拉入最终表,这样您就不必每次都尝试更新超过110万