首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MySQL插入...使用django 1.4进行大容量插入时的重复键更新

MySQL插入...使用django 1.4进行大容量插入时的重复键更新
EN

Stack Overflow用户
提问于 2012-10-16 22:24:17
回答 2查看 3.9K关注 0票数 3

我在弄清楚MySQL插件时遇到了一些问题...关于django 1.4的重复密钥更新。

我试图插入记录的表有一个2列(复合)的唯一键。我收到的记录来自第三方来源,值将随着时间的推移而变化,除了那些构成唯一密钥集的字段。我一次收到1~ 5k条记录,需要

目前我正在使用Model.objects.bulk_create进行大容量插入,性能真的很惊人,因为它通常会发出一个查询,而不管记录集有多大。但是,由于我的记录在第三方端可能会随着时间的推移而更改,因此我需要执行MySQL插入...在记录集上执行重复键更新查询。

我计划编写原始SQL语句,并使用如下代码执行:

代码语言:javascript
复制
sql = "MySQL INSERT ... ON DUPLICATE KEY UPDATE"

raw_insert(sql)

def raw_insert(sql):
    from django.db import connection, transaction
    cursor = connection.cursor()

    # Data modifying operation - commit required
    cursor.execute(sql)
    transaction.commit_unless_managed()

    return 1

想知道是否有更好的方法来解决我的问题。另外,如何清理原始插入的字段值?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-10-17 11:20:14

所以我创建了一个自定义管理器。这是经理:

代码语言:javascript
复制
class BulkInsertManager(models.Manager):
    def _bulk_insert_or_update(self, create_fields, update_fields, values):

        from django.db import connection, transaction
        cursor = connection.cursor()

        db_table = self.model._meta.db_table

        values_sql = []
        values_data =[]

        for value_lists in values:
            values_sql.append( "(%s)" % (','.join([ "%s" for i in range(len(value_lists))]),) )
            values_data.extend(value_lists)

        base_sql = "INSERT INTO %s (%s) VALUES " % (db_table, ",".join(create_fields))

        on_duplicates = []

        for field in update_fields:
            on_duplicates.append(field + "=VALUES(" + field +")")

        sql = "%s %s ON DUPLICATE KEY UPDATE %s" % (base_sql, ", ".join(values_sql), ",".join(on_duplicates))

        cursor.executemany(sql, [values_data])
        transaction.commit_unless_managed()

和一个示例模型:

代码语言:javascript
复制
class User_Friend(models.Model):
    objects = BulkInsertManager() # assign a custom manager to handle bulk insert

    id = models.CharField(max_length=255)
    user = models.ForeignKey(User, null=False, blank=False)
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    city = models.CharField(max_length=50, null=True, blank=True)
    province = models.CharField(max_length=50, null=True, blank=True)
    country =  models.CharField(max_length=30, null=True, blank=True)

和示例实现:

代码语言:javascript
复制
def save_user_friends(user, friends):
    user_friends = []
    for friend in friends:

        create_fields = ['id', 'user_id', 'first_name', 'last_name', 'city', 'province', 'country']
        update_fields = ['first_name', 'last_name', 'city', 'province', 'country']

        user_friends.append(
            [
                str(user.id), 
                str(friend['id']),
                friend['first_name'],
                friend['last_name'],
                friend['city'],
                friend['province'],
                friend['country'],
            ]
        )

    User_Friend.objects._bulk_insert_or_update(create_fields, update_fields, user_friends)

这是gist

票数 9
EN

Stack Overflow用户

发布于 2012-10-17 05:54:56

您可以使用ModelForm进行清理:

代码语言:javascript
复制
from django.forms.models import modelform_factory
form_class = modelform_factory(MyModel)

for obj in my_data:
    form = form_class(obj)
    if not form.is_valid():
        raise Hell()

至于原始的SQL,我说去吧。看起来Django的ORM并不支持ON DUPLICATE KEY UPDATE,所以不要让它妨碍你。The Django docs talk about doing it without any reservation

不过,使用Manager.raw可能是值得的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12916880

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档