Python peewe将多个记录插入位于的多个表中

2024-04-28 20:33:42 发布

您现在位置:Python中文网/ 问答频道 /正文

概述
我有一个关系型MySQL InnoDB数据库。目前,我已经准备好了代码,可以使用python2.6.6中的peeweeorm向数据库添加数据。问题是,由于我所有的外键,我最终在每个数据点上执行五个SELECT和(最坏情况)五个INSERT语句。可以想象,当我尝试添加5000000个左右的数据点(40 MiB左右的数据)时,由于所有的事务处理,需要花费非常长的时间。在

示例
下面是一个虚拟的例子,来演示我要做的事情:

import csv
import peewee as pw
db = pw.MySQLDatabase(example, **{'passwd': 'example', 'host': 'example', 'port': 3306, 'user': 'example'})

class BaseModel(pw.Model):
    class Meta:
        database = db
class Users(BaseModel):
    User      = pw.PrimaryKeyField(db_column = 'User_ID')
    User_Name = pw.CharField(db_column = 'User_Name', max_length = 50)
    class Meta:
        db_table = 'users'
class Pets(BaseModel):
    Pets     = pw.PrimaryKeyField(db_column = 'Pet_ID')
    Pet_Name = pw.CharField(db_column = 'Pet_Name', max_length = 50)
    User     = pw.ForeignKeyField(db_column = 'User_ID', rel_model = Users)
    class Meta:
        db_table = 'pets'

def add_measurement(user_name, pet_name):
    # Add user
    try:
        self.dbo_users = Users.get(Users.User_Name == user_name)
    except Users.DoesNotExist:
        self.dbo_users = Users.create(User_Name = user_name)
    # Add pet and link to user
    try:
        self.dbo_pets = Pets.get(Pets.User == self.dbo_users.User,
                                 Pets.Pet_Name == pet_name)
    except Pets.DoesNotExist:
        self.dbo_pets = Pets.create(User = self.dbo_users.User,
                                    Pet_Name = pet_name)

db.connect()
example_data_file = r'C:\users_pets.csv'

# Add all data in CSV file to database, assume first row == header, all other
# rows are data, with the format of: user_name, pet_name
with open(example_data_file, 'rb') as f:
    reader = csv.reader(f)
    reader.next() # Skip header
    for row in reader:
        add_measurement(row[0], row[1])

问题
在这个基本示例中,输入文件中的每一行使用两个SELECT语句和最多两个INSERT语句。对于非常大的文件,将所有这些数据放入数据库将花费大量时间。在

我想用某种方法读入输入文件的块,然后执行一条INSERT语句将所有数据大量转储到数据库中。由于我不知道所有的FK关系,我仍然需要执行所有这些SELECT语句;但是,由于所有FK都是自动递增的,所以我可以手动跟踪它们。在

理想情况下,我希望使用peewee来实现这一点;但是,我也愿意使用纯SQL解决方案。我在想我可以建立所有我试图插入内存的数据,然后一次将它们全部转储。使用这种方法,除了数据库中的FK关系之外,我还需要检查内存内容。在

基本上,我在寻找“最快”的方法来获取大量数据并将其转储到数据库中。任何意见都是非常感谢的,我现在几乎被卡住了。在

解决方案
我能够想出一个比上面的实现快2000倍以上的解决方案。最后,我构建了一个包含所有数据的CSV文件,将其复制到服务器,然后使用LOAD DATA INFILE将这些数据存储到一个临时表中。虽然这在技术上没有数据库中的数据,但正确地说,它允许用户快速地转储数据,而不必等待它完成。然后我有一个存储过程来处理实际的数据插入。这个解决方案有点复杂,但确实很有效。在


Tags: 数据nameself数据库dbexampleusersclass