Оптимизация Sqlite3 для 20 000+ обновлений - PullRequest
3 голосов
/ 15 июля 2011

У меня есть списки из примерно 20 000 элементов, которые я хочу вставить в таблицу (с около 50 000 строк в ней). Большинство из этих элементов обновляют определенные поля в существующих строках, а меньшинство будет вставлять совершенно новые строки.

Я получаю доступ к базе данных дважды для каждого элемента. Первый - это запрос выбора, который проверяет, существует ли строка. Далее я вставляю или обновляю строку в зависимости от результата запроса select. Я фиксирую каждую транзакцию сразу после обновления / вставки.

Для первых нескольких тысяч записей я пропускаю около 3 или 4 элементов в секунду, затем он начинает замедляться. К концу каждой итерации требуется больше 1/2 секунды. Почему это может замедляться?

Мое среднее время составляет: 0,5 секунды для всего прогона, разделенного на .18 с на запрос выбора и .31 с на вставку / обновление. Последний 0,01 обусловлен несколькими неизмеренными процессами, связанными с анализом данных перед вводом в базу данных.

Обновление

Я закомментировал все коммиты в качестве теста и не получил никаких изменений, так что это не так (все же хотелось бы больше мыслей об оптимальном фиксировании).

Что касается структуры таблицы: В каждом ряду двадцать столбцов. Первые четыре являются полями TEXT (все задаются с первой вставкой), а 16 являются полями REAL, одно из которых вводится с помощью оператора начальной вставки.

Со временем «выдающиеся» поля REAL будут заполнены процессом, который я пытаюсь оптимизировать.

У меня нет явного индекса, хотя одно из полей является уникальным ключом для каждой строки.

Следует отметить, что по мере того, как база данных становилась больше, запросы SELECT и UPDATE занимали все больше и больше времени, что особенно заметно ухудшило производительность операции SELECT.

Изначально я думал, что это может быть какая-то структурная проблема с SQLITE (что бы это ни значило), но я нигде не смог найти никакой документации, которая бы указывала на естественные ограничения для программы.

База данных составляет около 60 мегабайт, сейчас.

Ответы [ 2 ]

5 голосов
/ 15 июля 2011

Я думаю, что вашим узким местом является то, что вы фиксируете с / avec каждую вставку / обновление:

Я фиксирую каждую транзакцию сразу после обновления / вставки.

Любая остановкасделать это или хотя бы переключиться на WAL ведение журнала ;см. этот мой ответ на вопрос: Сравнение производительности SQL Server CE 4.0

Если у вас есть первичный ключ, вы можете оптимизировать выбор, используя предложение ON CONFLICT с INSERT INTO:

http://www.sqlite.org/lang_conflict.html

РЕДАКТИРОВАТЬ : Раньше я хотел написать «если у вас есть первичный ключ », а не внешний ключ;Я исправил это.

2 голосов
/ 15 июля 2011

Редактировать : позор мне.Я неправильно понял вопрос и как-то понял, что это было для mySQL , а не для SQLite ... Упс.
Пожалуйста, не обращайте внимания на этот ответ, за исключением получения универсальногоидеи об обновлении СУБД.Вероятное решение проблемы OP - это слишком частые коммиты, как указано в sixfeetsix 'response .


Правдоподобным объяснением является то, что таблица становится фрагментированной .
Этот факт можно проверить с помощью частой дефрагментации таблицы и проверки, вернется ли производительность к частоте 3 или 4 элемента в секунду.(Что, кстати, априори относительно медленно, но может зависеть от аппаратного обеспечения, схемы данных и других особенностей.) Конечно, вам нужно учитывать количество времени, которое занимает дефрагментация, и сопоставлять его с временем, потерянным из-за медленного обновления.Скорость, чтобы найти оптимальную частоту для дефрагментации.

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

Последнее предложение,для повышения общей производительности обновлений можно (* если это возможно) удалить несколько индексов в таблице, выполнить обновления и заново создать индексы .Этот нелогичный подход работает для относительно больших обновлений, потому что затраты на воссоздание новых индексов часто меньше совокупных затрат на их обслуживание в процессе обновления.

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