在Django中将数据从一个表复制到另一个表的最快方法是什么?

时间:2011-12-13 07:11:09

标签: sql django

我有两个型号 -

ChatCurrent - (存储当前活动聊天的消息)
ChatArchive - (存档已结束聊天的消息)

我这样做的原因是ChatCurrent表始终具有最少的条目数,使得快速查询表(我不知道这是否有效,如果我有,请告诉我这个错误的

所以我基本上想要将ChatCurrent中的数据复制(剪切)到ChatArchive模型。什么是最快的方式来做到这一点。从我在网上看到的,似乎我可能必须执行一个原始的SQL查询,如果你愿意甚至陈述查询,我​​将不胜感激。

其他细节 - 两个模型都具有相同的模式。

5 个答案:

答案 0 :(得分:4)

我的观点是,今天他们没有理由denormalize database 以这种方式来提高绩效。应该使用索引或分区+索引

此外,如果出于语义原因,你更喜欢两个表(模型),如:Chat和ChatHistory(或ChatCurrent和ChatActive),就像你说的那样用django管理它,我的东西保持一致性的正确方法是在ChatCurrent中创建ToArchive()方法。此方法将聊天条目移动到历史聊天模型。您可以在后台模式中执行此操作,然后您可以在celery进程中对交换进行线程化,这样在线用户就可以避免等待请求。进入芹菜过程中,复制数据的最快方法是 raw sql 。请记住,您可以将sql封装到存储过程

已修改为包含对您的评论的回复

您可以在ChatCurrent.save()方法中执行ChatCurrent.ToArchive():

class ChatCurrent(model.Model):
    closed=models.BooleanField()

    def save(self, *args, **kwargs):
        super(Model, self).save(*args, **kwargs)
        if self.closed:
            self.ToArchive()

    def ToArchive(self):
        from django.db import connection, transaction
        cursor = connection.cursor()            
        cursor.execute("insert into blah blah")
        transaction.commit_unless_managed()
        #self.delete()  #if needed (perhaps deleted on raw sql)

答案 1 :(得分:2)

尝试这样的事情:

INSERT INTO "ChatArchive" ("column1", "column2", ...)
SELECT "column1", "column2", ...
FROM "ChatCurrent" WHERE yourCondition;

而不仅仅是

DELETE FROM "ChatCurrent" WHERE yourCondition;

答案 2 :(得分:2)

您要做的是表分区。 大多数数据库都支持此功能,而无需手动记账。

除了将数据的一部分手动移动到不同的表之外,分区也会产生更好的结果。通过使用分区,您可以避免:   - 数据不一致。这很容易介绍,因为您将批量移动记录,然后从源表中删除大量记录。很容易犯错并只复制一部分数据。   - 性能下降 - 移动数据并从事务中获得相关的开销通常会忽略减少ChatCurrent表大小所带来的任何好处。

快速破解。表分区允许您告诉数据库一起存储和检索部分数据,这大大加快了查询速度,因为数据库知道它只需要查看数据集的特定部分。示例:来自当天,最后一小时,上个月等的聊天。您可以另外将每个分区存储在不同的驱动器上,这样您就可以将当前的聊天记录保存在快速SSD驱动器上,并将历史记录保存在常规较慢的磁盘上。

请参阅您的数据库手册以了解有关如何处理分区的详细信息。

PostgreSQL示例:http://www.postgresql.org/docs/current/static/ddl-partitioning.html

  

分区是指将逻辑上一个大表分成较小的物理块。分区可以带来几个好处:

     
      
  • 在某些情况下,查询性能可以得到显着提高,特别是当表的大多数访问量很大的行位于单个分区或少量分区中时。分区可以替代索引的前导列,从而减少索引大小,并使索引中频繁使用的部分更有可能适合内存。

  •   
  • 当查询或更新访问单个分区的大部分时,可以通过利用该分区的顺序扫描而不是使用分散在整个表中的索引和随机访问读取来提高性能。

  •   
  • 如果计划在分区设计中,则可以通过添加或删除分区来完成批量加载和删除。 ALTER TABLE NO INHERIT和DROP TABLE都比批量操作快得多。这些命令还完全避免了由批量DELETE引起的VACUUM开销。

  •   
  • 很少使用的数据可以迁移到更便宜和更慢的存储介质。

  •   

答案 3 :(得分:0)

根据上述解决方案,请勿复制。

如果你真的想要查询两个单独的表,将聊天记录存储在一个表中(并且首选,使用此处提到的所有数据库技术),然后有一个Current和Archive表,其对象只指向聊天对象/

答案 4 :(得分:0)

def copyRecord(self,recordId):
    emailDetail=EmailDetail.objects.get(id=recordId)
    copyEmailDetail= CopyEmailDetail()
    for field in emailDetail.__dict__.keys():
       copyEmailDetail.__dict__[field] = emailDetail.__dict__[field]
    copyEmailDetail.save()
    logger.info("Record Copied %d"%copyEmailDetail.id)