Я унаследовал приложение, которое связывает множество различных видов деятельности с сайтом. Существует около 100 различных видов деятельности, и каждый из них имеет различный набор из 3-10 полей. Однако все действия имеют как минимум одно поле даты (может быть любое сочетание даты, даты начала, даты окончания, запланированной даты начала и т. Д.) И одно поле ответственного лица. Все остальные поля сильно различаются, и поле даты начала не обязательно будет называться «Дата начала».
Создание одной таблицы подтипов для каждого типа деятельности привело бы к созданию схемы со 100 различными таблицами подтипов, что было бы слишком громоздко для решения. Текущее решение этой проблемы - сохранить значения активности в виде пар ключ-значение. Это очень упрощенная схема существующей системы, чтобы понять суть.
Каждое действие имеет несколько полей деятельности; каждый сайт имеет несколько действий, и таблица SiteActivityData хранит KVP для каждого объекта SiteActivity.
Это делает (веб-приложение) приложение очень простым для кодирования, потому что все, что вам действительно нужно сделать, - это перебрать записи в SiteActivityData для данного действия и добавить метку и элемент управления вводом для каждой строки в форму. Но есть много проблем:
- Целостность это плохо; в SiteActivityData можно поместить поле, которое не относится к типу действия, а DataValue является полем varchar, поэтому необходимо постоянно приводить числа и даты.
- Отчетность и специальные запросы этих данных сложны, подвержены ошибкам и медленны. Например, для получения списка всех действий определенного типа с конечной датой в указанном диапазоне требуются сводки и приведения типов к датам. Авторы отчетов ненавидят эту схему, и я их не виню.
Поэтому я ищу способ хранения большого количества действий, которые почти не имеют общих полей, чтобы упростить отчетность. До сих пор я придумал, как использовать XML для хранения данных активности в формате псевдо-noSQL:
Таблица Activity будет содержать XSD для каждого действия, что устраняет необходимость в таблице ActivityField. SiteActivity будет содержать ключ-значение XML, поэтому каждое действие для сайта теперь будет находиться в одной строке.
Деятельность выглядела бы примерно так (но я еще не полностью ее описал):
<SomeActivityType>
<SomeDateField type="StartDate">2000-01-01</SomeDateField>
<AnotherDateField type="EndDate">2011-01-01</AnotherDateField>
<EmployeeId type="ResponsiblePerson">1234</EmployeeId>
<SomeTextField>blah blah</SomeTextField>
...
Преимущества:
- XSD будет проверять XML, отлавливая ошибки, такие как помещение строки в числовое поле на уровне базы данных, что было невозможно при старой схеме, в которой все хранилось в varchar.
- Набор записей KVP, который используется для создания веб-форм, может быть легко воспроизведен с использованием
select ... from ActivityXML.nodes('/SomeActivityType/*') as T(r)
- Подзапрос xpath XML можно использовать для создания результирующего набора, в котором есть столбцы для даты начала, даты окончания и т. Д., Без использования сводной точки, что-то вроде
select ActivityXML.value('.[@type=StartDate]', 'datetime') as StartDate, ActivityXML.value('.[@type=EndDate]', 'datetime') as EndDate from SiteActivity where...
Кажется ли это хорошей идеей? Я не могу придумать другие способы хранения такого большого количества различных наборов свойств. Еще одна мысль, которая у меня возникла, - сохранить существующую схему и перевести ее в нечто более удобное для запросов в хранилище данных, но я никогда раньше не проектировал звездообразную схему и не знал, с чего начать.
Дополнительный вопрос: если я определю тег как имеющий тип данных даты в XSD с использованием xs:date
, собирается ли SQL Server индексировать его как значение даты? Я обеспокоен тем, что, если я сделаю запрос по дате, он должен будет привести строку даты к значению даты и исключить любую возможность использования индекса.