我继承了一个有很多问题的数据库。我目前要解决的问题之一是,许多表都有字符主键,用10个字符填充空格。
在大多数情况下,我已经能够更新表格以轻松删除填充。但是,有一个辅助表,有超过一千万条记录。它有一个带有填充主键的表的外键。
我想将此外键列的所有值更新为其修剪值。我尝试了一个简单的更新查询。
UPDATE actions SET foreignkey = TRIM(foreignkey);
这给了我错误“锁的总数超过了锁表大小”。通过更改innodb_buffer_pool_size看起来可能有一个修复,但我决定尝试另一种策略。让我感到震惊的是,如果我重新创建表并选择它,我会避免这个错误,也不会因为搞乱索引字段而减速。
CREATE TABLE actions2 LIKE actions;
INSERT INTO actions2 (id, foreignkey, otherfields) SELECT id, TRIM(foreignkey), otherfields FROM actions;
如果我事先没有禁用表的索引,这个解决方案会比UPDATE解决方案快得多吗?有没有更快的方法来做到这一点,我错过了?
编辑:此表的外键和另一个表的主键是VARCHAR(10)
字段。另外,我可以在一批中仅将最新的200万条记录加载到表中,并随着时间的推移慢慢填充其余记录。
答案 0 :(得分:1)
我会以“块”的形式走过那张桌子,一次做1000行。这是一些伪代码。 (详细信息取决于您希望使用的语言。)
$a = ''; -- assuming this is less than any value
loop...
$z = SELECT v FROM main
WHERE v > $a ORDER BY v LIMIT 1000,1; -- efficient locate stopper
BEGIN;
-- Update each table
UPDATE main SET v = TRIM(v)
WHERE v > $a AND v <= $z;
UPDATE table2 SET v = TRIM(v)
WHERE v > $a AND v <= $z;
UPDATE table3 SET v = TRIM(v)
WHERE v > $a AND v <= $z;
COMMIT; -- this keeps anyone from stumbling over FKs in transition
if finished, exit loop
$a = $z
end loop
我有点随意选了1000。它可能足够小,对运行系统的影响最小,但又足够大,不能永远占用。
注意:如果您已经有一些修剪过的值,您是否可以前往“重复密钥”?