2014-03-05 33 views
0

我们正在使用MySQL。 我们有一张非常长的表格(110m * 7),我们经常在这张表中添加新的记录(当我们这样做时,我们上传csv文件,所以从来没有一个非常痛苦的过程,即使是大量的记录)。1.1亿条记录的更新查询不会完成

现在我们需要添加一个新列到这个表中以某种方式区分记录。具体而言,最近添加的大约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,它是一步一步做法,没有条件句。

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

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

我们再执行下面的查询把价值1中的所有记录,以后希望对大家能只有10万条记录的值更改为2

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

但这个查询运行超过24小时,直到现在,再也没有抱怨任何事情。

我们一直通过监视服务器:

select * from pg_stat_activity; 

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

我们的问题:

  1. 这是一个速度应该期待什么,考虑到创纪录的数字是100多万元?
  2. 有没有可能这个查询不起作用,但会永久卡住?无论如何要告诉?
  3. 无论如何提高速度?或者以不同的方式做到这一点?

非常感谢提前!

+0

你的4个查询中的哪一个需要很长时间?你有'bp_serial_id'上的索引吗? – h2ooooooo

+0

你的表的结构是什么,它有哪些索引等等?它在我看来,bp_serial_id不是索引,或者你没有足够的内存,索引实际存储在磁盘上,因此速度很慢。您也可以尝试在bp_serial_id上对表进行分区:https://dev.mysql.com/doc/refman/5.6/en/partitioning-key.html – Ashalynd

+0

1.1亿行? –

回答

1

我不知道数据的基础,但一次推送的1.1亿多条记录可能有点困难。

为什么不试图找到其他的标准,做一个循环,并以较小的块做...可能基于某些“添加”日期或结构中的其他字段。或者,只是使用bp_serial_id,如(再次,通过循环处理)

伪代码同时

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值分配给临时表时,请将它们拖到最终表中,以便不必每次尝试更新1.1亿以上时间。

+0

这正是答案。根据我的经验,更新需要最长时间,应该进行批处理或尽可能避免。或者,创建一个一对一的表并执行ID的插入以及新标志。 – user158017

+0

非常感谢!今天会尝试! – user3384166

+0

@ user3384166,对于咧嘴而不是窒息它,你甚至可以用0-3的周期数进行尝试,并将记录数更新为10比100万,只是为了让你的语法工作...然后改变到百万乘数。并且确保你在bp_serial_id上有一个索引。 – DRapp