在postgresql数据库中:
class Persons(models.Model):
person_name = models.CharField(max_length=10, unique=True)
persons.csv
文件,包含100万个名称。
$cat persons.csv
Name-1
Name-2
...
Name-1000000
我想:
我的方法:
使用COPY
命令或实现它的django-postgres-copy应用程序。
还可以利用新的Postgresql-9.5 + upsert feature。
现在,csv文件中的所有名称也在数据库中。
我需要从数据库中获取他们的ID - 在内存或其他csv文件中以有效的方式:
我不认为任何上述获取ID的方法都是有效的。
第三种选择,与this post一致,应该是一个很好的解决方案,它结合了以上所有。
答案 0 :(得分:0)
类似的东西:
SELECT * FROM persons;
创建一个名称:从数据库中收到的名称中的id字典:
db_dict = {'Harry': 1, 'Bob': 2, ...}
查询字典:
ids = []
for name in list_of_million_names:
if name in db_dict:
ids.append(db_dict[name])
这样您就可以使用快速字典索引而不是较慢的if x in list
方法。
但真正确切知道的唯一方法是对这3种方法进行基准测试。
答案 1 :(得分:0)
This post介绍如何将RETURNING
与ON CONFLICT
一起使用,以便在插入数据库时csv文件的内容,当插入成功时,ID将保存在另一个表中,或当 - 由于唯一约束 - 插入被省略。
我在sqlfiddle中测试了它,我使用的a set up类似于用于COPY
命令的命令,它直接从csv文件插入数据库,尊重唯一约束。
架构:
CREATE TABLE IF NOT EXISTS label (
id serial PRIMARY KEY,
label_name varchar(200) NOT NULL UNIQUE
);
INSERT INTO label (label_name) VALUES
('Name-1'),
('Name-2');
CREATE TABLE IF NOT EXISTS ids (
id serial PRIMARY KEY,
label_ids varchar(12) NOT NULL
);
剧本:
CREATE TEMP TABLE tmp_table
(LIKE label INCLUDING DEFAULTS)
ON COMMIT DROP;
INSERT INTO tmp_table (label_name) VALUES
('Name-2'),
('Name-3');
WITH ins AS(
INSERT INTO label
SELECT *
FROM tmp_table
ON CONFLICT (label_name) DO NOTHING
RETURNING id
)
INSERT INTO ids (label_ids)
SELECT
id FROM ins
UNION ALL
SELECT
l.id FROM tmp_table
JOIN label l USING(label_name);
输出:
SELECT * FROM ids;
SELECT * FROM label;