Я унаследовал приложение, которое связывает множество различных видов деятельности с сайтом. Существует около 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 индексировать его как значение даты? Я обеспокоен тем, что, если я сделаю запрос по дате, он должен будет привести строку даты к значению даты и исключить любую возможность использования индекса.
источник
Ответы:
Недостаточно репутации, чтобы прокомментировать сначала, так что поехали!
Если основной целью является создание отчетов, и у вас есть DW (даже если это не звездообразная схема), я бы рекомендовал попытаться включить это в звездообразную схему. Преимущества - быстрые, простые запросы. Недостатком является ETL, но вы уже подумываете о переносе данных в новый дизайн, и ETL в звездообразную схему, вероятно, проще построить и поддерживать, чем решение для оболочки XML (а SSIS включен в лицензию SQL Server). Кроме того, он запускает процесс признанного дизайна отчетности / аналитики.
Так как это сделать ... Похоже, у вас есть то, что известно как Бессмысленный Факт . Это пересечение атрибутов, которые определяют событие без связанной меры (например, продажная цена). У вас есть даты для некоторых или всех ваших мероприятий? Вероятно, у вас должно быть пересечение Активности, Сайта и Даты.
DimActivity
- Я предполагаю, что есть шаблон, который может позволить вам разбить их на хотя бы относительно общие столбцы. Если так, у вас может быть три? пять? размеры для занятий. В худшем случае у вас есть пара непротиворечивых столбцов, таких как имя деятельности, вы можете фильтровать их, и вы оставляете общие заголовки, такие как «Атрибут1» и т. Д. Для оставшихся случайных деталей.Вам не нужно все в измерении - там (вероятно) не должно быть никаких дат в измерении Activity - все они должны быть на самом деле, поскольку суррогатный ключ ссылается на измерение Date. Например, Дата, которая останется в измерении человека, будет датой рождения, потому что это атрибут человека. Дата посещения больницы зависит от факта, поскольку, помимо прочего, это событие на определенный момент времени, связанное с человеком, но оно не является признаком лица, посещающего больницу. Более актуальная дискуссия по факту.
DimSite
- кажется прямым, поэтому мы опишем суррогатные ключи здесь. По сути, это просто увеличивающийся уникальный идентификатор. Столбец Integer Identity является общим. Это позволяет разделить DW и исходные системы и обеспечивает оптимальные объединения в хранилище данных. Ваш естественный ключ или бизнес-ключ обычно сохраняется, но для технического обслуживания / проектирования не анализируется и не присоединяется. Пример схемы:DimDate
- атрибуты даты. Сделайте «умный ключ» вместо удостоверения личности. Это означает, что вы можете ввести значащее целое число, которое относится к дате для запросов, например WHERE DateSK = 20150708. Существует множество бесплатных сценариев для загрузки DimDate, и в большинстве из них включен этот смарт-ключ. ( один вариант )DimEmployee
- ваш XML включил это, если это более общее изменение в DimPerson, и заполните соответствующими атрибутами лица, поскольку они доступны и имеют отношение к отчетности.И ваш факт:
Вы можете переименовать их в факте, и вы можете иметь несколько ключей даты на событие. Факты, как правило, очень велики, поэтому избегать обновлений, как правило, хорошо ... если у вас есть несколько обновлений дат для одного события, вы можете попробовать удалить / вставить дизайн, добавив SK к факту, который позволяет выбирать строки «обновления» для удалить, а затем вставить последние данные.
Расширьте факт дату , чтобы все , что вам нужно:
StartDateSK, EndDateSK, ScheduledStartDateSK
.Все измерения должны иметь неизвестную строку, обычно с жестким кодом -1 SK. Когда вы загружаете факт, и у активности нет ни одной из включенных дат, она должна просто загрузить -1.
Фактом является набор целочисленных ссылок на ваши атрибуты, хранящиеся в измерениях, соединяйте их вместе, и вы получаете все свои данные в очень чистом шаблоне соединения, а факт, благодаря его типам данных, исключительно мал и быстр. Поскольку вы находитесь в SQL Server, добавьте индекс columnstore для дальнейшего повышения производительности. Вы можете просто уронить его и восстановить во время ETL. Как только вы попадаете в SQL 2014+, вы можете писать в индексы columnstore.
Если вы идете по этому пути, исследуйте Dimensional Modeling. Я бы порекомендовал методику Кимбалла . Существует также множество бесплатных руководств, но если это будет что-то иное, чем одноразовое решение, инвестиции, вероятно, того стоят.
источник