Предостережение: ниже могут быть неточности. Я узнал о многих вещах по ходу дела, так что возьмите это с щепоткой соли. Это довольно долго, но вы можете просто прочитать параметры, с которыми мы играли, а затем перейти к заключению в конце.
Есть несколько уровней, где вы можете беспокоиться о производительности записи SQLite:
Мы посмотрели на те, которые выделены жирным шрифтом. Конкретные параметры были
- Кэш записи на диск. Современные диски имеют кэш-память RAM, которая используется для оптимизации записи на диск относительно вращающегося диска. Если этот параметр включен, данные могут быть записаны в виде блоков, вышедших из строя, поэтому в случае сбоя вы можете получить частично записанный файл. Проверьте настройку с помощью hdparm -W / dev / ... и установите его с помощью hdparm -W1 / dev / ... (чтобы включить его и -W0 для его выключения).
- Барьер = (0 | 1). Много комментариев онлайн, говорящих: «Если вы работаете с барьером = 0, значит, не включено кэширование записи на диск». Вы можете найти обсуждение барьеров на http://lwn.net/Articles/283161/
- data = (журнал | упорядоченный | обратная запись). Посмотрите на http://www.linuxtopia.org/HowToGuides/ext3JournalingFilesystem.html описание этих параметров.
- совершают = N. Сообщает ext3 синхронизировать все данные и метаданные каждые N секунд (по умолчанию 5).
- SQLite прагма синхронный = ON | OFF. Когда ON, SQLite будет гарантировать, что транзакция будет «записана на диск» перед продолжением. Отключение этого по существу делает другие настройки в значительной степени неактуальными.
- SQLite прагма cache_size. Управляет тем, сколько памяти SQLite будет использовать для хранения в кеше. Я попробовал два размера: один, где вся БД помещалась в кеш, и другой, где кэш был наполовину от максимального размера БД.
Узнайте больше о параметрах ext3 в документации ext3 .
Я провел тесты производительности по ряду комбинаций этих параметров. Идентификатор представляет собой номер сценария, о котором говорится ниже.
Я начал с конфигурации по умолчанию на моей машине, как сценарий 1. Сценарий 2 - это то, что я считаю «самым безопасным», а затем попробовал различные комбинации, где это уместно / предложено. Это, вероятно, проще всего понять с помощью карты, которую я в итоге использовал:
Я написал тестовый скрипт, который выполнял много транзакций со вставками, обновлениями и удалениями, все в таблицах с только INTEGER, только TEXT (со столбцом id) или смешанными. Я запускал это несколько раз для каждой из приведенных выше конфигураций:
Два нижних сценария - это № 6 и № 17, которые имеют «pragma synchronous = off», поэтому неудивительно, что они были самыми быстрыми. Следующий кластер из трех - № 7, № 11 и № 19. Эти три выделены синим цветом на «карте конфигурации» выше. По сути, конфигурация включает в себя кэш записи на диск, барьер = 0 и набор данных, отличный от «журнала». Изменение фиксации между 5 секундами (# 7) и 60 секундами (# 11), кажется, не имеет большого значения. В этих тестах, кажется, не было особой разницы между data = order и data = writeback, что меня удивило.
Тест смешанного обновления - это средний пик. Существует группа сценариев, которые более явно медленнее в этом тесте. Это все с данными = журнал . В противном случае между другими сценариями не так много.
У меня был другой тест синхронизации, который сделал более разнородную смесь вставок, обновлений и удалений для различных комбинаций типов. Это заняло намного больше времени, поэтому я не включил его в приведенный выше сюжет:
Здесь вы можете видеть, что конфигурация обратной записи (# 19) немного медленнее, чем упорядоченная (# 7 и # 11). Я ожидал, что обратная запись будет немного быстрее, но, возможно, это зависит от ваших шаблонов записи, или, может быть, я просто недостаточно читал в ext3 :-)
Различные сценарии несколько представляли операции, выполняемые нашим приложением. После выбора короткого списка сценариев мы запустили временные тесты с некоторыми из наших автоматических тестовых пакетов. Они были в соответствии с результатами выше.
Вывод
- Параметр commit, казалось, не имел большого значения, поэтому мы оставляем его на 5 с.
- Мы собираемся с кэшем записи на диск, барьер = 0 и данные = упорядочены . Я читал некоторые вещи онлайн, которые думали, что это плохая установка, и другие, которые, казалось, думали, что это должно быть по умолчанию во многих ситуациях. Я думаю, самое важное, что вы принимаете обоснованное решение, зная, какие компромиссы вы делаете.
- Мы не собираемся использовать синхронную прагму в SQLite.
- Установка прагмы SQLite cache_size, чтобы БД поместилась в памяти, улучшила производительность некоторых операций, как мы и ожидали.
- Вышеуказанная конфигурация означает, что мы немного больше рискуем. Мы будем использовать API резервного копирования SQLite, чтобы минимизировать опасность сбоя диска при частичной записи: делать снимок каждые N минут и сохранять последние значения M. Я тестировал этот API во время выполнения тестов производительности, и это придало нам уверенности, чтобы идти по этому пути.
- Если бы мы все еще хотели большего, мы могли бы взглянуть на проблему с ядром, но мы достаточно улучшили ситуацию, не заходя туда.
Спасибо @Huygens за различные советы и указатели.