Здравствуйте, Pavel Dvorkin, Вы писали:
PD>>>Трансакцией "удаление — добавление", если БД.
S>>Вопрос был не "при помощи чего", а "в какой момент".
S>>Вот я взял и добавил в расписание рабочие дни на ближайшие 5 лет. Потом в какой то момент мне нужно пойти и добавить их ещё на следующие 5 лет.
PD>Ну и добавить новый элемент. Если он не пересекается по датам со старыми, никакой проблемы нет. Если пересекается — создать объединение, удалить старый, добавить новый.
Ты упорно игнорируешь вопрос.
В какой момент мне надо это сделать?
Первичная инициализация — понятно: вот мы
конструируем расписание. Например, по запросу пользователя, или по API сервиса такой запрос пришёл.
После этого идут запросы только к GetNext. Ну и как мне понять, что наступил момент для "удалить старый, добавить новый"?
PD>Так когда появился, тогда и сделать.
И? Каков будет алгоритм работы? "Как-то" найти в системе все экземпляры расписаний, которые зависят от расписания государственных праздников, и их перегенерировать?
PD>Я не пойму вопрос "в какой момент". По-моему, в тот, когда это изменение актуализируется.
Вижу, что не понимаешь. Что значит "актуализируется"? Вот пример выше — у нас есть 500к расписаний, которые
зависят от расписания государственных праздников. В архитектуре вычисляемых событий мы просто изменяем один экземпляр, на который ссылаются все эти полмиллиона остальных экземпляров, и за O(1) получаем 500к обновлённых расписаний.
Для случая материализации у нас полмиллиарда "строчек", которые нужно
а) найти по какому-то признаку (по какому? как мы вообще поймём, что расписание с ID = 1472 было построено с учётом расписания государственных праздников?)
б) удалить
в) нагенерировать новых.
Ладно, чёрт с ним с обновлением. Просто у нас есть расписание начисления процентов, в котором было 1000 строк.
Как мы поймём, что пора добавить в него ещё 1000 строк? По какому критерию?
Как мы будем "догенерировать" строчки к существующему расписанию? Ну вот была у нас некая функция CreateDailySchedule(Time timeOfDay). Она вернула нам ID сгенерированного расписания (или там ссылку на экземпляр таблицы событий в памяти). Она нам наплодила сколько-то строчек (сколько? даже это пока непонятно). Как будет выглядеть сигнатура функции, которая должна к этой таблице добавить продолжение? Как она будет устроена внутри? В какой момент и кто будет её вызывать?
PD>А тут пока что нет O(1). Дерево же.
У дерева размер O(N).
PD>Согласен, просто. Вот только это слишком "регулярное событие". Если бы все они были такими или иными, но столь же регулярными, то было бы просто. А если на это "ежедневно в 8.00" наложится еще хотя бы одно такое типа "ежедневно в 18.00" , то все станет менее просто.
Нет, не станет. Потому, что у нас появляется Union(Schedule s1, Schedule s2), у которого GetNextOccurence устроен вот так:
TimeStamp GetNextOccurence(TimeStamp start, TimeZone zone)
{
return Min(s1.GetNextOccurence(start, zone), s2.GetNextOccurence(start, zone));
}
Имеем O(1) по памяти, O(1) по времени работы. Вроде ж не rocket science, не?
PD>А если еще и добавится "по нечетным в 13.00", то станет совсем весело искать следующий. Хотя теоретически возможно.
Добавление
чего угодно работает ровно так, как я показал. Ну будет Union(Union(dailyAt0800, dailyAt1800), evensAt1300).
Остаётся вопрос, как реализовать evensAt1300. Но пока что у нас получалось сделать всё за O(1) и по времени, и по памяти, в связи с чем есть искушение продолжать думать в эту сторону.
Вместо того, чтобы моментально сдаться и перейти к O(log(N)) по времени и O(N) по памяти.
PD>Оно лишь означает, что для того, чтобы в БД был O(logN) поиск, достаточно INDEX в таблицу добавить, а если в ОП, то придется это дерево (Set, Map) самому делать. Разница небольшая, конечно, но с БД проще. В конце концов можно же и БД в ОП взять.
Пока что получается, что мы сначала берём неэффективный алгоритм, а потом в него добавляем накладные расходы от самой СУБД. Асимптотика-то не поменяется, а вот коэффициенты перед O будут примерно 1000 — это для СУБД в памяти. Не очень понятен ход мысли, который приводит к таким архитектурным решениям.
PD>Да и множества , возможно, тоже не нужны. Тебе же один элемент нужен , хватит и первый элемент брать.
Вот то-то и оно.
Но тут дело не в Java и не в C# — всё это будет вообще ни на одном из этих языков. Первична сама архитектура, а реализацию потом напилим как надо.