截断行并插入新行而不引入服务中断?
问题描述:
我在PostgreSQL 9.5数据库表中有大约1,500,000条记录,并且我得到一个CSV文件(通过http post请求),其中包含新的〜1,500,000行,其中一些没有改变,有些不同,有些被删除到原始行。截断行并插入新行而不引入服务中断?
我再
- 截断旧表
- 循环遍历CSV文件的行
- 将每个行插入表
我需要的是一个办法做到这一点没有向我的客户介绍服务中断,即服务应该继续使用旧数据,直到完成所有三个步骤。目前服务暂停将会持续1个小时,这就是读取CSV并插入所有新行所需的时间。如果需要的话,我可以休息5分钟。
我该如何实现这样的行为?
这里是我的Python脚本的简化版本:
cursor = conn.cursor(cursor_factory=DictCursor)
cursor.execute('TRUNCATE TABLE rows CASCADE')
with open(request.files.csv) as csv_file:
for line in csv_file:
row = parse_line(line)
cursor.execute(
'''INSERT INTO rows (name, bla, blu)
VALUES (%(name)s, %(bla)s, %(blu)s)''',
row,
)
cursor.commit()
答
- 使用
COPY
代替with open(request.files.csv)
,因为150万行从CSV - 复制到一个表在几秒钟内,如果这些秒(让我们假设一个分钟)太长,只是使用交易无济于事,导致表格上的truncate requires lock,而不是行
TRUNCATE上
所以它的运作 每个表获取到一个ACCESS EXCLUSIVE锁,如果你可以重建在桌子上,兴田最重要依赖对象很可能是:
create t_table as select * from "rows" where false;
copy t_table from request.files.csv;
--build all needed dependant objects (indexes, constraints,triggers);
begin;
alter table "rows" rename to "some_name";
alter table "t_table " rename to "rows";
end;
--here is a miliseconds glitch to swith for users (if you use memcache or so - need to refresh it)
drop table "some_name";
更新 to copy columns from csv to several table columns list columns:
COPY table_name [(column_name [,...])]]
截断会在truncate命令出现问题之前影响其他正在处理快照的事务,所以它不适合'服务应该继续使用旧数据,直到完成所有三个步骤完成要求。 –
这看起来很棒,谢谢!只有一个跟进问题; CSV文件有20列,但我的表只需要其中的五个。我能否以某种方式只复制五个特定的列,或者我应该在将Python转发到数据库之前使用Python编辑CSV? –
@MarkusMeskanen更新。使用request.files.csv中的'copy t_table(col1,col4,col5等);' –