Самый эффективный метод сохранения сложных типов с переменными схемами в SQL.

Что я делаю

Я создаю таблицу SQL, которая обеспечит внутренний механизм хранения для объектов сложного типа. Я пытаюсь определить, как добиться этого с наилучшей производительностью. Мне нужно иметь возможность запрашивать каждое отдельное значение простого типа сложного типа (например, строковое значение города в сложном типе адреса).

Первоначально я думал, что могу хранить значения сложного типа в одной записи в виде XML, но теперь меня беспокоит производительность поиска при таком дизайне. Мне нужна возможность создавать схемы переменных "на лету", ничего не меняя в уровне доступа к базе данных.


Где я сейчас

Прямо сейчас я думаю создать следующие таблицы.

 TABLE:  Schemas
   COLUMN NAME       DATA TYPE
   SchemaId          uniqueidentifier
   Xsd               xml                 //contains the schema for the document of the given complex type
   DeserializeType   varchar(200)        //The Full Type name of the C# class to which the document deserializes.

 TABLE:  Documents
   COLUMN NAME       DATA TYPE      
   DocumentId        uniqueidentifier
   SchemaId          uniqueidentifier

 TABLE:  Values                            //The DocumentId+ValueXPath function as a PK
   COLUMN NAME       DATA TYPE      
   DocumentId        uniqueidentifier
   ValueXPath        varchar(250)
   Value             text

из этих таблиц при выполнении запросов я выполнял бы серию самообъединений в таблице значений. Когда я хочу получить весь объект по DocumentId, у меня будет общий скрипт для создания представления, имитирующего денормализованную таблицу данных сложного типа.


Что я хочу знать

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

1 - comparing the value of a text field versus of a varchar field.
2 - different kind of joins versus nested queries
3 - getting a view versus an xml document from the sql db
4 - doing some other things that I don't even know I don't know would be affecting my query but, I am experienced enough to know exist

Я был бы признателен за любую информацию или ресурсы об этих проблемах с производительностью в sql, а также за рекомендацию о том, как более эффективно подойти к этой общей проблеме.


Например,

Вот пример того, что я сейчас планирую делать.

У меня есть адрес класса С#, который выглядит как

public class Address{
     string Line1 {get;set;}
     string Line2 {get;set;}
     string City {get;set;}
     string State {get;set;}
     string Zip {get;set;
}

Экземпляр создается из new Address{Line1="17 Mulberry Street", Line2="Apt C", City="New York", State="NY", Zip="10001"}

его значение XML будет выглядеть так.

<Address>
   <Line1>17 Mulberry Street</Line1>
   <Line2>Apt C</Line2>
   <City>New York</City>
   <State>NY</State>
   <Zip>10001</Zip>
</Address>

Используя приведенную выше схему db, у меня будет одна запись в таблице схем с определением XSD схемы адреса xml. Этот экземпляр будет иметь уникальный идентификатор (PK таблицы Documents), который назначается SchemaId записи Address в таблице Schemas. Тогда в таблице значений будет пять записей, представляющих этот адрес.

Они будут выглядеть так:

DocumentId                              ValueXPath        Value
82415E8A-8D95-4bb3-9E5C-AA4365850C70    /Address/Line1    17 Mulberry Street
82415E8A-8D95-4bb3-9E5C-AA4365850C70    /Address/Line2    Apt C
82415E8A-8D95-4bb3-9E5C-AA4365850C70    /Address/City     New York
82415E8A-8D95-4bb3-9E5C-AA4365850C70    /Address/State    NY
82415E8A-8D95-4bb3-9E5C-AA4365850C70    /Address/Zip      10001

Только что добавил награду...

Моя цель состоит в том, чтобы получить ресурсы, которые мне нужны, чтобы предоставить моему приложению уровень доступа к данным, который полностью доступен для поиска и имеет схему данных, сгенерированную на уровне приложения, которая не требует прямой настройки базы данных (т.е. создание новой таблицы SQL) в чтобы добавить новый совокупный корень в модель предметной области.

Я открыт для возможности использования .NET-совместимых технологий, отличных от SQL, но я потребую, чтобы любые такие предложения были адекватно обоснованы, чтобы их можно было рассмотреть.


person smartcaveman    schedule 23.02.2011    source источник
comment
Вы повторно реализуете РСУБД внутри РСУБД. БД уже может это сделать - вот для чего нужны операторы DDL, такие как создание таблицы и создание схемы .... Совершенно серьезно. Просто откажитесь от вознаграждения и потратьте свое время на работу над тем, как ваше приложение может определить, какие таблицы/индексы создавать и когда.   -  person Ben    schedule 10.03.2011
comment
@ Бен, в этом есть смысл. Что мне не нравится, так это то, что это значительно усложняет ассоциации, но я полагаю, что я также могу автоматически генерировать их.   -  person smartcaveman    schedule 10.03.2011
comment
Основная проблема заключается в том, что вы не разделили данные и объекты чистым и функциональным образом; они совершенно разные и требуют совершенно разных методологий проектирования. Как только вы примените их, у вас будет высокая производительность с обеих сторон. Но подход к этому так, как вы это делаете, с мышлением Object или XML, и db только как место хранения, является гарантированной катастрофой производительности и обслуживания.   -  person PerformanceDBA    schedule 13.03.2011
comment
@PerformanceDBA, вот почему я задал вопрос, братан   -  person smartcaveman    schedule 13.03.2011
comment
@умныйпещерный. В этом случае откажитесь от объектов и XML и публикуйте только все, что знаете о данных. Проверьте мой ответ на этот вопрос и этот вопрос   -  person PerformanceDBA    schedule 14.03.2011
comment
@PerformanceDBA, что вы думаете о CQRS?   -  person smartcaveman    schedule 14.03.2011
comment
@умныйпещерный. Это не имеет значения, потому что основано на представлении о том, что вам нужны денормализованные и нормализованные базы данных, что неверно. Обосновывать наличие двух баз данных (и дополнительного уровня CQRS) совершенно безумно. Это просто, гораздо проще и быстрее иметь правильно нормализованную реляционную базу данных. Этот ответ< /b> связано.   -  person PerformanceDBA    schedule 15.03.2011
comment
@PerformanceDBA, спасибо за все ресурсы. Похоже, вы говорите, что мой общий подход неверен, и что сам вопрос проблематичен. Моя цель - создать общее решение, но, похоже, вы говорите, что это не очень хороший подход. Я понимаю, что любое универсальное решение будет снижать производительность. Однако я не уверен, что эта проблема должна перевешивать преимущества универсального решения для сохраняемости в отношении реальных бизнес-сценариев. Я собираюсь исследовать некоторые моменты, которые вы сделали, и я ценю качественную информацию.   -  person smartcaveman    schedule 15.03.2011
comment
@PerformanceDBA, какие рекомендации вы могли бы предложить для принятия решения о том, подходит ли сценарий для базы данных документов или реляционной базы данных?   -  person smartcaveman    schedule 15.03.2011
comment
@умныйпещерный. (оффлайн уже неделю) С удовольствием. Что ж, в наши дни я бы поместил документы в реляционную базу данных в виде больших двоичных объектов. Вы получаете всю мощь Relational plus docs. Большинство из них имеют функцию полнотекстового поиска, если вам это нужно. Это прекрасно работает для IEC/ISO/ANSI Standard SQL, двигателей корпоративного класса; но не для несовместимых или фиктивных SQL. Я не видел оправдания для базы данных документа, которая действительно действительна (они просто делают одну вещь хорошо, а большинство плохо).   -  person PerformanceDBA    schedule 22.03.2011


Ответы (5)


Как насчет поиска решения на архитектурном уровне? Я также ломал голову над сложными графиками и производительностью, пока не обнаружил CQRS.

[запустить режим евангелиста]

  • Вы можете выбрать хранилище на основе документов или реляционное. Даже оба! (Источник событий)
  • Хорошее разделение задач: чтение модели и запись модели
  • Возьми свой торт и съешь его тоже!

Хорошо, есть начальное обучение / техническая кривая, которую нужно преодолеть;)

[конец режима евангелиста]

Как вы заявили: «Мне нужна возможность создавать схемы переменных на лету, ничего не меняя в уровне доступа к базе данных». Главное преимущество заключается в том, что ваша модель чтения может быть очень быстрой, поскольку она создана для чтение. Если вы добавите в смесь Event Sourcing, вы сможете удалить и перестроить свою модель чтения по любой схеме, которую вы хотите... даже "онлайн".

Есть несколько хороших фреймворков с открытым исходным кодом, таких как nServiceBus, которые экономят много времени и решают технические проблемы. Все зависит от того, насколько далеко вы хотите зайти в этих концепциях, на что вы готовы/можете потратить время. Вы даже можете начать с основ, если будете следовать подходу Грега Янга. Смотрите информацию по ссылкам ниже.

Видеть

person Derick Schoonbee    schedule 11.03.2011
comment
Мне интересно узнать больше о CQRS. Можете ли вы порекомендовать более полные ресурсы? - person smartcaveman; 15.03.2011
comment
На сайте cqrsinfo.com есть прекрасное 6-часовое подробное видео от Грега Янга, которое обязательно нужно посмотреть даже новичкам в CQRS. Тогда отлично подойдет группа Google. - person Derick Schoonbee; 16.03.2011

Почему-то то, что вы хотите, звучит как болезненная вещь в SQL. По сути, внутреннюю часть текстового поля следует рассматривать как непрозрачную, как при запросе к базе данных SQL. Текстовые поля не были созданы для эффективных запросов.

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

Ваша идея звучит так, будто вы хотите выполнить несколько объединений, синтаксический анализ XML и приложение XPath, чтобы получить значение. Это не кажется мне самым эффективным.

Итак, мой совет:

Дополнение согласно вашим пояснениям выше

Проще говоря, не переусердствуйте с этой вещью:

  • Если вы просто хотите сохранить объекты C#/.NET, просто используйте сериализацию XML уже встроен в фреймворк, единая таблица и покончено с этим.
  • Если вам по какой-то причине нужно хранить сложный XML, используйте специальное хранилище XML.
  • Если у вас есть фиксированная схема базы данных, но она слишком сложна для эффективных запросов, используйте хранилище документов в памяти, где вы храните денормализованную версию ваших данных для более быстрых запросов (или просто упростите свою схему базы данных).
  • Если вам действительно не нужна фиксированная схема, используйте только хранилище документов и вообще забудьте о каком-либо «определении схемы».

Что касается вашего решения, да, оно может работать как-то. Как и обычная схема SQL, если вы правильно ее настроите. Но для применения XPath вы, вероятно, будете анализировать весь XML-документ каждый раз, когда обращаетесь к записи, что было бы не очень эффективно для начала.

Если вы хотите проверить базы данных документов, есть драйверы .NET для CouchDB и MongoDB. база данных eXist XML предлагает ряд веб-протоколов, и вы, вероятно, можете легко создать клиентский класс с точки зрения VisualStudio. -и стрелять интерфейс. Или просто погуглите, кто уже сделал.

person averell    schedule 23.02.2011
comment
Я рассматривал что-то подобное, но я не очень осведомлен в этой теме. В настоящее время читает предоставленные вами ресурсы. Знаете ли вы что-нибудь об относительной производительности этих решений? - person smartcaveman; 23.02.2011
comment
Опять же, это зависит от запроса, который вы хотите выполнить, и конкретного механизма; но они обычно будут достаточно эффективными. С хранилищем документов вы, как правило, денормализуете свои данные, тем самым делая запросы простыми и быстрыми. Есть также люди, которые используют хранилища документов в качестве кеша для выполнения запросов к данным, которые исходно поступают из очень сложных таблиц SQL. Я предлагаю вам прочитать о различных решениях, чтобы увидеть, что подходит вам лучше всего. - person averell; 23.02.2011

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

Вы повторно реализуете РСУБД внутри РСУБД. БД уже может это сделать - для этого нужны операторы DDL, такие как create table и create schema....

Я предлагаю вам изучить «схемы» и безопасность SQL. При правильной настройке безопасности нет никаких причин, по которым вы не можете позволить своим пользователям создавать свои собственные таблицы для хранения атрибутов документов или даже генерировать их автоматически.

Редактировать: Немного более длинный ответ, если у вас нет полных требований немедленно, я бы сохранил данные как тип данных XML и запросил их с помощью запросов XPath. Это будет нормально для случайных запросов по небольшому количеству строк (менее нескольких тысяч, конечно).

Кроме того, ваша СУБД может поддерживать индексы через XML, что может быть еще одним способом решения вашей проблемы. CREATE XML INDEX в SqlServer 2008, например.

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

Я не знаю ваших требований, но если вы сами отвечаете за создание отчетов/запросов, это может быть подходом для использования. Если вам нужно дать пользователям возможность создавать свои собственные отчеты, это еще большая гора.

Я думаю, что я говорю: «Вы уверены, что вам нужно это сделать, и XML не может просто выполнить эту работу».

person Ben    schedule 10.03.2011
comment
это имеет большой смысл. Как бы вы справились с обновлением схемы модели и поддержанием допустимого состояния данных при таком подходе? - person smartcaveman; 15.03.2011
comment
спасибо - мне, вероятно, понадобится более высокая производительность, чем позволяет SQLXML. В настоящее время я изучаю несколько различных решений с открытым исходным кодом либо для базы данных документов, оптимизированной для запросов, либо для чего-то похожего на то, что вы изначально предложили. - person smartcaveman; 16.03.2011

Частично это будет зависеть от вашего механизма БД. Вы используете SQL Server, не так ли?

Отвечаю на ваши темы:

1 - Сравнение значения текстового поля и поля varchar: если вы сравниваете два поля db, поля varchar умнее. Nvarchar(max) хранит данные в юникоде размером 2*l+2 байта, где «l» — длина. Что касается проблем с производительностью, вам нужно будет подумать, насколько большими будут таблицы, чтобы выбрать лучший способ индексации (или нет) полей вашей таблицы. см. тему.

2. Иногда вложенные запросы легко создаются и выполняются, что также позволяет сократить время запроса. Но, в зависимости от сложности, было бы лучше использовать разные типы соединений. Лучший способ - попытаться сделать в обоих направлениях. Выполняйте два или более раз каждый запрос, поскольку механизм БД «компилирует» запрос при первом выполнении, а последующие выполняются намного быстрее. Измерьте время для разных параметров и выберите лучший вариант.

«Иногда вы можете переписать подзапрос, чтобы использовать JOIN и повысить производительность. Преимущество создания JOIN заключается в том, что вы можете оценивать таблицы в порядке, отличном от того, который определен запросом. Преимущество использования подзапроса заключается в том, что он часто не необходимо просмотреть все строки из подзапроса, чтобы оценить выражение подзапроса. Например, подзапрос EXISTS может вернуть TRUE при просмотре первой подходящей строки». – ссылка

3- В этом вопросе мало информации, но если вы получите XML-документ непосредственно из таблицы, было бы неплохо установить представление. Опять же, это будет зависеть от представления и документа.

4- Другие вопросы касаются общего количества записей, ожидаемых для вашей таблицы; индексация столбцов, в которой вам необходимо учитывать сортировку, объединение, фильтрацию, PK и FK. Каждая ситуация может потребовать различных подходов. Я предлагаю потратить некоторое время на чтение о вашем механизме базы данных и запросах, функционирующих и связанных с вашей системой.

Надеюсь, я помог.

person Alex    schedule 23.02.2011
comment
О 1) - Проблема не столько в размере, сколько в том, что текстовые поля имеют переменный размер в БД, и это затрудняет БД поиск материала в таблице (проще говоря). Вот почему вы должны иметь их в отдельной таблице, которую вы не используете для обычных запросов. И хотя некоторые базы данных предлагают некоторую индексацию для полнотекстового поиска, вам, вероятно, гораздо лучше использовать для такой задачи специальную систему полнотекстового поиска. - person averell; 24.02.2011

Интересный вопрос.

Я думаю, что вы можете задать неправильный вопрос здесь. Вообще говоря, пока у вас есть FULLTEXT индекс в вашем текстовом поле, запросы будут быстрыми. Гораздо быстрее, чем varchar, например, если вам нужно использовать подстановочные знаки.

Однако на вашем месте я бы сосредоточился на реальных запросах, которые вы собираетесь выполнять. Вам нужны логические операторы? Подстановочные знаки? Числовые сравнения? Вот где я думаю, вы столкнетесь с реальными проблемами производительности.

Я полагаю, вам понадобятся такие запросы, как:

  • "найти все адреса в штатах Нью-Йорк, Нью-Джерси и Пенсильвания"
  • "найти все адреса между номерами домов 1 и 100 на улице Малберри"
  • "найти все адреса, где отсутствует почтовый индекс, а город - Нью-Йорк"

На высоком уровне решение, которое вы предлагаете, состоит в том, чтобы где-то хранить ваш XML, а затем денормализовать этот XML в пары имя/значение для запросов.

Пары имя/значение имеют долгую и славную историю, но становятся громоздкими в ситуациях сложных запросов, потому что вы не используете встроенные оптимизации и концепции модели реляционной базы данных.

Некоторые уточнения, которые я бы рекомендовал, - это взглянуть на модель предметной области и, по крайней мере, посмотреть, можете ли вы выделить отдельные типы данных в столбец «значение»; вы можете получить "textValue", "moneyValue", "integerValue" и "dateValue". В приведенном вами примере вы можете разложить «адрес 1» на «номер дома» (в виде целого числа) и «название улицы».

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

person Neville Kuyt    schedule 09.03.2011