Скорость вставки SQLite замедляется по мере увеличения числа записей из-за индекса

Оригинальный вопросФон

Общеизвестно, что SQLiteдолжен быть хорошо настроен для достижения скорости вставки порядка 50 тыс. вставок / с. Здесь много вопросов относительно медленной скорости вставки, а также множество советов и тестов.

Это такжеутверждает, что SQLite может обрабатывать большие объемы данныхс отчетами более 50 ГБ не вызывает проблем с правильными настройками.

Я следовал советам здесь и в других местах, чтобы достигнуть этих скоростей, и я счастлив с 35k-45k вставками / с. У меня проблема в том, что все тесты показывают только быструю скорость вставки с записями <1м. Я вижу, чтоскорость вставки обратно пропорциональна размеру таблицы.

вопрос

Мой вариант использования требует хранения 500м до 1b кортежей ([x_id, y_id, z_id]) в течение нескольких лет (1 млн строк / день) в таблице ссылок. Все значения представляют собой целочисленные идентификаторы от 1 до 2 000 000. Существует один индекс наz_id.

Производительность велика для первых 10-метровых строк, ~ 35 тыс. Вставок / с, но к тому времени, когда в таблице будет ~ 20 млн. Строк, производительность начнет снижаться. Я сейчас вижу около 100 вставок / с.

Размер стола не особо большой. С 20-метровыми строками размер диска составляет около 500 МБ.

Проект написан на Perl.

Вопрос

Это реальность больших таблиц в SQLite или есть какие-то секретыподдержания высокая скорость вставки для таблиц с> 10 м строк?

Известные обходные пути, которых я бы хотел избежать, если это возможноУдалить индекс, добавить записи и переиндексировать: Это хорошо в качестве обходного пути, но не работает, когда БД все еще должна использоваться во время обновлений. Это не поможет сделать базу данных полностью недоступной дляx минут / деньРазбейте таблицу на более мелкие подтаблицы / файлыЭто будет работать в краткосрочной перспективе, и я уже экспериментировал с этим. Проблема в том, что мне нужно иметь возможность извлекать данные из всей истории при запросах, что означает, что в конечном итоге я достигну предела вложения в 62 таблицы. Присоединение, сбор результатов во временную таблицу и отсоединение сотен раз за запрос кажется большой работой и накладными расходами, но я попробую, если нет других альтернатив.Установлен SQLITE_FCNTL_CHUNK_SIZE: Я не знаю C (?!), Поэтому я предпочел бы не изучать это, просто чтобы сделать это. Я не вижу способа установить этот параметр с помощью Perl, хотя.ОБНОВИТЬ

СледующийПредложение тима что индекс вызывал все более медленное время вставки, несмотря на заявления SQLite о том, что он способен обрабатывать большие наборы данных, я провел сравнение производительности со следующими параметрами:

вставленные строки:14 миллионовпринять размер пакета:50000 записейcache_size прагма:10000page_size прагма:+4096temp_store прагма:Памятьjournal_mode прагма:удалятьsynchronous прагма:от

В моем проекте, как и в приведенных ниже результатах тестирования, создается временная таблица на основе файлов и используется встроенная поддержка SQLite для импорта данных CSV. Временная таблица затем присоединяется к принимающей базе данных, и наборы из 50 000 строк вставляются сinsert-select заявление. Поэтому время вставки не отражаетфайл в базу данных вставить раз, а точнеестол к столу вставить скорость. Принятие во внимание времени импорта CSV уменьшит скорости на 25-50% (очень грубая оценка, импорт данных CSV не займет много времени).

Очевидно, что наличие индекса приводит к замедлению скорости вставки при увеличении размера таблицы.

Из приведенных выше данных совершенно ясно, что правильный ответ может быть назначенТим ответ а не утверждения, что SQLite просто не может с этим справиться. Ясно этоМожно обрабатывать большие наборы данныхесли индексирование этого набора данных не является частью вашего варианта использования. Я использовал SQLite только для этого, в качестве бэкэнда для системы журналирования, в течение некоторого времени, что делаетне нужно индексировать, поэтому я был довольно удивлен замедлением, которое я испытал.

Заключение

Если кто-то захочет хранить большой объем данных с использованием SQLiteа также проиндексировать это,используя осколки может быть ответ. В конце концов я остановился на использовании первых трех символов хеша MD5 уникального столбца вz определить присвоение одной из 4096 баз данных. Поскольку мой вариант использования в основном архивный, схема не изменится, и запросы никогда не потребуют обхода осколков. Существует ограничение на размер базы данных, так как крайне старые данные будут сокращены и в конечном итоге отброшены, поэтому это сочетание шардинга, настроек прагмы и даже некоторыхденормализация дает мне хороший баланс, который, исходя из приведенного выше теста производительности, поддерживает скорость вставки не менее 10 тыс. вставок в секунду.

Ответы на вопрос(5)

Ваш ответ на вопрос