Я пишу jango-ORM enchancement, который пытается кэшировать модели и откладывать сохранение модели до конца транзакции. Все это почти закончилось, однако я столкнулся с неожиданными трудностями в синтаксисе SQL.
Я не являюсь администратором баз данных, но, насколько я понимаю, базы данных не работают эффективно для многих небольших запросов. Несколько больших запросов намного лучше. Например, лучше использовать большие пакетные вставки (скажем, 100 строк одновременно) вместо 100 однострочных.
Теперь, из того, что я вижу, SQL действительно не предоставляет какой-либо инструкции для выполнения пакетного обновления в таблице. Этот термин, похоже, запутан, поэтому я объясню, что я имею в виду. У меня есть массив произвольных данных, каждая запись, описывающая одну строку в таблице. Я хотел бы обновить некоторые строки в таблице, каждый из которых использует данные из соответствующей записи в массиве. Идея очень похожа на пакетную вставку.
Например: Моя таблица может иметь два столбца "id"
и "some_col"
. Теперь массив, описывающий данные для пакетного обновления, состоит из трех записей (1, 'first updated')
, (2, 'second updated')
и (3, 'third updated')
. Перед обновлением таблица содержит строки: (1, 'first')
, (2, 'second')
, (3, 'third')
.
Я пришел на этот пост:
Почему пакетные вставки/обновления быстрее? Как работают пакетные обновления?
который, кажется, делает то, что я хочу, однако я не могу понять синтаксис в конце.
Я мог бы также удалить все строки, которые требуют обновления, и повторно вставить их, используя пакетную вставку, однако мне трудно поверить, что это действительно будет лучше.
Я работаю с PostgreSQL 8.4, поэтому некоторые хранимые процедуры также возможны здесь. Однако, поскольку я планирую вначале открыть исходный код проекта, более приветствуются любые переносимые идеи или способы сделать то же самое на другой РСУБД.
Последующий вопрос: Как выполнить пакетный оператор "insert-or-update" / "upsert"?
Результаты тестов
Я выполнил 100x раз 10 операций вставки, распределенных по 4 различным таблицам (так что всего 1000 вложений). Я тестировал Django 1.3 с бэкэндом PostgreSQL 8.4.
Вот результаты:
- Все операции, выполняемые через Django ORM - каждый проход ~ 2.45 секунд,
- Те же операции, но без Django ORM - каждый проход ~ 1.48 секунд,
- Только операции вставки, без запроса базы данных для значений последовательности ~ 0,72 секунды,
- Только операции вставки, выполняемые в блоках по 10 (всего 100 блоков) ~ 0.19 секунд,
- Только операции вставки, один большой блок выполнения ~ 0.13 секунды.
- Только операции вставки, около 250 операторов на блок, ~ 0,12 секунды.
Заключение: выполните как можно больше операций в одном соединении .execute(). Сам Django вводит существенные накладные расходы.
Отказ от ответственности: я не вводил никаких индексов, кроме индексов первичного ключа по умолчанию, поэтому из-за этого операции вставки могут работать быстрее.