【问题标题】:Large Import into django postgres database大量导入 django postgres 数据库
【发布时间】:2015-08-08 00:24:01
【问题描述】:

我有一个包含 4,500,000 行的 CSV 文件,需要导入到我的 django postgres 数据库中。该文件包含关系,因此不像使用 COPY 将 CSV 文件直接导入数据库那么容易。

如果我想直接将其加载到 postgres 中,我可以更改 CSV 文件以匹配数据库表,但我不确定如何获取关系,因为我需要知道插入的 id 才能建立关系.

有没有办法生成将获取最后一个 id 并在以后的语句中使用的 sql 插入?

我最初是使用 django ORM 编写的,但它需要很长时间才能做到这一点,而且它似乎正在放慢速度。我删除了所有索引和约束,所以这不应该是问题。

数据库在我的机器上本地运行。我认为一旦将数据输入数据库,将其转储并重新加载到生产数据库中就不难了。

那么我怎样才能将这些数据以正确的关系存入我的数据库中呢?

请注意,我不懂 JAVA,所以这里建议的答案对我来说不是超级实用:Django with huge mysql database

编辑: 以下是更多详细信息:

我有一个类似这样的模型:

class Person(models.Model):
    name = models.CharField(max_length=100)
    offices = models.ManyToManyField(Office)
    job = models.ForeignKey(Job)

class Office(models.Model):
    address = models.CharField(max_length=100)

class Job(models.Model):
    title = models.CharField(max_length=100)

所以我有一个人可以有一份工作但有很多办公室。 (我的真实模型有更多字段,但你明白了)。

我的 CSV 文件是这样的:

name,office_1,office_2,job
hailey,"123 test st","222 USA ave.",Programmer

还有更多的领域,但我只包括相关的领域。

所以我需要制作 person 对象和 office 对象并将它们关联起来。工作对象已经创建,所以我需要做的就是找到工作并将其保存为该人的工作。

在此之前原始数据不在数据库中。只有平面文件。我们正在尝试使其具有相关性,以便具有更大的灵活性。

谢谢!!!

【问题讨论】:

    标签: python django database postgresql


    【解决方案1】:

    嗯,这是一个。

    当您说关系时,它们都在一个 CSV 文件中?我的意思是,像这样,假设一个简单的数据模型,与自身有关系?

    id;parent_id;name
    4;1;Frank
    1;;George
    2;1;Costanza
    3;1;Stella
    

    如果是这种情况并且出现故障,我会编写一个 Python 脚本来重新排序,然后导入它们。

    前段时间我有一个场景,我有许多 CSV 文件,但它们来自单独的模型,我在其中加载了第一个父文件,然后是第二个,等等。

    我们在这里编写了自定义导入器,它们将从单个 CSV 读取数据,并对它进行一些处理,例如检查它是否已经存在、某些东西是否有效等。每个 CSV 文件的方法。

    对于足够大的 CSV,我们只是将它们拆分为较小的文件(每个文件大约 20 万条记录),然后一个接一个地处理它们。不同之处在于,这个大 CSV 所依赖的所有以前的数据都已经在数据库中,通过前面描述的相同方法导入。

    没有例子,我无法评论更多。

    编辑

    好吧,既然你给了我们你的模型,并且基于工作模型已经存在的事实,我会选择这样的东西:

    1. 创建自定义方法,即使您可以从 shell 调用。一个方法/函数或任何东西,它将接收文件的单行。
    2. 在该方法中,找出该人与多少个办公室相关。搜索以查看数据库中是否已存在办公室。如果是这样,用它来联系一个人和办公室。如果没有,请创建并关联它们
    3. 查找作业。它存在吗?是的,然后使用它。不?创建它然后使用它。

    类似这样的:

    def process_line(line):
    
        data = line.split(";")
        person = Person()
        # fill in the person details that are in the CSV
        person.name = data[1]
        person.name = data[2]
        person.save() # you'll need to save to use the m2m
    
        offices = get_offices_from_line(line) # returns the plain data, not office instances
    
        for office in offices:
    
            obj, create = get_or_create(office_address=office)
            if (obj):
                person.offices.add(obj)
    
            if (create):
                person.offices.add(create)
    
        job_obj, job_create = get_or_create(job_title=data[5])
        # repeat
    

    请注意,上面的函数没有经过测试或防范任何类型的错误。您需要:

    1. 自己动手;
    2. 创建识别每个人拥有的办公室的函数。我不知道数据,但是如果您查看第一个办公室之前的字段,然后再查看所有办公室之后的第一个字段,您可能会掌握所有这些字段;
    3. 您需要创建一个函数来解析高级文件,迭代行并将它们传递给您闪亮的导入函数。

    这里是 get_or_create 的文档:https://docs.djangoproject.com/en/1.8/ref/models/querysets/#get-or-create

    【讨论】:

    • 谢谢。我的数据中没有父 ID。我编辑了我的问题以给出一个具体的例子。如果您需要更多详细信息,请告诉我。
    • 这几乎就是我正在做的,但它真的很慢。我所做的唯一区别是使用 python csv 模块来解析该行。它现在已经 24 小时运行,并且仅解析了 400 万行中的 600000 行。我正在寻找一种无需通过 ORM 即可工作的方法。
    • 您可以编写一个脚本,首先创建所有相关的办公室。那里有多少?如果不是太多,首先创建它们,缓存它们,然后从列表或哈希中获取。它将为您节省大量的 sql 查询。
    • 办公室的数量与人数几乎相同,因此实际上并没有太大帮助。 :-/
    猜你喜欢
    • 2020-12-21
    • 2019-08-05
    • 2014-05-12
    • 2011-03-04
    • 2021-11-01
    • 2020-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多