Денормализация данных и сериализация БД объектов C # - PullRequest
2 голосов
/ 14 апреля 2010

Я использую таблицу БД с различными объектами. Это означает, что я не могу иметь произвольное количество полей в нем, чтобы сохранить все виды различных объектов. Вместо этого я хочу сохранить только самые важные поля (даты, идентификаторы ссылок - вид внешнего ключа для различных других таблиц, наиболее важные текстовые поля и т. Д.) И дополнительное текстовое поле, в котором я хочу хранить более полные данные объекта.

самое очевидное решение - использовать XML строки и хранить их. Вторым наиболее очевидным выбором будет JSON, который обычно короче и, вероятно, также быстрее сериализуется / десериализуется ... И, вероятно, также быстрее. Но так ли это на самом деле? Мои объекты также не должны быть строго сериализуемыми, потому что JsonSerializer обычно может сериализовать что угодно. Даже анонимные объекты, которые также могут быть использованы здесь.

Что было бы наиболее оптимальным решением для решения этой проблемы?

Дополнительная информация

Моя БД сильно нормализована, и я использую Entity Framework, но в целях обеспечения внешней сверхбыстрой функциональности полнотекстового поиска я пожертвую немного денормализацией БД. Просто для информации я использую SphinxSE поверх MySql. Sphinx будет возвращать идентификаторы строк, которые я буду использовать для быстрого запроса к моей конгломератной таблице, оптимизированной по индексу, для получения наиболее важных данных из нее гораздо быстрее, чем для запроса нескольких таблиц по всей моей БД.

Моя таблица будет иметь такие столбцы, как:

  • RowID (автоинкремент)
  • EntityID (фактической сущности - но не имеет прямого отношения, поскольку это должно указывать на разные таблицы)
  • EntityType (чтобы я мог получить реальную сущность при необходимости)
  • DateAdded (запишите метку времени, когда она была добавлена ​​в эту таблицу)
  • Title
  • Metadata (сериализованные данные, относящиеся к конкретному типу сущности)

Эта таблица будет проиндексирована с помощью индексатора SPHINX. Когда я буду искать данные с использованием этого индексатора, я предоставлю серию EntityIDs и дату ограничения. Индексатору придется возвращать очень ограниченную выгружаемую сумму в RowIDs, упорядоченную по DateAdded (по убыванию). Затем я просто присоединю эти RowIDs к моей таблице и получу соответствующие результаты. Так что на самом деле это будет не полнотекстовый поиск, а поиск с фильтрацией. Таким образом, получение RowIDs будет очень быстрым, а получение результатов из таблицы будет намного быстрее, чем сравнение EntityIDs и DateAdded сравнений, даже если они будут правильно проиндексированы.

Ответы [ 4 ]

3 голосов
/ 14 апреля 2010

Единственное средство сохранения данных в базе данных SQL, которое не приведет к долговременной боли, - это на самом деле создать правильную, нормализованную, проиндексированную схему и расширять эту схему по мере необходимости, когда вы добавляете новые свойства в объекты вашего домена.

Пожалуйста, не пытайтесь "сериализовать" объекты в базу данных SQL.Если это действительно то, что вы хотите сделать, лучше использовать базу данных объектов, например db4o .


Обновление:

Вот как я сейчас понимаю проблемное пространство, основываясь на комментариях и обновлениях вопросов:

  • Структура таблицы уже нормализована;
  • Используется полнотекстовый движок (Sphinx)для оптимизации определенных поисков;
  • Конкретные "сериализованные" данные, обсуждаемые здесь, будут использоваться в качестве сводок или предварительных просмотров для отдельных результатов поиска и не представляют полные данные объекта.

Мой выбор для этого, в порядке предпочтения, будет:

  • Использовать функции движка FTS.
    Почти каждый движок FTS, включая Sphinx, позволяет настраивать пользовательскийатрибуты, которые будут храниться как часть каждого «документа».В настоящее время вы говорите, что храните только идентификатор строки, поэтому вы можете присоединиться к этой таблице.Ваши результаты вернутся намного быстрее, если вы вообще не присоединитесь и вместо этого сохраните эту информацию в самом полнотекстовом индексе.Есть некоторые довольно жесткие ограничения для того, что вы можете здесь указать, но если вы можете обойти ограничение, это ваш лучший вариант.

  • Документно-ориентированная база данных.
    Вы говорите, что вы даже не используете «полнотекстовую» часть Sphinx, вы просто используете ее для оптимизации определенных запросов.Почему бы тогда не вырезать среднего человека?Вы предложили JSON в качестве формата сериализации; MongoDB (чтобы указать только один вариант) поддерживает BSON изначально .Вы по-прежнему можете создавать индексы для общих столбцов, но в отличие от mysql, он на самом деле понимает формат BSON и способен хранить эти данные на lot более эффективно, чем строки JSON или XMLв реляционной базе данных.Если вы все равно денормализуетесь, у вас есть свобода выбора любого репозитория, который вы хотите;выберите тот, который лучше всего оптимизирован для ваших конкретных требований.

  • Наследование в одной таблице.
    Это общая схема, которая заменяет нормализацию на простоту отображения,В вашем случае вся цель - денормализация, так что это хорошая сделка.Это не очень хороший вариант, если столбцов будет сотен , но для 10 или 20 это будет хорошо, так как ваши данные будут храниться как "данные" и не окажут существенного влияния на производительность..

  • XML-столбцы.
    Преимущество этого подхода состоит в том, что данные не являются непрозрачными.Это на самом деле имеет смысл в контексте базы данных.Если вы должны сохранить эту информацию в базе данных mysql - вероятно, вы ожидаете выполнения некоторых специальных запросов - тогда вы можете также сохранить ее в формате, понятном для mysql,С другой стороны, если вы на 100% уверены, что вам никогда не понадобится "десериализовать" эти данные до тех пор, пока они не попадут в ваше приложение, то я, вероятно, согласился бы с ...

  • Пользовательский двоичный формат сериализации.
    Если вы должны сохранить данные в своей базе данных mysql и , вы точно знаете, что выВам никогда не нужно будет индексировать его или даже читать его содержимое из запроса , а затем не тратить драгоценный ввод-вывод на кодирование раздутого текста.Даже JSON раздут по сравнению с двоичным, потому что JSON должен хранить все имена свойств;если вы делаете свою собственную сериализацию, вы можете использовать один или два байта для определения типа, а затем десериализовать оставшиеся поля / свойства в известном порядке.Просто данные, без метаданных.Я бы даже не использовал .NET BinaryFormatter здесь, я бы создал свою собственную сильно оптимизированную версию. В конце концов, это должно быть быстро, быстро, быстро! , и каждый дополнительный байт, входящий в вашу таблицу, замедляет запрос. Возможно, вы даже сможете сжать некоторые данные GZip, в зависимости от того, что именно там.


Если бы я до сих пор не до конца понял ваши требования, я бы даже не рассмотрел другие варианты.

1 голос
/ 14 апреля 2010

Не делай этого. Это плохая идея.

Если вы действительно должны это сделать, я бы использовал XML. Например, SQL Server позволяет выполнять запросы к XMl, если поле имеет тип XML.

В некотором смысле вы делаете то, что делали объектно-ориентированные базы данных. Они потеряли популярность, потому что, по большей части, инструменты ORM, такие как Hibernate и Microsoft Entity Framework, позволяют вам получить лучшее из OO и реляционного мира.

0 голосов
/ 19 августа 2010

На самом деле я постоянно использую текстовые объекты в моей СУБД. При правильном использовании это может оказать положительное влияние на производительность и сэкономить на существовании и обслуживании многих таблиц и времени разработки. Идеально подходит для хранения часто меняющихся нереляционных метаданных о строке.

Хотя я бы рассматривал только использование текстовых блобов для объектов KVO (то есть не-сущностей - объектов, которые имеют смысл только с той строкой, с которой они сохраняются). Также не беспокойтесь, если вам нужно выполнить какие-либо манипуляции на стороне сервера, то есть запросить и т. Д.

Для тех, кто заинтересован, я разработал быстрый, упругий Type Serializer , который идеально подходит для хранения текстовых объектов в компактном, удобочитаемом текстовом формате.

0 голосов
/ 14 апреля 2010

Вы смотрели базы данных NoSql?

http://nosql -database.org /

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

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