Какой самый быстрый способ скопировать данные из одной таблицы в другую в Django? - PullRequest
2 голосов
/ 13 декабря 2011

У меня есть две модели -

ChatCurrent - (в котором хранятся сообщения для текущих активных чатов)
ChatArchive - (в которых архивируются сообщения для завершившихся чатов)

Я делаю это потому, что таблица ChatCurrent всегда имеет минимальное количество записей, что делает быстрый запрос к таблице ( Я не знаю, работает ли это, пожалуйста, дайте мне знать, если я ошибся )

Поэтому я хочу скопировать (вырезать) данные из ChatCurrent в модель ChatArchive.Какой бы самый быстрый способ сделать это.Из того, что я читал в Интернете, кажется, что мне, возможно, придется выполнить необработанный SQL-запрос, если вы будете достаточно любезны, чтобы даже заявить о запросе, я буду благодарен.

Дополнительные сведения - Обе моделиимеют ту же схему.

Ответы [ 5 ]

4 голосов
/ 13 декабря 2011

Мое мнение таково, что сегодня они не являются причиной для денормализации базы данных таким образом, чтобы повысить производительность. Индексы или разбиение + индексы должно быть достаточно .

Кроме того, в случае, если по семантическим причинам вы предпочитаете иметь две таблицы (модели) , например: Chat и ChatHistory (или ChatCurrent и ChatActive), как вы говорите и управляете им с помощью django, я думаю, что правильный способ сохранить последовательность - это создать метод ToArchive () в ChatCurrent . Этот метод перемещает записи чата в историческую модель чата. Вы можете выполнить эту операцию в фоновом режиме , затем вы можете подключить поток к процессу сельдерей , таким образом, пользователи в Интернете избегают ожидания запроса. В процесс сельдерея самым быстрым способом копирования данных является raw sql . Помните, что вы можете инкапсулировать sql в хранимую процедуру .

Отредактировано, чтобы включить ответ на ваш комментарий

Вы можете выполнить ChatCurrent.ToArchive () в методе ChatCurrent.save ():

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)
2 голосов
/ 13 декабря 2011

То, что вы пытаетесь сделать, это разбиение таблицы. Большинство баз данных поддерживают эту функцию без необходимости ведения бухгалтерского учета вручную.

Секционирование также даст намного лучшие результаты, чем ручное перемещение частей данных в другую таблицу. Используя разделы, вы избегаете: - Несоответствие данных. Это легко представить, потому что вы будете перемещать записи в большом количестве, а затем удалять их из исходной таблицы. Легко ошибиться и скопировать только часть данных. - Падение производительности - перемещение данных и связанные с ними накладные расходы на транзакции, как правило, пренебрегают любой выгодой, которую вы получаете от уменьшения размера таблицы ChatCurrent.

Для очень быстрого изложения. Секционирование таблиц позволяет сообщать базе данных, что части данных хранятся и извлекаются вместе, это значительно ускоряет запросы, так как база данных знает, что ей нужно только изучить определенную часть набора данных. Пример: чат с текущего дня, последнего часа, прошлого месяца и т. Д. Вы можете дополнительно хранить каждый раздел на отдельном диске, чтобы сохранить текущую болтовню на быстром SSD-накопителе и историю на обычных медленных дисках.

Пожалуйста, обратитесь к руководству по вашей базе данных, чтобы узнать подробности о том, как оно обрабатывает разбиение.

Пример для PostgreSQL: http://www.postgresql.org/docs/current/static/ddl-partitioning.html

Разделение означает разделение логически одной большой таблицы на более мелкие физические части. Разбиение может дать несколько преимуществ:

  • Производительность запросов может быть значительно улучшена в определенных ситуациях, особенно когда большинство часто используемых строк таблицы находятся в одном разделе или небольшом количестве разделов. Разделение заменяет ведущие столбцы индексов, уменьшая размер индекса и повышая вероятность того, что интенсивно используемые части индексов помещаются в памяти.

  • Когда запросы или обновления обращаются к большому проценту одного раздела, производительность можно улучшить, воспользовавшись преимуществом последовательного сканирования этого раздела вместо использования индекса и чтения с произвольным доступом, разбросанного по всей таблице.

  • Массовую загрузку и удаление можно выполнить путем добавления или удаления разделов, если это требование запланировано в проекте разделения. ALTER TABLE NO INHERIT и DROP TABLE работают намного быстрее, чем массовая операция. Эти команды также полностью исключают издержки VACUUM, вызванные массовым удалением.

  • Редко используемые данные можно переносить на более дешевые и медленные носители.

2 голосов
/ 13 декабря 2011

Попробуйте что-то вроде этого:

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

, а не просто

DELETE FROM "ChatCurrent" WHERE yourCondition;
0 голосов
/ 06 января 2012
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)
0 голосов
/ 13 декабря 2011

В соответствии с приведенными выше решениями не копируйте.

Если вы действительно хотите иметь две отдельные таблицы для запроса, сохраняйте свои чаты в одной таблице (и для предпочтения используйте все методы базы данныхздесь упоминается), а затем иметь таблицу Current и Archive, чьи объекты просто указывают на объекты Chat /

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...