В какой момент имеет смысл хранить большой объем структурированных данных в виде большого двоичного объекта?

0

Вопрос

Мы запускаем веб-приложение с поддержкой базы данных для анализа данных, в настоящее время основанное на 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) этого достаточно. Мне не нужен индекс для значений внутри большого двоичного объекта, только для метаданных (которые находятся в таблице рядов).

Мысли?

blob database-performance sql-server
2021-11-15 20:49:09
1

Лучший ответ

1

Одним из основных преимуществ хранения файлов в Бд является ACID (Атомарность, Согласованность, Изоляция, долговечность) технология в DBs. Это позволяет нам безопасно вставлять все данные в разные таблицы при работе с данными. Когда вы сохраняете свои файлы в БД в виде большого двоичного объекта, у вас есть преимущество при копировании файлов в другое хранилище, потому что большой двоичный объект работает быстрее, чем операционная файловая система, и вы можете легко создавать резервные копии своих файлов. Но, если размер файла для каждой записи превышает 10-50-100 МБ, не рекомендуется хранить файлы в большом двоичном объекте. В этом случае длительность вставки записей в таблицу может занять 10-15-30 секунд. Это не очень хорошо, потому что транзакции тоже длятся так долго, и все таблицы во время транзакции в этом смысле блокируются, как вы знаете, и длительная блокировка этих таблиц также приведет к тому, что пользователи не смогут работать. Одним из интересных способов хранения файлов в виде больших двоичных объектов является технология больших двоичных объектов FILESTREAM, которая поддерживается только SQL Server. Вы можете получить более подробную информацию об этой технологии из этого

2021-11-18 21:34:15

Спасибо за указатель. Я провел сравнительный анализ вставок нескольких блоков данных объемом 50 МБ в примерную таблицу на нашем производственном сервере, и каждая из них заняла 1-2 секунды, что приемлемо. Но большой двоичный объект FILESTREAM-тоже хорошая идея.
Jens

На других языках

Эта страница на других языках

Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................