Разработка схемы данных с общими и произвольными атрибутами - PullRequest
0 голосов
/ 01 марта 2011

Я не уверен, имеет ли название смысл, но вот моя общая проблема:

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

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

Вот надуманный пример:

Event Table:
  int Id
  datetime Occured_On
  uniqueidentifier UserId --> Users table
  int Category (the type of event) --> Categories table
  text Summary (textual summary of the event)
  text EventSource (specifies whether this is a DesktopEvent or MobileEvent)

Тогда каждое устройство имеет свой собственный набор данных для каждого события.Например:

DesktopEvent
  int Id
  int EventId --> Event table
  text Hostname
  text LoggedInUsername

MobileEvent
  int Id
  int EventId --> Event table
  int PlatformId 
  text ESN

...

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

results = SELECT * FROM Event DESCENDING Occured_On LIMIT 5. 

foreach (result in results)
{
    if (result.EventSource == "DesktopEvent")
       data = SELECT * FROM DestkopEvent WHERE EventId == result.EventId

    ...
}

Это кажется очень неэффективным.

Это еще более усложняется тем, что может быть много разных источников событий, а не только 2 (DesktopEvent и MobileEvent), как указано выше.Попытка объединить более 10 таблиц, для которых проверка не является NULL, кажется хуже, чем выше.

Есть ли лучший способ структурировать эти данные?Большое спасибо.

Ответы [ 3 ]

2 голосов
/ 01 марта 2011

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

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

Каждый уникальный набор атрибутов принадлежит отдельным таблицам; эти таблицы называются подтипами. В моделировании данных «супертип» и «подтип» не имеют ничего общего с концепциями объектно-ориентированного программирования, в которых используются одни и те же слова. Одни и те же слова, совершенно разные значения. Будьте осторожны с этим.

Похоже, таблица "события" - это ваш супертип. «Настольные события» и «Мобильные события» - это два из нескольких подтипов.

Если это так, вы, вероятно, на правильном пути. Неэффективность только очевидна, а не реальна. Настоящая правда в том, что настольные и мобильные события для вас разные вещи, и поэтому они должны храниться в разных таблицах. А хранение их в разных таблицах делает ограничения целостности бесконечно проще для реализации. В конце концов, это то, для чего предназначены базы данных SQL. Запросы могут использовать индексы.

Обычно подтипы супертипа и «n» отображаются на «n» + 1 таблицы и «n» представления. У вас есть одна таблица для каждого из подтипов 'n', плюс одна таблица для супертипа. Вы также создали бы одно представление для каждого подтипа; каждое представление объединяет один подтип с супертипом. Вы обычно используете представления, а не используете таблицы подтипов напрямую. Но вы можете использовать таблицу супертипов напрямую - например, для получения последних пяти событий.

Поиск SO по терминам супертип и подтип. SO пользователь PerformaceDBA и я оба писали о них более одного раза. (Приношу извинения тем, кто взвешивал реляционные супертипы и подтипы; у меня много проблем с запоминанием имен.)

1 голос
/ 01 марта 2011

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

Например

SELECT * FROM (
SELECT de.*, e.* 
FROM DestkopEvent  de , Event e
WHERE EventId == e.EventId
ORDER BY e.occurred_on desc
) 
WHERE rownum < 6

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

1 голос
/ 01 марта 2011

Один из вариантов - сохранить все такие данные, относящиеся к событию, в таблице стилей EAV:

http://en.wikipedia.org/wiki/Entity-attribute-value_model

Таким образом, вам могут понадобиться только две таблицы - таблица EVENT и таблица EVENT_DETAILS. Например, если у вас есть ID события рабочего стола = 12, в таблице EVENT_DETAILS может быть следующее:

1, 12, hostname, myhost
2, 12, loggedInName, myname
...
25, 17, esn, <esn value> 
etc.

Итак, вы смешиваете подробные данные для разных типов событий в одной таблице. Эта может быть более неэффективной для запроса, но это простая, хорошо понимаемая модель, которая поддается расширению и динамическим обработкам / представлениям данных.

Если вам нужно оптимизировать подобные вещи, вы можете взглянуть на колоночно-ориентированные БД:

http://en.wikipedia.org/wiki/Column-oriented_DBMS

...