Какова наилучшая практика для представления временных интервалов в хранилище данных?

В частности, я имею дело с типом 2 медленно изменяющимся размером и должен представлять временной интервал, на который была активна определенная запись, т.е. для у каждой записи у меня есть StartDate и EndDate. Мой вопрос заключается в том, следует ли использовать закрытый ([StartDate, EndDate]) или наполовину открытый ([StartDate, EndDate)) для представления этого, т.е. Включать ли последнюю дату в интервал или нет. Чтобы взять конкретный пример, скажем, запись 1 была активна с 1-го дня до 5-го дня, а с 6-го дня запись 2 стала активной. Я делаю EndDate для записи 1 равным 5 или 6?

В последнее время я пришел к мысли о том, что половина открытых интервалов лучше всего основана на, в частности, Dijkstra: Почему нумерация должна начинаться с нуля, а также соглашения для разбиения массива и функции range() в Python. Применяя это в контексте хранилища данных, я бы увидел преимущества соглашения с открытым интервалом наполовину:

  • EndDate-StartDate дает время, в которое была активна запись.
  • Проверка. Стартовая запись следующей записи будет равна EndDate предыдущей записи, которую легко проверить.
  • Future Proofing: если позже я решит изменить мою гранулярность от ежедневного до более короткого, то дата переключения все еще остается точной. Если я использую закрытый интервал и сохраняю EndDate с отметкой времени полуночи, тогда мне придется отрегулировать эти записи для этого.

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

Заранее благодарим за любые идеи и комментарии.

Ответ 1

Я видел как закрытые, так и полуоткрытые версии. Я предпочитаю полуоткрытый по причинам, о которых вы заявили.

По-моему, полуоткрытая версия делает понятное поведение более понятным и "безопаснее". Предикат (a <= x < b) ясно показывает, что b предназначен вне интервала. В отличие от этого, если вы используете закрытые интервалы и задаете (x BETWEEN a AND b) в SQL, то, если кто-то неправильно использует enddate одной строки в качестве начала следующего, вы получите неправильный ответ.

Сделайте последнюю дату окончания по умолчанию самой большой датой, которую поддерживает ваша СУБД, а не null.

Ответ 2

В общем, я согласен с ответом Дэвида (проголосовали), поэтому я не буду повторять эту информацию. Кроме того:

Вы действительно имели в виду наполовину открытый ([StartDate, EndDate])

Даже в этом "полуоткрытом" есть две ошибки. Одна из них - прямая ошибка нормализации, которая, конечно же, реализует повторяющиеся данные, которые вы определяете в ходе обсуждения, которые доступны в виде производных данных, и их следует удалить.

  • Для меня Half Open (StartDate)
  • EndDate получен из следующей строки.
  • это лучшая практика.
  • это не обычное использование, потому что (а) обычные разработчики в эти дни не знают и (б) они слишком ленивы или не знают, как закодировать необходимый простой подзапрос
  • он основан на опыте, в крупных банковских базах данных

Подробнее см. ниже:

Ссылка на недавнюю очень похожую модель вопросов и данных

Ответы на комментарии

Вы, кажется, явно одобряете нормализованные проекты с естественными, содержательными ключами. Всегда ли оправдано отклонение от этого в хранилище данных отчетности? Я понимаю, что дополнительное пространство, предназначенное для суррогатных ключей и дубликатов столбцов (например, EndDate), является компромиссом для повышения производительности запросов. Однако некоторые из ваших комментариев об использовании кеша и увеличении ввода-вывода дисков заставляют меня подвергать сомнению это. Я был бы очень заинтересован в ваших данных по этому поводу.

  • Да. Абсолютно. Любой здравомыслящий человек (который не изучает информатику из wiki) должен подвергнуть сомнению это. Это просто противоречит законам физики.

  • Вы можете понять, что многие люди, не понимая нормализации или базы данных (вам нужно 5NF), производят Unnormalised медленные кучи данных, и их знаменитое оправдание (написанное "гуру" ) "денормализировано для производительности"? Теперь вы знаете, что это экскременты.

  • Те же самые люди, не понимая нормализацию или хранилища данных (вам нужно 6NF), (a) создайте копию базы данных и (б) всевозможные странные и прекрасные структуры для "улучшать" запросы, включая (c) еще большее дублирование. И угадайте, каково их оправдание? "denormalised for performance".

    • Это преступление, и "гуру" не лучше, они подтверждают его.

    • Я бы сказал, что эти "гуру" являются всего лишь "гуру" , потому что они обеспечивают псевдонаучную основу, которая оправдывает не-науку большинства.

    • ложная информация больше не верна, повторяя ее, и Бог знает, что они повторяют ее до бесконечности .

  • Простая истина (недостаточно сложная для людей, которые оправдывают хранилища данных с помощью (1) (2) (3)), заключается в том, что 6NF, выполненный правильно, является хранилищем данных. Я предоставляю базу данных и хранилища данных из тех же данных на скоростях склада. Нет второй системы; нет второй платформы; нет копий; нет ETL; синхронизация без сохранения копий; нет пользователей, которые должны перейти в два источника. Конечно, для преодоления ограничений SQL требуется умение и понимание производительности, а также немного специального кода (вы не можете указать 6NF в DDL, вам нужно реализовать каталог).

    • зачем внедрять StarSchema или SnowFlake, когда чистая нормализованная структура уже имеет полную возможность Dimension-Fact. ,
  • Даже если вы этого не сделали, если вы только что сделали традиционную вещь и ETLed эту базу данных в отдельную систему datawarehouse, внутри нее, если вы устранили дублирование, уменьшили размер строки, уменьшили индексы, конечно, это было бы беги быстрее. В противном случае это бросает вызов законам физики: толстые люди бегут быстрее, чем худые люди; корова бежит быстрее лошади.

    • достаточно справедливо, если у вас нет нормализованной структуры, тогда что-нибудь, пожалуйста, чтобы помочь. Поэтому они придумывают StarSchemas, SnowFlakes и всевозможные проекты Dimension-Fact.

И, пожалуйста, поймите, только un_qualified, in_experienced люди верят всем этим мифам и магии. У образованных опытных людей есть свои трудолюбивые истины, они не нанимают врачей-ведьм. Эти "гуру" только подтверждают, что толстый человек не выигрывает гонку из-за погоды или звезд; ничего, кроме того, что решит проблему. Несколько человек получают свои трусики в узел, потому что я прям, я говорю, что толстый человек проливает вес; но истинная причина, по которой они расстраиваются, - это проколоть их заветные мифы, которые делают их оправданными жирными. Люди не любят меняться.

  • Одна вещь. Всегда ли оправданно отклоняться. Правила не черно-белые; они не являются едиными правилами в изоляции. Разумный человек должен рассмотреть все вместе; расставить приоритеты для контекста. Вы не найдете ни всех ключей Id iot, ни нулей Id iot в моих базах данных, но каждый ключ Id был тщательно рассмотрен и обоснован.

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

    • Но никогда не начинайте с суррогатов. Это серьезно затрудняет вашу способность понимать данные; Нормализация; моделировать данные.

      • Вот один ▶ вопрос/ответ ◀ (из многих!), где человек застрял в процессе, не в состоянии идентифицировать даже основные сущности и отношения, потому что он застрял на всех клавишах Id iot. Проблема решена без обсуждения, на первой итерации.
        .
  • Хорошо, еще одна вещь. Изучите эту тему, получите опыт и дальнейшую работу. Но не пытайтесь научить его или преобразовывать других, даже если свет горит, и вы очень хотите. Особенно, если вы в восторге. Зачем? Потому что, когда вы сомневаетесь в совете врача ведьмы, вся деревня будет линчевать вас, потому что вы нападаете на их заветные мифы, их комфорт; и вы нуждаетесь в моем опыте, чтобы гвоздь ведьм-врачей (просто проверьте на наличие доказательств его в комментариях!). Дайте ему несколько лет, получите свой настоящий опыт с трудом, а затем возьмите их.

Если вы заинтересованы, следуйте этому ▶ вопрос/ответ ◀ в течение нескольких дней, это будет отличный пример того, как следуйте методологии IDEF1X, как разоблачить и перенаправить эти идентификаторы.

Ответ 3

Ну, стандартный sql where my_field between date1 and date2 включен, поэтому я предпочитаю инклюзивную форму - не то, что другой ошибочен.

Дело в том, что для обычных запросов DW эти поля (rowValidFrom, rowValidTo) в основном не используются вообще, потому что внешний ключ в таблице фактов уже указывает на соответствующую строку в таблице измерений.

Это в основном необходимо во время загрузки (мы говорим здесь SCD типа 2), чтобы найти самый последний первичный ключ для соответствующего бизнес-ключа. В этот момент у вас есть что-то вроде:

select ProductKey
from dimProduct
where ProductName = 'unique_name_of_some_product'
  and rowValidTo > current_date ;

Или, если вы предпочитаете создавать ключевой конвейер перед загрузкой:

insert into keys_dimProduct (ProductName, ProductKey)  -- here ProductName is PK
select ProductName, ProductKey 
from dimProduct
where rowValidTo > current_date ;

Это помогает загружать, так как перед загрузкой легко кэшировать таблицу ключей в память. Например, если ProductName - это varchar (40) и ProductKey целое число, таблица ключей составляет менее 0,5 ГБ на 10 миллионов строк, легко кэшируется для поиска.

Другие часто наблюдаемые варианты включают were rowIsCurrent = 'yes' и where rowValidTo is null.

В общем случае используется одно или несколько из следующих полей:

  • rowValidFrom
  • rowValidTo
  • rowIsCurrent
  • rowVersion

в зависимости от конструктора DW и иногда используемого инструмента ETL, поскольку большинство инструментов имеют загрузочные блоки типа SCD.

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

Предположим, что я использую все поля row_.

rowValidFrom date       = 3 bytes
rowValidTo   date       = 3 bytes
rowIsCurrent varchar(3) = 5 bytes
rowVersion   integer    = 4 bytes

Это составляет 15 байт. Можно утверждать, что это слишком много 9 или даже 12 байтов - ОК.

Для 10 миллионов строк это составляет 150 000 000 байтов ~ 0,14 ГБ

Я искал цены с сайта Dell.

Memory ~ $38/GB
Disk   ~ $80/TB = 0.078 $/GB 

Я возьму здесь рейд 5 (три диска), поэтому цена диска будет равна 0,078 $/ГБ * 3 = 0,23 $/ГБ

Итак, для 10 миллионов строк, чтобы сохранить эти 4 поля на диске, стоит 0.23 $/GB * 0.14 GB = 0.032 $. Если всю таблицу измерений нужно кэшировать в память, цена этих полей будет 38 $/GB * 0.14GB = 5.32 $ на 10 миллионов строк. Для сравнения, пиво в моем местном пабе стоит ~ 7 $.

Год 2010, и я ожидаю, что у моего следующего ноутбука будет 16 ГБ памяти. Вещи и (лучшие) практики меняются со временем.

EDIT:

Произошел ли какой-то поиск за последние 15 лет емкость диска среднего компьютера увеличилась примерно в 1000 раз, а память - в 250 раз.