У нас есть требование хранить 500 измерений в секунду, поступающих с нескольких устройств. Каждое измерение состоит из отметки времени, типа величины и нескольких векторных значений. Сейчас на измерение приходится 8 векторных значений, и мы можем считать это число постоянным для нужд нашего проекта-прототипа. Мы используем HNibernate. Тесты проводятся в SQLite (файл на диске db, а не в оперативной памяти), но, вероятно, будет производиться MsSQL.
Наш класс сущности Measurement - это класс, который содержит одно измерение и выглядит следующим образом:
public class Measurement
{
public virtual Guid Id { get; private set; }
public virtual Device Device { get; private set; }
public virtual Timestamp Timestamp { get; private set; }
public virtual IList<VectorValue> Vectors { get; private set; }
}
Векторные значения хранятся в отдельной таблице, так что каждое из них ссылается на свое родительское измерение через внешний ключ.
Мы сделали несколько вещей, чтобы обеспечить (разумно) эффективный сгенерированный SQL: мы используем Guid.Comb для генерации идентификаторов, мы сбрасываем около 500 элементов за одну транзакцию, размер пакета ADO.Net установлен на 100 (я думаю, что SQLIte не поддерживает пакетные обновления? Но это может пригодиться позже).
Проблема
Прямо сейчас мы можем вставить 150-200 измерений в секунду (что недостаточно быстро, хотя мы говорим об SQLite). Глядя на сгенерированный SQL, мы видим, что в одну транзакцию мы вставляем (как и ожидалось):
- 1 отметка времени
- 1 измерение
- 8 векторных значений
, что означает, что мы фактически делаем в 10 раз больше операций вставки в одну таблицу: 1500-2000 в секунду.
Если мы поместим все (все 8 векторных значений и временную метку) в таблицу измерений (добавив 9 выделенных столбцов), кажется, что мы можем увеличить скорость вставки до 10 раз.
Переключение на сервер SQL повысит производительность, но мы хотели бы знать, может ли быть способ избежать ненужных затрат на производительность, связанных с организацией базы данных прямо сейчас.
[Изменить]
С SQLite в памяти я получаю около 350 элементов в секунду (3500 вставок в одну таблицу), что, по моему мнению, примерно так же хорошо, как и с NHibernate (принимая этот пост для справки: http://ayende.com/Blog/archive/2009/08/22/nhibernate-perf-tricks.aspx).
Но я мог бы с таким же успехом переключиться на SQL-сервер и перестать предполагать, верно? Я обновлю свой пост, как только протестирую его.
[Update]
Я перешел на сервер SQL и сгладил свою иерархию, протестировал ее, сохранив 3000 измерений в секунду в течение нескольких часов, и, похоже, он работает нормально.