Я успадкував додаток, який асоціює багато сайтів із різними видами діяльності. Існує приблизно 100 різних типів діяльності, і кожен має різний набір 3-10 полів. Однак усі види діяльності мають принаймні одне поле дати (може бути будь-яка комбінація дати, дати початку, дати закінчення, запланованої дати початку тощо) та одного поля відповідальної особи. Усі інші поля сильно відрізняються, і поле дати дати необов’язково називатиметься "датою початку".
Створення однієї таблиці підтипів для кожного типу діяльності призведе до створення схеми зі 100 різними таблицями підтипів, з якими було б занадто безтурботно мати справу. Поточним рішенням цієї проблеми є збереження значень активності як пар ключ-значення. Це значно спрощена схема діючої системи для отримання точки впоперек.
Кожна активність має кілька полів активності; на кожному Сайті є кілька заходів, а таблиця SiteActivityData зберігає KVP для кожного SiteActivity.
Це робить (веб-додаток) дуже легким для кодування, тому що все, що вам потрібно зробити, це перебирати записи в SiteActivityData для певної діяльності та додавати до мітки та управління введенням для кожного рядка форму. Але проблем багато:
- Цілісність погана; можна помістити поле в SiteActivityData, яке не належить до типу активності, а DataValue - це поле варчару, тому цифри та дати потрібно постійно додавати.
- Повідомлення та спеціальний запит цих даних є складним, схильним до помилок та повільним. Наприклад, для отримання списку всіх видів певного типу, які мають Кінцеву дату у визначеному діапазоні, потрібні повороти та лиття вархарів до дат. Автори звітів ненавидять цю схему, і я не звинувачую їх.
Тож, що я шукаю, це спосіб зберігати велику кількість видів діяльності, які майже не мають спільних полів, щоб полегшити звітність. Я придумав поки що - це використовувати XML для зберігання даних про активність у форматі псевдо-noSQL:
Таблиця активності міститиме 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 індексувати його як значення дати? Мене хвилює, якщо я запитую за датою, потрібно буде привести рядок дати до значення дати та створити будь-який шанс використання індексу.