Здравствуйте, Буравчик, Вы писали:
Б>А как удобнее было бы складывать данные?
А вот за ответ на этот вопрос архитекторы и получают свои зарплаты Тут уже начинается — сколько этих данных, какие запросы к ним будут стучаться, как часто и в каких масштабах изменения, где надо вносить изменения задним числом (!) и как это всё будет меняться в ожидаемом будущем. Свою долю вносят фичи конкретной СУБД.
В целом, есть два основных варианта:
а) Основные операции идут с актуальными данными, а исторические в основном лежат. В этом случае нужен способ эффективно отделять текущие данные от прочих. В простом случае это может быть вышеупомянутый булёвый столбец. Дальше начинаются соображения о том, что актуальным данным хорошо бы лежать физически рядом и на быстых дисках, а исторические хорошо бы убрать подальше и на медленные. Поэтому могут делать отдельную таблицу актуальных данных и отдельную — исторических. Могут, например, партиционировать таблицу на "актуальную" и "историческую" части. А могут держать таблицу как историческую, а для быстрого чтения актуальных сделать materialized view.
б) Основные операции идут "на указанную дату". В этом случае естественное решение — снабжать каждую строку периодом активности, date_from / date_to. Но если данных сравнительно немного, а меняются сравнительно часто, то иногда делают слепки каждый день (чаще всего так поступают с курсами валют). Ещё один интересный вопрос: когда меняется одно поле, делать новую версию для этого поля (как в исходном примере) или для всей записи. Тратится больше места, зато быстрее выборка. Бывает, что и в этом варианте актуальные данные нужны чаще среднего — и снова начинаются приседания из предыдущего пункта.
Здравствуйте, wildwind, Вы писали:
W>Здравствуйте, Буравчик, Вы писали:
Б>>Обычный запрос, вроде. Б>>С индексами будет работать очень быстро.
W>Первые пару лет.
Вот смотри, ты уже вбросил данные про пару лет... При этом ты не в курсе задачи. Насколько там часто пишут данные. Насколько вообще важна история. Если там данные пишут не чаще раза в день, то оно и 100 лет будет работать отлично, всего то 300000 записей по одному свойству, да еще и индексом = 19 итераций поиска на каждое свойство.
Здравствуйте, vsb, Вы писали:
vsb>Здравствуйте, Буравчик, Вы писали:
vsb>>>Обычно добавляют булевский столбец типа актуальные данные или нет.
Б>>И при добавлении еще менять булевый столбец, зачем?
vsb>Чтобы запросы делать не через одно место.
А булевский столбец мы будем триггером обновлять по все таблице... отличный вариант.
Если принять, что update_id увеличивается с каждым обновлением, то примерно так:
with cte as (
select max(update_id) as last_update_id
from history as h
group by h.key
)
select h.update_id, h.key, h.value
from history as h
inner join cte on h.update_id = cte.last_update_id;
Здравствуйте, Слава, Вы писали:
С>А кого конкретно уволить-то? Автора темы или авторов BigQuery?
К BigQuery у меня претензий нет (возможно, потому, что я с ним не работал). А вот зачем складывать данные так, чтобы для тривиального запроса требовалось завязываться узлом — вопрос, назовём так, открытый.
Здравствуйте, Softwarer, Вы писали:
S>К BigQuery у меня претензий нет (возможно, потому, что я с ним не работал). А вот зачем складывать данные так, чтобы для тривиального запроса требовалось завязываться узлом — вопрос, назовём так, открытый.
Обычно добавляют булевский столбец типа актуальные данные или нет.
Здравствуйте, Softwarer, Вы писали:
S>К BigQuery у меня претензий нет (возможно, потому, что я с ним не работал). А вот зачем складывать данные так, чтобы для тривиального запроса требовалось завязываться узлом — вопрос, назовём так, открытый.
Здравствуйте, Буравчик, Вы писали:
vsb>>Обычно добавляют булевский столбец типа актуальные данные или нет.
Б>И при добавлении еще менять булевый столбец, зачем?
Здравствуйте, Softwarer, Вы писали:
S>Здравствуйте, Слава, Вы писали:
С>>А кого конкретно уволить-то? Автора темы или авторов BigQuery?
S>К BigQuery у меня претензий нет (возможно, потому, что я с ним не работал). А вот зачем складывать данные так, чтобы для тривиального запроса требовалось завязываться узлом — вопрос, назовём так, открытый.
Ок. И так задача, хранить курсы валют и получать их на заданную дату.
Как будешь делать?
Одна таблица точно будет: период, валюта, курс.
Для ускорения, если есть потребность дергать данные ну прям очень быстро и это критично, можно сделать вторую: валюта, курс.
На первую повесить триггер и при записи/обновлении/удалении обновлять запись во второй таблица.
Так?
Теперь представь что дергать актуальные данные надо хотя и часто, в алгоритме где они нужны, время работы такого запроса меньше 1% времени. Все еще надо вторую таблицу делать?
Здравствуйте, wraithik, Вы писали:
vsb>>Здравствуйте, Буравчик, Вы писали:
vsb>>>>Обычно добавляют булевский столбец типа актуальные данные или нет.
Б>>>И при добавлении еще менять булевый столбец, зачем?
vsb>>Чтобы запросы делать не через одно место.
W>А булевский столбец мы будем триггером обновлять по все таблице... отличный вариант.
Чего? При редактировании записи проставляешь false отредактированной записи, true новой. Какой ещё триггер? Вместо одного insert получаешь insert + update. Отличий почти нет. А производительность select-ов небо и земля. Если партиционировать, то вообще разницы не будет.
Здравствуйте, Softwarer, Вы писали:
S>А вот за ответ на этот вопрос архитекторы и получают свои зарплаты Тут уже начинается — сколько этих данных, какие запросы к ним будут стучаться, как часто и в каких масштабах изменения, где надо вносить изменения задним числом (!) и как это всё будет меняться в ожидаемом будущем. Свою долю вносят фичи конкретной СУБД.
Архитектор должен изучить требования, а потом принимать решения.
Может это все автору совсем не надо. Автор просто спросил запрос для его данных.
S>В целом, есть два основных варианта:
Насчет архитектуры, имхо:
— надо проектировать исходя из текущих (обозримых) потребностей, а не городить суперсистему, которая способна на все
— в случае сомнения в выборе проектного решения, выбрать абстракцию и выделить выбранное решение в отдельный модуль/класс, чтобы можно было в дальнейшем легко изменить решение (например, для повышения быстродействия)
Здравствуйте, vsb, Вы писали:
vsb>Здравствуйте, wraithik, Вы писали:
vsb>>>Здравствуйте, Буравчик, Вы писали:
vsb>>>>>Обычно добавляют булевский столбец типа актуальные данные или нет.
Б>>>>И при добавлении еще менять булевый столбец, зачем?
vsb>>>Чтобы запросы делать не через одно место.
W>>А булевский столбец мы будем триггером обновлять по все таблице... отличный вариант.
vsb>Чего? При редактировании записи проставляешь false отредактированной записи, true новой. Какой ещё триггер? Вместо одного insert получаешь insert + update. Отличий почти нет. А производительность select-ов небо и земля. Если партиционировать, то вообще разницы не будет.
Если инсерт в середину делаем? Или считаем только всегда в конец?
Тут либо сторед-проц пишем, либо триггер делаем. Твой вариант инсерт+апдейт приведет к тому, что кто-то забудет что-то сделать.
Здравствуйте, wraithik, Вы писали:
W>>>А булевский столбец мы будем триггером обновлять по все таблице... отличный вариант.
vsb>>Чего? При редактировании записи проставляешь false отредактированной записи, true новой. Какой ещё триггер? Вместо одного insert получаешь insert + update. Отличий почти нет. А производительность select-ов небо и земля. Если партиционировать, то вообще разницы не будет.
W>Если инсерт в середину делаем? Или считаем только всегда в конец?
Речь про историю изменений, что ещё за инсерт в середину. История всегда в конец дописывается.
W>Тут либо сторед-проц пишем, либо триггер делаем. Твой вариант инсерт+апдейт приведет к тому, что кто-то забудет что-то сделать.
Ну любители писать логику на стороне сервера могут и хранимку написать, я предпочитаю писать код в приложении, а не в базе, но сути это не меняет. Кто-то забудет, получит по башке и вспомнит. А так и триггер можно отключить, а то чего он мешает базу портить (: А триггер, если есть желание, будет достаточно простой: в update проверяем, что ставится false на тот флажок; в insert проверяем, что ставится true, а у (n-1)-й записи проставлен false. Всё вытаскивается моментально.
Здравствуйте, vsb, Вы писали:
vsb>Речь про историю изменений, что ещё за инсерт в середину. История всегда в конец дописывается.
Да что ты... Про изменения задним числом не слышал?
W>>Тут либо сторед-проц пишем, либо триггер делаем. Твой вариант инсерт+апдейт приведет к тому, что кто-то забудет что-то сделать.
vsb>Ну любители писать логику на стороне сервера могут и хранимку написать, я предпочитаю писать код в приложении, а не в базе, но сути это не меняет. Кто-то забудет, получит по башке и вспомнит. А так и триггер можно отключить, а то чего он мешает базу портить (: А триггер, если есть желание, будет достаточно простой: в update проверяем, что ставится false на тот флажок; в insert проверяем, что ставится true, а у (n-1)-й записи проставлен false. Всё вытаскивается моментально.
Это пофиг где ты пишешь. Должен быть атомарный вызов чего-то, что не сломает логику.
По мне так самое верное когда есть движок, который дает бизнес-объекты, и всю логику ты пишешь на них, а не лезешь каждый раз в SQL.
Здравствуйте, wraithik, Вы писали:
vsb>>Речь про историю изменений, что ещё за инсерт в середину. История всегда в конец дописывается.
W>Да что ты... Про изменения задним числом не слышал?
Про уголовную ответственность за подделку документов слышал (: Не, поменять-то можно, структура-то позволяет. Если это надо редко. Если это надо очень часто, другой вопрос, тут уже связный список надо делать.
W>>>Тут либо сторед-проц пишем, либо триггер делаем. Твой вариант инсерт+апдейт приведет к тому, что кто-то забудет что-то сделать.
vsb>>Ну любители писать логику на стороне сервера могут и хранимку написать, я предпочитаю писать код в приложении, а не в базе, но сути это не меняет. Кто-то забудет, получит по башке и вспомнит. А так и триггер можно отключить, а то чего он мешает базу портить (: А триггер, если есть желание, будет достаточно простой: в update проверяем, что ставится false на тот флажок; в insert проверяем, что ставится true, а у (n-1)-й записи проставлен false. Всё вытаскивается моментально.
W>Это пофиг где ты пишешь. Должен быть атомарный вызов чего-то, что не сломает логику. W>По мне так самое верное когда есть движок, который дает бизнес-объекты, и всю логику ты пишешь на них, а не лезешь каждый раз в SQL.
Ну да, это правильно. Хотя от запросов на SQL всё равно обычно никуда не уйти, но вставка/изменение лучше всего бы в одном месте, тем более, что и всякие права проверять централизованно проще и надёжней.
Здравствуйте, vsb, Вы писали:
vsb>Здравствуйте, wraithik, Вы писали:
vsb>>>Речь про историю изменений, что ещё за инсерт в середину. История всегда в конец дописывается.
W>>Да что ты... Про изменения задним числом не слышал?
vsb>Про уголовную ответственность за подделку документов слышал (: Не, поменять-то можно, структура-то позволяет. Если это надо редко. Если это надо очень часто, другой вопрос, тут уже связный список надо делать.
ХМ... причем тут документы и база данных. Да и от ошибок никто не застрахован. Ты живешь с воем идеальном программситком мирке. Где все по инструкции.
W>>>>Тут либо сторед-проц пишем, либо триггер делаем. Твой вариант инсерт+апдейт приведет к тому, что кто-то забудет что-то сделать.
vsb>>>Ну любители писать логику на стороне сервера могут и хранимку написать, я предпочитаю писать код в приложении, а не в базе, но сути это не меняет. Кто-то забудет, получит по башке и вспомнит. А так и триггер можно отключить, а то чего он мешает базу портить (: А триггер, если есть желание, будет достаточно простой: в update проверяем, что ставится false на тот флажок; в insert проверяем, что ставится true, а у (n-1)-й записи проставлен false. Всё вытаскивается моментально.
W>>Это пофиг где ты пишешь. Должен быть атомарный вызов чего-то, что не сломает логику. W>>По мне так самое верное когда есть движок, который дает бизнес-объекты, и всю логику ты пишешь на них, а не лезешь каждый раз в SQL.
vsb>Ну да, это правильно. Хотя от запросов на SQL всё равно обычно никуда не уйти, но вставка/изменение лучше всего бы в одном месте, тем более, что и всякие права проверять централизованно проще и надёжней.
Уйти. Пример 1С. Мне вообще всегда фиолетово, в какой таблице на SQL что лежит.
И пример автора я бы описал так ВЫБРАТЬ * Из РегистрСведений.КурсыВалют.СрезПоследних(&Дата).
Я прекрасно понимаю во что это транслируется на SQL, но к счастью, это делает платформа, а я занимаюсь полезной деятельностью, а не рутиной.
Здравствуйте, wraithik, Вы писали:
W>Если инсерт в середину делаем? Или считаем только всегда в конец? W>Тут либо сторед-проц пишем, либо триггер делаем. Твой вариант инсерт+апдейт приведет к тому, что кто-то забудет что-то сделать.
Стоит ещё задуматься о том, что будет, если вставка происходит в параллельных транзакциях.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, wraithik, Вы писали:
W>>Если инсерт в середину делаем? Или считаем только всегда в конец? W>>Тут либо сторед-проц пишем, либо триггер делаем. Твой вариант инсерт+апдейт приведет к тому, что кто-то забудет что-то сделать. S>Стоит ещё задуматься о том, что будет, если вставка происходит в параллельных транзакциях.
Вот теперь точно сторед-проц. Т.к. надо сперва блокировку сделать, а потом менять. Иначе будет весело, но потом, и не очень.
Здравствуйте, Буравчик, Вы писали:
Б>Здравствуйте, Softwarer, Вы писали:
S>>К BigQuery у меня претензий нет (возможно, потому, что я с ним не работал). А вот зачем складывать данные так, чтобы для тривиального запроса требовалось завязываться узлом — вопрос, назовём так, открытый.
Б>А как удобнее было бы складывать данные?
вроде стандартное решение: две таблицы
1) основная
2) архивная
при изменении, старые значение вставляются в архив
потом, если потребуется история, можно вытянуть из архива,
в главной всегда актуальная инфа.
Здравствуйте, varenikAA, Вы писали:
AA>вроде стандартное решение: две таблицы AA>1) основная AA>2) архивная AA>при изменении, старые значение вставляются в архив AA>потом, если потребуется история, можно вытянуть из архива, AA>в главной всегда актуальная инфа.
Имхо, ты решил проблему, которой у автора нет.
Усложнил систему без необходимости для этого.
Здравствуйте, Буравчик, Вы писали:
Б>Здравствуйте, varenikAA, Вы писали:
AA>>вроде стандартное решение: две таблицы AA>>1) основная AA>>2) архивная AA>>при изменении, старые значение вставляются в архив AA>>потом, если потребуется история, можно вытянуть из архива, AA>>в главной всегда актуальная инфа.
Б>Имхо, ты решил проблему, которой у автора нет. Б>Усложнил систему без необходимости для этого.
Спросили как хранить исторические данные.
Да, конечно, проще cte написать, проще вообще одну таблицу на все приложение.
Особенно, если учесть,что исторические данные быть может нужны лишь при просмотре единственной записи.