慢Python Django Mysql更新查询

时间:2017-05-11 00:10:17

标签: mysql django python-2.7 django-models

我有一个用户表,其中包含user_id,update_time等列 一个动作表,其中包含user_id,action和create_time表。

    class User(models.Model):
        user_id = models.CharField(db_index = True, max_length = 255, unique = True, null = False)
        update_time = models.DateTimeField(db_index = True, default = timezone.now, null = True, blank = True)

    class Action(models.Model):
        user_id = models.CharField(db_index = True, max_length = 255, null = False)
        action = models.CharField(db_index = True, max_length = 15, unique = False, null = False)
        create_time = models.DateTimeField(db_index = True, auto_now_add = True, null = True)

我想在update_time列中保存用户的上一个活动时间。我每天都会受到很多用户的许多操作。因此,在插入操作时,我不会更新用户表update_time列。我通过后台作业更新update_time列,后台作业找到与user_id相对应的所有操作的最大create_time,并更新用户表中的update_time列。

为此目的,后台作业在代码/查询下运行。但这段代码的表现并不那么好。任何人都可以帮我优化它,或者更好的MySQL查询,甚至是Django ORM查询的格式,还是任何不同的策略来做这个整体的事情?

    days_limit = datetime.now() - timedelta(1)
    query = "UPDATE user a JOIN (SELECT user_id, MAX(create_time) AS last_create_time FROM user_action WHERE create_time >= %s GROUP BY user_id) b ON a.user_id = b.user_id SET a.update_time = last_create_time WHERE a.update_time < last_create_time"
    cursor = connection.cursor()
    print cursor.execute(query, [str(days_limit)])

1 个答案:

答案 0 :(得分:1)

问题#1

class User(models.Model):
    user_id = models.CharField(db_index = True, max_length = 255, 

如果这是数字user_id而不是用户名,则此列没有任何意义。它应该删除。加速mysql查询的关键方法之一是减少数据大小和磁盘上的索引。这个列似乎是多余的,如果需要保留它应该是int。

问题#2

class Action(models.Model):
    user_id = models.CharField(db_index = True, max_length = 255, null = False)

如上所述,但你真正应该拥有的是

class Action(models.Model):
    user_id = models.ForeignKey(User)

因为没有外键,你不会在两个模型之间建立关系,这就是为什么你被迫使用原始查询而不是ORM查询的原因

问题#3

  

我每天都会受到很多用户的许多操作。所以我不会更新   插入操作时的用户表update_time列

如果你有正确的表结构,那么每天做很多更新都不会很慢。更新由其主键引用的单行实际上会非常快。比现在使用的复杂连接查询快得多。

如果您真的担心此类更新需要几毫秒,您可以使用芹菜在后台运行它。

问题#4

 UPDATE user a JOIN 
  (SELECT user_id, MAX(create_time) AS last_create_time FROM user_action WHERE create_time >= %s GROUP BY user_id) b 
 ON a.user_id = b.user_id SET a.update_time = last_create_time WHERE a.update_time < last_create_time"

要加快速度,您需要在user_id和create_time上使用多列索引,但user_id列是多余的....