2011-07-15 3 views
3

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

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

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

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

Update

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

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

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

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

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

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

База данных о 60ish megs, сейчас.

+1

Вы можете настроить SQLite, используя «PRAGMAs», вести журнал и т. Д. –

+0

Эти времена «априорно» ужасны, но нам нужно больше контекста, чтобы действительно иметь идею. Можете ли вы опубликовать структуру таблицы, а также образец типичных записей? –

+0

Помогли ли вы вести журнал WAL? –

ответ

5

Я думаю, что узким местом является то, что вы совершаете с/АВЭК каждой вставки/обновления:

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

Либо прекратите это делать, либо, по крайней мере, переключитесь на WAL journaling; увидеть этот ответ мой, почему: SQL Server CE 4.0 performance comparison

Если у вас есть первичный ключ вы можете оптимизировать из избранных с помощью предложения КОНФЛИКТА ON с INSERT INTO:

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

EDIT: Ранее Я хотел написать «если у вас есть первичный ключ », а не внешний ключ; Я починил это.

+1

avec? Смешивание языков? :) – FogleBird

+0

woa funky! мои сегодняшние корни в Монреале крепки! –

2

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


Вероятное объяснение состоит в том, что таблица фрагментируется.
Вы можете проверить этот факт на defragmenting the table так часто и проверить, возвращается ли производительность к ставке 3 или 4 позиции за секунду. (Какой BTW является априорно относительно медленным, но тогда это может зависеть от аппаратного обеспечения, схемы данных и других особенностей.) Конечно, вам нужно будет учитывать количество дефрагментации времени и сбалансировать это с временем, утерянным медленным обновлением чтобы найти оптимальную частоту для дефрагментации.

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

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

+0

Почему это поддерживается? OP спрашивает о sqlite, и вы бросаете на него функцию mysql. –

+0

@sixfeetsix: О, мой! Вы правы ... », должно быть, неправильно прочитали тег/вопрос. Также SQLite объясняет это 3-4 рецензирования в секунду. Ваш ответ намного правдоподобен, я сразу же его пойду. Возьмите сердце, ваше. скоро поднимутся до вершины, я надеюсь. – mjv

+0

hehe cool спасибо за + –

Смежные вопросы