Мы запускаем веб-приложение с поддержкой базы данных для анализа данных, в настоящее время основанное на C#.NET с EntityFramework на сервере и в основном с фреймворками HTML+Javascript на стороне клиента (на основе Интернета).
Наше приложение регулярно получает данные измерений X/Y в больших объемах, т. е. 1e6 или более, загруженные пользователями или полученные другой инфраструктурой.
В настоящее время у нас есть таблица в MSSQL под названием Values
с id, series_id as int; x, y, z as float
. Эта таблица представляет собой BULK INSERT
заполняется данными, когда клиент загружает их, и соответствующие метаданные сохраняются в Series
стол. Общий размер БД в настоящее время приближается к 1 ТБ, 99,99% из которых составляет Values
данные.
Этот подход был прост в реализации, но у него есть несколько недостатков, которые со временем сделали его сложным и медленным:
- мы должны вставлять фрагменты, чтобы не перегружать процесс IIS, который его предварительно обрабатывает (в настоящее время 200 000 точек данных на фрагмент).
- Требования к памяти процесса IIS во время ВСТАВКИ огромны (>1500 МБ для 200 МБ данных).
- вставка происходит слишком медленно (5 миллионов записей составляют 100 МБ, вставка занимает >30 секунд даже при использовании МАССОВОЙ ВСТАВКИ).
- во время ВСТАВКИ вся таблица блокируется, т. е. одновременно может вставлять только один пользователь
- извлечение данных также происходит довольно медленно, запрос записей 1e6 иногда занимает >10 секунд
- удаление серий с записями >1e6 регулярно приводит к тайм-аутам на стороне веб-приложения.
Данные никогда не выбираются частично, поэтому нам на самом деле не нужно, чтобы они были в таблице. НО он "уменьшен" для отображения перед отправкой клиентам, т. Е. записи 1e6 по умолчанию, т. е. в 99% случаев использования, уменьшены до 2000 или 10 000 записей перед отправкой клиенту. Этот набор кэшируется на клиенте, но если новый клиент запрашивает тот же набор, он обрабатывается снова. В таблице значений также есть индекс на series_id
который занимает больше места на диске, чем сама таблица.
Мне интересно, имеет ли смысл изменить этот формат хранения на хранилище больших двоичных объектов в "Значениях" с собственным форматом данных (CSV или JSON или двоичный файл) и, возможно, дополнительными столбцами с предварительно обработанными "уменьшенными" наборами данных для отображения, которые можно отправлять клиентам без изменений (например, в JSON). Так что новый Values
формат таблицы будет примерно таким
id, series_id, data(blob), reduced_data(blob)
и был бы только один Value
по Series
запись, а не 1e6 или более. Уменьшенный набор данных будет создан один раз при получении загруженных данных, а затем использоваться для отображения по запросу клиентов
Я потеряю частичный контроль над values
по идентификатору или значению X/Y, но значения никогда не выбираются на основе чего-либо, кроме id
или series_id
так что в настоящее время это не является ограничением. Итак, вот мои вопросы:
- Имеет ли это вообще смысл? Я ожидаю, что создание и удаление большого набора данных BLOB-объектов всегда будет значительно быстрее, чем создание и удаление 1 000 000 отдельных записей. Правда?
- Двоичный большой двоичный объект или CSV/JSON/.. КАПЛЯ? Самый простой подход к хранению больших двоичных объектов, конечно, состоит в том, чтобы создать огромный фрагмент CSV или JSON и сохранить его (возможно, в сжатом виде) в базе данных. Пользовательский двоичный формат данных был бы еще меньше, но его нужно было бы преобразовать в JSON перед отправкой клиентам.
У меня такое чувство, что дополнительные проблемы, связанные с двоичными форматами данных, могут того не стоить, и лучше сжать большой двоичный объект CSV/JSON, чем изобретать двоичный формат. Правда?
Как насчет других недостатков пятен, о которых я, возможно, даже не знаю? Ограничения по размеру, похоже, не являются проблемой, varbinary(MAX)
этого достаточно. Мне не нужен индекс для значений внутри большого двоичного объекта, только для метаданных (которые находятся в таблице рядов).
Мысли?