SQLite против сериализации на диск - PullRequest
5 голосов
/ 26 октября 2011

Я делаю некоторое сравнение производительности, идти ли на сериализацию данных или хранить их в БД. Приложение получает чертовски много данных (x ГБ), которые необходимо сохранить с минимальной скоростью 18 МБ / с (как сейчас)

Хранение в БД предлагает более простую функциональность с точки зрения поиска и доступа к данным в более позднее время, моментальных снимков данных, миграции данных и т. Д., Но мои тесты пока показывают огромную разницу во времени производительности.

Тест сохраняет 1000 объектов (около 7 сотен килобайт каждый). Либо в соответствующие столбцы в таблице, либо на диск, сохранив их как общий список. (SQLite заканчивается немного больше данных)

  1. Сохранение в SQLite v3, общий размер 745 МБ: 30,7 секунды (~ скорость: 24,3 МБ / с)
  2. Сериализация на диск, общий размер 741 МБ: 0,33 секунды (~ скорость: 2245 МБ / с)

Я не делал никаких настроек производительности для SQLite, просто использовал его из коробки с Fluent nHibernate и адаптером SQLite.Data (без транзакций), но сначала подумал, что это огромная разница.

Очевидно, я знаю, что прохождение через ORM mapper и DB для записи на диск дает дополнительные издержки по сравнению с сериализацией, но это было много.

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

Есть мысли?

----- Обновления (поскольку я продолжаю исследовать решения) ------

  • Оборачивая 1000 вставок в транзакции, время теперь составляло ~ 14 с = 53 МБ / с, однако, если я выбрасываю исключение на полпути, я теряю все свои данные.
  • Использование IStatelessSession сокращает время на 0,5-1 с
  • Не наблюдалось какого-либо прироста производительности при назначении идентификатора сущности вместо его автоматического назначения в таблице и, следовательно, избавления от (выберите row_generatedid ()) для каждой вставки sql. -> Id (x => x.Id) .GeneratedBy.Assigned ();
  • альтернатива nosync () в SQLite не является альтернативой, поскольку БД может быть повреждена в случае сбоя питания.

Ответы [ 3 ]

5 голосов
/ 26 октября 2011

Однажды у меня была похожая проблема , и я предлагаю вам пойти по пути SQLite.

Что касается ваших проблем с производительностью, я уверен, что вы получите значительное повышение, если вы:

  1. выполнить все INSERT в одной транзакции - запросы на запись должны получить (и снять) блокировку файла SQLite, это очень дорого с точки зрения дискового ввода-вывода, и вы должны заметить огромное повышение ***
  2. рассмотрите возможность использования нескольких INSERT (это, вероятно, не сработает для вас, поскольку вы полагаетесь на ORM)
  3. как упомянул @ user896756, вы также должны подготовить свои заявления

Тест 1: 1000 вставок

CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100));
INSERT INTO t1 VALUES(1,13153,'thirteen thousand one hundred fifty three');
INSERT INTO t1 VALUES(2,75560,'seventy five thousand five hundred sixty');
... 995 lines omitted
INSERT INTO t1 VALUES(998,66289,'sixty six thousand two hundred eighty nine');
INSERT INTO t1 VALUES(999,24322,'twenty four thousand three hundred twenty two');
INSERT INTO t1 VALUES(1000,94142,'ninety four thousand one hundred forty two');
  • PostgreSQL: 4,373
  • MySQL: 0,114
  • SQLite 2.7.6: 13.061
  • SQLite 2.7.6 (nosync): 0,223

Тест 2: 25000 вставок в транзакции

BEGIN;
CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100));
INSERT INTO t2 VALUES(1,59672,'fifty nine thousand six hundred seventy two');
... 24997 lines omitted
INSERT INTO t2 VALUES(24999,89569,'eighty nine thousand five hundred sixty nine');
INSERT INTO t2 VALUES(25000,94666,'ninety four thousand six hundred sixty six');
COMMIT;
  • PostgreSQL: 4.900
  • MySQL: 2,184
  • SQLite 2.7.6: 0,914
  • SQLite 2.7.6 (nosync): 0,757

*** Эти тесты для SQLite 2, SQLite 3 должен быть еще быстрее .

2 голосов
/ 26 октября 2011

Вы должны рассмотреть возможность использования скомпилированных операторов для sqlite.

Проверка это

В запросах на вставку / обновление наблюдается огромный прирост производительности, мне удалось увеличить время выполнения в 2–10 раз, используя скомпилированные операторы, хотя от 33 до 0,3 с - долгий путь.

С другой стороны, скорость выполнения SQLite зависит от схемы таблицы, которую вы используете, например: если у вас есть индекс для огромных данных, это приведет к медленной вставке.

0 голосов
/ 07 ноября 2011

После дальнейших исследований ответ немного смешивается с первоначальными результатами.

При тестировании результата с большими данными я получил другой результат.

Скорость передачи дискаограничено 126 МБ / с производителем и как я могу написать 750 МБ за долю секунды?Не уверен почему.Но когда я увеличил объем данных, скорость передачи при быстром снижении до ~ 136 МБ / с.

Что касается базы данных, при использовании транзакции я получил скорость до 90 МБ / с, используя IStatelessSession с большими объемами данных5-10GB).Это достаточно для наших целей, и я уверен, что он все еще может быть изменен с помощью скомпилированных операторов SQL и других при необходимости.

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