powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / История одна дата vs две. Что лучше?
129 сообщений из 129, показаны все 6 страниц
История одна дата vs две. Что лучше?
    #35650193
Novice22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день!
Подскажите плз какой из двух вариантов ведения истории значения поля лучше выбрать:
Вариант1:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
    Tovar(
      id int,
      type varchar( 50 )
    )
    Tovar_history(
      id, FK(Tovar.id),
      Date,
      Name
    )
    id+Date - PK Tovar_history
Вариант2:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
    Tovar(
      id int,
      type varchar( 50 )
    )
    Tovar_history(
      id, FK(Tovar.id),
      DateStart,
      DateEnd,
      Name
    )
    id+DateStart - PK Tovar_history

Что лучше и эффективней использовать?
Вариант1 быстрее для вставки и удаления записей, Вариант2 для выборок?
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650210
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Novice22
Код: plaintext
1.
    id+Date - PK Tovar_history
Вот это зря, имхо.
Уже неоднократно обсуждалось, что чревато пытаться достичь уникальности на основе даты (даже со временем).
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650221
Novice22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
miksoftNovice22
Код: plaintext
1.
    id+Date - PK Tovar_history
Вот это зря, имхо.
Уже неоднократно обсуждалось, что чревато пытаться достичь уникальности на основе даты (даже со временем).

А можно ссылку на посты, где это обсуждалось, плз. А то при поиске как лучше организовать хранение изменений поля у меня наоборот сложилось впечатление, что этот вариант лучший :/ . http://rdbms.narod.ru/article/history/index.html
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650262
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Novice22 пишет:

> Tovar(
> id int,
> type varchar(*50*)
> )
> Tovar_history(
> id, FK(Tovar.id),
> DateStart,
> DateEnd,
> Name
> )
> id+DateStart - PK Tovar_history
>
>
> Что лучше и эффективней использовать?

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

(на самом деле конечно не такой он и сложный, но если его вложить
в другие запросы которые уже реально с данными работать будут,
будет совсем невесело).
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650270
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Novice22,
а между диапазонами разрывы могут быть?
Т.е. может ли так оказаться, что между DateEnd одной записи и DateStart другой записи ничего не будет.?
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650274
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivК тому же это нереляционноА дублировать (и не просто дублировать, а следить за непересечением и неразрывностью интервалов) данные лучше, что ли?
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650318
Novice22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZiv
Первый ты почти не сможешь обрабатывать запросами.


В первом варианте относительно запросов я вижу пока только одну проблему: каким образом отсекать, что с даты n история временно перестала вестись. Например:
Код: plaintext
1.
2.
3.
        1  Гвоздь  01 . 01 . 08 
        1  Большой гвоздь  15 . 02 . 08 
        1  Ржавый гвоздь    26 . 03 . 08 

Может понадобится "свернуть" историю по Товару с id = 1 с 30.05 он временно перестал выпускаться/покупаться/завозиться. Единственное, что пока придумалось добавление еще одной записи с пустым наименованием и датой, когда история временно прекращена.

miksoft
а между диапазонами разрывы могут быть?

Пересечений быть не должно разрывы могут. Товар может какое-то время отсутствовать по разным причинам на предприятии, на это время нужно прекратить вести историю, после появления товара историю нужно продолжить с даты появления.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650334
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Novice22Товар может какое-то время отсутствовать по разным причинам на предприятии, на это время нужно прекратить вести историю, после появления товара историю нужно продолжить с даты появления.А тогда как вы вообще собирались применять первый вариант?
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650369
Novice22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
miksoftА тогда как вы вообще собирались применять первый вариант?

Путем вставки записей с пустым наименованием и датой
Код: plaintext
1.
2.
3.
4.
5.
6.
        1  Гвоздь  01 . 01 . 08 
        1  Большой гвоздь  15 . 02 . 08 
        1  Ржавый гвоздь    26 . 03 . 08 
        1                            30 . 05 . 08  -- разрыв 
        1  Ржавый гвоздь    01 . 08 . 08 

В случае Варианта2:
Код: plaintext
1.
2.
3.
4.
        1  Гвоздь  01 . 01 . 08   14 . 02 . 08 
        1  Большой гвоздь  15 . 02 . 08   25 . 03 . 08 
        1  Ржавый гвоздь    26 . 03 . 08   30 . 05 . 08 
        1  Ржавый гвоздь    01 . 08 . 08   01 . 01 . 2999 

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

Пока складывается ощущение, что второй вариант лучше по реализации(простоте) select, но более громоздкий для insert/delete (при вставке/удалении не последнего значения надо изменять даты у "соседних записей"), первый наоборот. Или я не прав?
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650443
Фотография ChA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivК тому же это нереляционно - данные в одной записи неявно зависят
от данных в другой записи, поскольку дата начала действия (или конца) записи
лежит в данной записи, а дату конца (или соотв. начала)
действия данной записи ты можешь узнать, только найдя не самым простым
запросом последующую (или соотв. предыдущую ) запись.Ничуть. Скорее, такая зависимость есть именно во втором случае. В первом случае, данные в одной записи никак не зависят от данных в другой записи, во всех записях дата начала точки отсчета. А вот во втором случае, данные в одной записи как раз зависят от данных в другой записи, так как подразумевается, если я правильно понял, непересекающиеся промежутки. И если меняем, например, дату конца периода в первой записи, то обязательно надо корректировать дату в следующей, второй по порядку, записи. Хуже того, при неверном указании даты окончания в одной записи, все последующие могут оказаться в противоречивом состоянии, когда дата их окончания неожиданно станет меньше даты окончания первой записи. Но и это еще не все, во втором случае еще и появляется зависимость между полями. Значение в одном из них обязательно должно превышать значение в другом, и наоборот. Таким образом, именно второй случай следует считать проявлением нереляционности, а точнее, денормализации, выполняемый с целью оптимизации некоторых видов запросов.

P.S. То, что любой факт должен меняться только в одном месте, является косвенным признаком нормальности решения модели.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650507
korda
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
2 ChA
ChAMasterZivК тому же это нереляционно - данные в одной записи неявно зависят
от данных в другой записи, поскольку дата начала действия (или конца) записи
лежит в данной записи, а дату конца (или соотв. начала)
действия данной записи ты можешь узнать, только найдя не самым простым
запросом последующую (или соотв. предыдущую ) запись.Ничуть. Скорее, такая зависимость есть именно во втором случае. В первом случае, данные в одной записи никак не зависят от данных в другой записи, во всех записях дата начала точки отсчета. А вот во втором случае, данные в одной записи как раз зависят от данных в другой записи, так как подразумевается, если я правильно понял, непересекающиеся промежутки. И если меняем, например, дату конца периода в первой записи, то обязательно надо корректировать дату в следующей, второй по порядку, записи. Хуже того, при неверном указании даты окончания в одной записи, все последующие могут оказаться в противоречивом состоянии, когда дата их окончания неожиданно станет меньше даты окончания первой записи. Но и это еще не все, во втором случае еще и появляется зависимость между полями. Значение в одном из них обязательно должно превышать значение в другом, и наоборот. Таким образом, именно второй случай следует считать проявлением нереляционности, а точнее, денормализации, выполняемый с целью оптимизации некоторых видов запросов.

P.S. То, что любой факт должен меняться только в одном месте, является косвенным признаком нормальности решения модели.

С таким же успехом можно сказать, что в первом случае существует зависимость между любыми соседними записями, так как дата в предыдущей должна быть меньше, чем в последующей. Но мне кажется, что подобные зависимости, как в первом, так и во втором случае являются надуманными. Т.е. зависимости конечно есть, но их наличие не означает, что данное решение плохое. Например, в таблице с полями Пол, Беременность, второе поле для женщин может принимать значения TRUE или FALSE, а для мужчин - NULL, следовательно можно говорить, что поля Беременность и Пол находятся в зависимости. Что в этом плохого?

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

> То, что любой факт должен меняться только в одном месте, является косвенным признаком нормальности решения модели.
Это, конечно, в пользу первого варианта.

Я уже было решил, что буду использовать второй вариант, но теперь увидев эту тему и Ваш ответ засомневался в правильности выбора.
В свое время Вы написали примеры запросов ко второму варианту. См.: http://sql.ru/forum/actualthread.aspx?tid=599398
Не могли бы Вы написать, как будет выглядеть запрос для превого варианта?
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650525
Фотография ChA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kordaС таким же успехом можно сказать, что в первом случае существует зависимость между любыми соседними записями, так как дата в предыдущей должна быть меньше, чем в последующей. Но мне кажется, что подобные зависимости, как в первом, так и во втором случае являются надуманными.Нельзя так сказать, потому что в первом варианте есть только дата начала. Если поменять эту дату, то просто измениться историческая последовательность. И она может быть верной. Нет явной зависимости между записями. Нормализация не отвечает за Ваши умопостроения, она занимается только аномалиями данных и поиском функциональных зависимостей в модели данных.

kordaНапример, в таблице с полями Пол, Беременность, второе поле для женщин может принимать значения TRUE или FALSE, а для мужчин - NULL, следовательно можно говорить, что поля Беременность и Пол находятся в зависимости. Что в этом плохого?Только то, что мужчина может оказаться беременным, а женщина - в неизвестном медицине состоянии. Вы можете использовать такое решение, но не удивляйтесь сюрпризам. В общем случае, это неправильный подход.

kordaЯ уже было решил, что буду использовать второй вариант, но теперь увидев эту тему и Ваш ответ засомневался в правильности выбора.
Можно использовать любой из этих вариантов, но второй будет явно сложнее реализовывать. Много телодвижений по проверке корректности. Зато запросы на конкретную дату будут чуть проще. В большинстве случаев, я бы предпочел 1 способ.

kordaВ свое время Вы написали примеры запросов ко второму варианту. См.: http://sql.ru/forum/actualthread.aspx?tid=599398 Простите, но Вам не хотелось бы самому над этим поразмышлять ? Теория, это, конечно, хорошо, но без практики - толку от неё маловато.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650650
Michael_N
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ChA
Можно использовать любой из этих вариантов, но второй будет явно сложнее реализовывать. Много телодвижений по проверке корректности. Зато запросы на конкретную дату будут чуть проще. В большинстве случаев, я бы предпочел 1 способ.


+1
Зачем усложнять себе жизнь? Если дата окончания Вам не нужна - не делайте так. У Вас же периоды не перекрываются! Для упрощения запросов сделайте sp/view с датой окончания периода.

Второй вариант имеет право на существование только если периоды не будут редактироваться. А это маловероятно. Если будут - за&@&сь потом с проверкой корректности.

Всегда лучше то решение, которое проще. :-)
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650759
KOT MATPOCKuH
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Michael_NChA
Можно использовать любой из этих вариантов, но второй будет явно сложнее реализовывать. Много телодвижений по проверке корректности. Зато запросы на конкретную дату будут чуть проще. В большинстве случаев, я бы предпочел 1 способ.


+1
Зачем усложнять себе жизнь? Если дата окончания Вам не нужна - не делайте так. У Вас же периоды не перекрываются! Для упрощения запросов сделайте sp/view с датой окончания периода.

Второй вариант имеет право на существование только если периоды не будут редактироваться. А это маловероятно. Если будут - за&@&сь потом с проверкой корректности.

Всегда лучше то решение, которое проще. :-)

Выскажусь:
Согласен вышесказанным:
1 вариант проще в заполнении, сложнее в выборках, проверок корректности (почти) не требует
2 вариант сложнее в заполнении, проще в выборках, требует проверок корректности данных при корректировке.

Можно выбрать промежуточный вариант: структура - как во 2 варианте, но пользователь может корректировать только поле DateStart. Триггер пусть корректирует поле DateEnd в соответствующих записях. Результат: простота заполнения 1 варианта, простота выборок 2 варианта, отсутствие проверок корректности 1 варианта + триггер нада написать.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650767
KOT MATPOCKuH
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну и АВТОРу (начинает вроде):
DateStart = NULL - значит - "от царя гороха" или испокон веков (кому как нравится)
DateEnd = NULL - значит - пожизненно, т.е. всегда
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650798
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KOT MATPOCKuHНу и АВТОРу (начинает вроде):
DateStart = NULL - значит - "от царя гороха" или испокон веков (кому как нравится)
DateEnd = NULL - значит - пожизненно, т.е. всегдаДля выборок по индексу - очень неудачное решение. Имхо, лучше использовать константы, гарантированно выходящие за диапазон обрабатываемых данных.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650849
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoft пишет:

> А дублировать (и не просто дублировать, а следить за непересечением и
> неразрывностью интервалов) данные лучше, что ли?
Вы во-первых сами подняли тему о разрывах. Т.е. это не всегда и нужно.
а во-вторых - да, ЛУЧШЕ следить за этим. Это делается в ОДНОМ запросе
на изменение. А всё остальное надо делать во многих запросах на чтение.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650884
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv> А дублировать (и не просто дублировать, а следить за непересечением и
> неразрывностью интервалов) данные лучше, что ли?
Вы во-первых сами подняли тему о разрывах. Т.е. это не всегда и нужно.
а во-вторых - да, ЛУЧШЕ следить за этим. Это делается в ОДНОМ запросе
на изменение. А всё остальное надо делать во многих запросах на чтение.
Следить за этим констрейнтами мало в какой СУБД получится. Если следить запросами - сложно и/или накладно уберечься от одновременной вставки в разных сессиях. Кроме того, существует вероятность невыполнения этой проверки.
Имхо, лучше иметь надежные данные в базе и совершенстовать (исправлять ошибки) выборки, нежели наоборот.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650895
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ChA пишет:

> Ничуть. Скорее, такая зависимость есть именно во втором случае. В первом
> случае, данные в одной записи никак не зависят от данных в другой
> записи, во всех записях дата начала точки отсчета.

Да зависимость-то есть в любом случае, если она есть в предметной области.
Если один товар "сменяет" другой - они зависимы. Вопрос в том, как эту
зависимость более удобно представить в БД.

А вот во втором
> случае, данные в одной записи как раз зависят от данных в другой записи,
> так как подразумевается, если я правильно понял, непересекающиеся
> промежутки.

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

И если меняем, например, дату конца периода в первой записи,
> то обязательно надо корректировать дату в следующей, второй по порядку,
> записи.

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

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

вы во-первых путаете денормализацию и ненормализованность,
а во-вторых, говорите вообще ерунду. Кортежи нормализуются независимо
друг от друга - вся таблица целиком нормализуется. Функциональная зависимость--
это отношение между полями таблицы. У КАЖДОГО товара должен
быть срок его действия. Есть товар. Есть о нём запись в таблице(ах).
Все данные ЭТОГО товара должы быть самодостаточными для приложения.
Все остальные товары я могу удалить напр. Вот понадобится мне
почистить эту таблицу истории -- и КАК ? Последнюю запись перед
первой удаляемой придётся оставить, так ? Придётся. Но она БУДЕТ
НЕВАЛИДНОЙ, потому что срок начала её действия будет находится
в предыдущей удалённой записи. Тут пример немного надуманный, правда,
потому что можно считать дату в записи датой начала действия записи,
и тогда всё как бы в порядке. Но в общем это всё равно -
с такими проблемами вы всегда будете встречаться, если будете
раскладывать данные одной записи по нескольким.

> P.S. То, что любой факт должен меняться только в одном месте, является
> косвенным признаком нормальности решения модели.

Нет. Здесь нет никакой ненормальности. Это -- бизнес логика в
чистом виде -- вам нужно чтобы периоды сроков действия товаров не
пересекались.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650904
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
korda пишет:

> Я уже было решил, что буду использовать второй вариант, но теперь увидев
> эту тему и Ваш ответ засомневался в правильности выбора.
> В свое время Вы написали примеры запросов ко второму варианту. См.:
> http://sql.ru/forum/actualthread.aspx?tid=599398
> Не могли бы Вы написать, как будет выглядеть запрос для превого варианта?

вот именно. Надо написать список нужных запросов и попытаться реализовать
их в двух вариантах. Потом посмотреть, какой лучше. Я вас уверяю, второй
выиграет.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650912
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoft пишет:

> Для выборок по индексу - очень неудачное решение. Имхо, лучше
> использовать константы, гарантированно выходящие за диапазон
> обрабатываемых данных.

Да не пугайте народ. Ничего страшного.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650922
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KOT MATPOCKuH пишет:

> Можно выбрать промежуточный вариант: структура - как во 2 варианте, но
> пользователь может корректировать только поле DateStart. Триггер пусть
> корректирует поле DateEnd в соответствующих записях. Результат: простота
> заполнения 1 варианта, простота выборок 2 варианта, отсутствие проверок
> корректности 1 варианта + триггер нада написать.

Так , стоп.

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

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

Вообще, ещё раз, это бизнес-логика в чистом виде.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35650964
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv
miksoft пишет:

> Для выборок по индексу - очень неудачное решение. Имхо, лучше
> использовать константы, гарантированно выходящие за диапазон
> обрабатываемых данных.

Да не пугайте народ. Ничего страшного.
Тогда придется писать
Код: plaintext
1.
SELECT * FROM Tovar_history
WHERE (DateStart<NOW() OR DateStart IS NULL) AND (NOW()<DateEnd OR DateEnd IS NULL)
На мой взгляд, индексы тут неприменимы.

Хотя, если записей сто штук, то, конечно, ничего страшного...
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35651341
KOT MATPOCKuH
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv
...
Тут надо разобраться периоды могут пересекаться, или нет.
...


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

MasterZiv
...
будут ли дырки или нет?
...

Во-первых: сам автор уже ответил на этот вопрос - вполне нормально.
Только смысла в дырках я не вижу.
Функциональность отвечает (я так понял) только за историю значения параметра. Отсутствие значения однозначно всеми (мне известными) СУБД реализовано одним способом: значение = NULL, что в некотором смысле - тоже значение (в нашем случае строка в таблице истории). Отсутствие же доступа к параметру решается не на этом уровне, т.е. не этими сущностями, а попытка в одну сущность впихнуть несколько разных функциональностей еще никогда не приводила к хорошему результату.
Пример последнего: если с 01.01.2008 по 10.01.2008 небыло сковородок, то значение цены на сковородки должно существовать (старое, например), только показывать его смысла нет.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35651361
KOT MATPOCKuH
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv
Вообще, ещё раз, это бизнес-логика в чистом виде.

Вопросы, задаваемые в этом форуме редко относятся только к структуре БД.
Большей частью требуется подсказать вариант бизнес-логики и уже под нее структуру БД.

Даже если некто спрашивает про структуру, то отвечающие обычно пытаются догадаться о его бизнес-логике и ответить на вопрос.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35651762
Novice22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
2All
огромное спасибо за все ответы и советы.

Набросал запросы, которые надо реализовать для 2х вариантов(выбор наименования, цены на определенную дату; просмотр истории наименований, цены больше/меньше заданной даты; длительность действия данного наименования, цены для данного товара). В первом варианте запросы сложнее, но ничего особо страшного я не заметил. Или я не прав и чего-то не вижу и такая схема может потом замедлить работу системы?

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

При рассмотрении второго варианта смущают правки соседних записей, т.к. предполагается, что история будет активно редактироваться. Возможны случаи:
Код: plaintext
1.
2.
3.
  >  1       1  tov1  01 . 05 . 08   10 . 02 . 08 
  >  2       1  tov2  10 . 02 . 08   15 . 03 . 08 
  >  3       1  tov3  15 . 03 . 08   18 . 03 . 08 
Надо удалить, запись 2 - это приводит к редактированию даты в записи 1
Или вставить запись 1 tov2.1 20.02.08 10.03.08 - надо редактировать запись 3
Может возникнуть необходимость редактирования даты окончания действия наименования
tov2 до 17.03.08 - в этом случае начало действия наименования tov3 надо будет сдвигать
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35651941
korda
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
После всего прочитанного все больше склоняюсь к первому варианту. Во втором есть ещё один недостаток - одна и таже дата по сути дела продублирована в двух местах, ведь дата окончания одного периода совпадает с датой начала следующего.

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

По поводу "временного прекращения действия истории", кажется мне, что здесь что-то не то, что нужную Вам функциональность можно и нужно реализовать как-то по другому, не внося в идею непрерывной истории дополнительные факторы усложняющие общую картину, ведь в первом варианте, если рассматривать его в чистом виде, мы имеем, по сути дела, своеобразный лог изменения записей. Кстати, то, что это лог, делает первый вариант ещё более симпатичным, так как лог - вещь известная, стандартная. Возможно позже, Вы даже захотите использовать готовые инструменты для его анализа.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35652011
korda
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ChA
kordaНапример, в таблице с полями Пол, Беременность, второе поле для женщин может принимать значения TRUE или FALSE, а для мужчин - NULL, следовательно можно говорить, что поля Беременность и Пол находятся в зависимости. Что в этом плохого?Только то, что мужчина может оказаться беременным, а женщина - в неизвестном медицине состоянии. Вы можете использовать такое решение, но не удивляйтесь сюрпризам. В общем случае, это неправильный подход.


Вы правы, я не подумал... В данном случае, поле Беременность не должно присутствовать в таблице Люди, а должно находиться в таблице Женщины и отсутствовать в таблице Мужчины.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35652251
korda
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я перечитал свой пост в другой теме (см. выше) и понял, что написанные ChA запросы могут быть с успехом применены и к первому варианту. Получается, что дата окончания, в той-же самой записи просто не нужна!

Получение состояния исходной таблицы на определённую дату:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
SELECT *
FROM hist t1
WHERE t1.dt IN (
	SELECT max(t2.dt)
	FROM hist t2
	WHERE t2.kod = t1.kod AND '2009-12-20' > t2.dt
)
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35652730
Bely
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kordaчто дата окончания, в той-же самой записи просто не нужна! А Oracle в своих Flashback Archive Tables, почему-то, использует две даты в своих системных таблицах (а точнее START_SCN, END_SCN).

Вот и получается, что "Мужики-то не знают..." (с)
или там дураки сидят, пологаете?
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35652972
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoft пишет:


> Следить за этим констрейнтами мало в какой СУБД получится. Если следить
> запросами - сложно и/или накладно уберечься от одновременной вставки в
> разных сессиях. Кроме того, существует вероятность невыполнения этой
> проверки.
> Имхо, лучше иметь надежные данные в базе и совершенстовать (исправлять
> ошибки) выборки, нежели наоборот.

О чём вы вообще говорите ? Это - обычная бизнес-логика, и достаточно простая.
Реализуется элементарно в ЛЮБОЙ современной СУБД на триггерах или на процедурах.
В чём проблема там у вас -- я не понимаю.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35652976
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoft пишет:

> Тогда придется писать
>
> SELECT * FROM Tovar_history
> WHERE (DateStart<NOW() OR DateStart IS NULL) AND (NOW()<DateEnd OR DateEnd IS NULL)
>
> На мой взгляд, индексы тут неприменимы.

Предлагаю его переписать так:

SELECT *
FROM Tovar_history
WHERE @date_now between DateStart and DateEnd
or DateEnd >= @date_now and DateStart IS NULL
or DateStart <= @date_now and DateEnd IS NULL

И всё уже применимо в полный рост
(два индекса по (DateStart, DateEnd) и (DateEnd,DateStart) ).

Если оптимизатор совсем тупой, переписываем

SELECT *
FROM Tovar_history
WHERE @date_now between DateStart and DateEnd
union all
SELECT *
FROM Tovar_history
WHERE DateEnd >= @date_now and DateStart IS NULL
union all
SELECT *
FROM Tovar_history
WHERE DateStart <= @date_now and DateEnd IS NULL
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35652982
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Novice22 пишет:

> наименования, цены для данного товара). В первом варианте запросы
> сложнее, но ничего особо страшного я не заметил. Или я не прав и чего-то
> не вижу и такая схема может потом замедлить работу системы?

Так может пошлёте ?
>
> В первом варианте меня смущает необходимость вставки записи
> дополнительных записей для временного прекращения истории(строка с датой
> и без наименования) и для окончания ведения истории без удаления
> товара(последнее наименование и дата).

О! А я предупреждал ...

> Может возникнуть необходимость редактирования даты окончания действия
> наименования
> tov2 до 17.03.08 - в этом случае начало действия наименования tov3 надо
> будет сдвигать

Ну и подвиньте, триггером или процедурой.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35652994
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivЕсли оптимизатор совсем тупой, переписываем

SELECT *
FROM Tovar_history
WHERE @date_now between DateStart and DateEnd
union all
SELECT *
FROM Tovar_history
WHERE DateEnd >= @date_now and DateStart IS NULL
union all
SELECT *
FROM Tovar_history
WHERE DateStart <= @date_now and DateEnd IS NULL
union all
SELECT *
FROM Tovar_history
WHERE DateStart IS NULL and DateEnd IS NULL

и приплыли...
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35653046
korda
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Belykordaчто дата окончания, в той-же самой записи просто не нужна! А Oracle в своих Flashback Archive Tables, почему-то, использует две даты в своих системных таблицах (а точнее START_SCN, END_SCN).

Вот и получается, что "Мужики-то не знают..." (с)
или там дураки сидят, пологаете?

Может быть для такого подхода у Oracle имеются какие-то объективные причины. Скорость выполнения запросов или ещё что-то... Кстати, как Вы думаете, почему они так делают?
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35653139
Cheprasov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Мне кажется дату за ключ вообще брать не нужно, добавить в таблицу истории свое уникальное поле, а по полям id дата создать индекс
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35653644
KOT MATPOCKuH
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что по вашему быстрее работать будет и меньше ресурсов потреблять:
korda
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
SELECT *
FROM hist t1
WHERE t1.kod = 'Сосиски'
    AND t1.dt IN (
	SELECT max(t2.dt)
	FROM hist t2
	WHERE t2.kod = t1.kod AND '2009-12-20' > t2.dt
)
[/quot]

или

Код: plaintext
1.
2.
3.
4.
5.
SELECT *
FROM hist t1
WHERE t1.kod = 'Сосиски'
    AND '2009-12-20' >= t1.start_date
    AND '2009-12-20' < t1.end_date

А проще - попробуйте на своей БД: создайте табличку, залейте туда 10 000 000 записей - и вперед!

Результаты - в студию!
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35653787
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KOT MATPOCKuHЧто по вашему быстрее работать будет и меньше ресурсов потреблять:В такой постановке вопроса первый вариант выиграет однозначно. Во втором варианте еще и не всякий оптимизатор индекс догадается поиметь.

Второй вариант может выиграть на запросах типа
Код: plaintext
select sum(ostatok) from hist where dt_start<=:date and dt_end>:date;
То есть когда нас интересуют некие аналитики на заданную дату.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35653796
Bely
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kordaМожет быть для такого подхода у Oracle имеются какие-то объективные причины. Скорость выполнения запросов или ещё что-то...Вы сами ответили - скорость выполнения запросов.
Для принятия решения о попадании строки в выборку - для двух дат нужна только эта строка.
Для одной даты - надо найти еще вторую строку, которая укажет конец интервала.

2 KOT MATPOCKuH
Всетаки, для первого запроса надо использовать аналитические функции.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
SELECT  t2.*
FROM
(
SELECT t1.dt as dt_start
  , lead(t1.dt) over (partition by t1.kod order by t1.dt, t1.id) as dt_end
  , t1.id, t1.kod
FROM hist t1
) t2
WHERE  1 = 1 
  AND '2009-12-20' >= t2.dt_start
  AND '2009-12-20' < t3.dt_end
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35653902
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BelyВсетаки, для первого запроса надо использовать аналитические функции.Лучше не надо :)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
SQL> create table hist(kod integer,dt date);

Таблица создана.

SQL> create index ix_hist on hist(dt);

Индекс создан.

SQL> 
SQL> insert into hist(kod, dt)
   2   select lv, sysdate-lv from
   3   (select level as lv from dual connect by level <= 1000000 ) pivot;

 1000000  строк создано.

SQL> 
SQL> set autotrace on   
SQL> 
SQL> SELECT kod FROM hist t1
   2   WHERE t1.dt IN (SELECT max(t2.dt) FROM hist t2
   3                    WHERE t2.dt < sysdate -  1000 );

       KOD
----------
       1000 


План выполнения
----------------------------------------------------------

-------------------------------------------------------------------------------
| Id  | Operation                      | Name    | Rows  | Bytes | Cost (%CPU)|
-------------------------------------------------------------------------------
|    0  | SELECT STATEMENT               |         |      1  |     22  |      7    ( 0 )|
|    1  |  TABLE ACCESS BY INDEX ROWID   | HIST    |      1  |     22  |      5    ( 0 )|
|*   2  |   INDEX RANGE SCAN             | IX_HIST |   4005  |       |      1    ( 0 )|
|    3  |    SORT AGGREGATE              |         |      1  |      9  |            |
|    4  |     FIRST ROW                  |         |  1001K|  8799K|      2    ( 0 )|
|*   5  |      INDEX RANGE SCAN (MIN/MAX)| IX_HIST |  1001K|  8799K|      2    ( 0 )|
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

    2  - access("T1"."DT"= (SELECT MAX("T2"."DT") FROM "HIST" "T2" WHERE
              "T2"."DT"<SYSDATE@!- 1000 ))
    5  - access("T2"."DT"<SYSDATE@!- 1000 )

Note
-----
   - 'PLAN_TABLE' is old version


Статистика
----------------------------------------------------------
          36   recursive calls
           0   db block gets
         167   consistent gets
         461   physical reads
          72   redo size
         330   bytes sent via SQL*Net to client
         373   bytes received via SQL*Net from client
           2   SQL*Net roundtrips to/from client
           0   sorts (memory)
           0   sorts (disk)
           1   rows processed

SQL> 
SQL> SELECT  kod
   2   FROM (SELECT t1.dt as dt_start
   3     , lead(t1.dt) over (order by t1.dt) as dt_end
   4     , t1.kod
   5   FROM hist t1
   6   ) t2
   7   WHERE  1 = 1 
   8     AND t2.dt_start <= sysdate- 1000 
   9     AND t2.dt_end > sysdate- 1000 ;

       KOD
----------
       1000 


План выполнения
----------------------------------------------------------

-------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes |TempSpc| Cost (%CPU)|
-------------------------------------------------------------------------
|    0  | SELECT STATEMENT    |      |  1001K|    29M|       |   7400    ( 4 )|
|*   1  |  VIEW               |      |  1001K|    29M|       |   7400    ( 4 )|
|    2  |   WINDOW SORT       |      |  1001K|    21M|    61M|   7400    ( 4 )|
|    3  |    TABLE ACCESS FULL| HIST |  1001K|    21M|       |    581    ( 7 )|
-------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

    1  - filter("T2"."DT_START"<=SYSDATE@!- 1000  AND
              "T2"."DT_END">SYSDATE@!- 1000 )

Note
-----
   - 'PLAN_TABLE' is old version


Статистика
----------------------------------------------------------
           4   recursive calls
           0   db block gets
        2552   consistent gets
        1816   physical reads
           0   redo size
         330   bytes sent via SQL*Net to client
         373   bytes received via SQL*Net from client
           2   SQL*Net roundtrips to/from client
           1   sorts (memory)
           0   sorts (disk)
           1   rows processed

SQL> 
SQL> set autotrace off
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35653907
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bogdanov Andrey,
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35653911
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Блин, забыл статистику актуализировать. Вот исправленный вариант - разница еще более впечатляющая :)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
SQL> create table hist(kod integer,dt date);

Таблица создана.

SQL> create index ix_hist on hist(dt);

Индекс создан.

SQL> 
SQL> insert into hist(kod, dt)
   2   select lv, sysdate-lv from
   3   (select level as lv from dual connect by level <= 1000000 ) pivot;

 1000000  строк создано.

SQL> 
SQL> analyze table hist compute statistics;

Таблица проанализирована.

SQL> set autotrace on   
SQL> 
SQL> SELECT kod FROM hist t1
   2   WHERE t1.dt IN (SELECT max(t2.dt) FROM hist t2
   3                    WHERE t2.dt < sysdate -  1000 );

       KOD
----------
       1000 


План выполнения
----------------------------------------------------------

-------------------------------------------------------------------------------
| Id  | Operation                      | Name    | Rows  | Bytes | Cost (%CPU)|
-------------------------------------------------------------------------------
|    0  | SELECT STATEMENT               |         |      1  |     11  |      7    ( 0 )|
|    1  |  TABLE ACCESS BY INDEX ROWID   | HIST    |      1  |     11  |      4    ( 0 )|
|*   2  |   INDEX RANGE SCAN             | IX_HIST |      1  |       |      3    ( 0 )|
|    3  |    SORT AGGREGATE              |         |      1  |      7  |            |
|    4  |     FIRST ROW                  |         |   999K|  6829K|      3    ( 0 )|
|*   5  |      INDEX RANGE SCAN (MIN/MAX)| IX_HIST |   999K|  6829K|      3    ( 0 )|
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

    2  - access("T1"."DT"= (SELECT MAX("T2"."DT") FROM "HIST" "T2" WHERE
              "T2"."DT"<SYSDATE@!- 1000 ))
    5  - access("T2"."DT"<SYSDATE@!- 1000 )

Note
-----
   - 'PLAN_TABLE' is old version


Статистика
----------------------------------------------------------
           1   recursive calls
           0   db block gets
           8   consistent gets
           2   physical reads
           0   redo size
         330   bytes sent via SQL*Net to client
         373   bytes received via SQL*Net from client
           2   SQL*Net roundtrips to/from client
           0   sorts (memory)
           0   sorts (disk)
           1   rows processed

SQL> 
SQL> SELECT  kod
   2   FROM (SELECT t1.dt as dt_start
   3     , lead(t1.dt) over (order by t1.dt) as dt_end
   4     , t1.kod
   5   FROM hist t1
   6   ) t2
   7   WHERE  1 = 1 
   8     AND t2.dt_start <= sysdate- 1000 
   9     AND t2.dt_end > sysdate- 1000 ;

       KOD
----------
       1000 


План выполнения
----------------------------------------------------------

-------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes |TempSpc| Cost (%CPU)|
-------------------------------------------------------------------------
|    0  | SELECT STATEMENT    |      |  1000K|    29M|       |   5117    ( 5 )|
|*   1  |  VIEW               |      |  1000K|    29M|       |   5117    ( 5 )|
|    2  |   WINDOW SORT       |      |  1000K|    10M|    38M|   5117    ( 5 )|
|    3  |    TABLE ACCESS FULL| HIST |  1000K|    10M|       |    581    ( 7 )|
-------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

    1  - filter("T2"."DT_START"<=SYSDATE@!- 1000  AND
              "T2"."DT_END">SYSDATE@!- 1000 )

Note
-----
   - 'PLAN_TABLE' is old version


Статистика
----------------------------------------------------------
           1   recursive calls
           0   db block gets
        2482   consistent gets
         193   physical reads
           0   redo size
         330   bytes sent via SQL*Net to client
         373   bytes received via SQL*Net from client
           2   SQL*Net roundtrips to/from client
           1   sorts (memory)
           0   sorts (disk)
           1   rows processed

SQL> 
SQL> set autotrace off
SQL> 
SQL> drop table hist;

Таблица удалена.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35653921
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну и для сравнения, вариант с двумя датами:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
SQL> create table hist(kod integer,start_dt date,end_dt date);

Таблица создана.

SQL> create index ix_hist on hist(start_dt,end_dt);

Индекс создан.

SQL> 
SQL> insert into hist(kod, start_dt,end_dt)
   2   select lv, sysdate-lv, sysdate-lv+ 1  from
   3   (select level as lv from dual connect by level <= 1000000 ) pivot;

 1000000  строк создано.

SQL> 
SQL> analyze table hist compute statistics;

Таблица проанализирована.

SQL> 
SQL> set autotrace on   
SQL> 
SQL> SELECT *
   2   FROM hist t1
   3   WHERE t1.start_dt < sysdate- 1000  and t1.end_dt >=sysdate- 1000 ;

       KOD START_DT END_DT
---------- -------- --------
       1000   18 . 02 . 06   19 . 02 . 06 


План выполнения
----------------------------------------------------------

---------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)|
---------------------------------------------------------------
|    0  | SELECT STATEMENT  |      |   1000  |  18000  |    928   ( 16 )|
|*   1  |  TABLE ACCESS FULL| HIST |   1000  |  18000  |    928   ( 16 )|
---------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

    1  - filter("T1"."END_DT">=SYSDATE@!- 1000  AND
              "T1"."START_DT"<SYSDATE@!- 1000 )

Note
-----
   - 'PLAN_TABLE' is old version


Статистика
----------------------------------------------------------
           1   recursive calls
           0   db block gets
        3591   consistent gets
        1652   physical reads
           0   redo size
         452   bytes sent via SQL*Net to client
         373   bytes received via SQL*Net from client
           2   SQL*Net roundtrips to/from client
           0   sorts (memory)
           0   sorts (disk)
           1   rows processed

SQL> set autotrace off
SQL> 
SQL> drop table hist;
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35653986
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoft пишет:
> Автор: "miksoft"
> MasterZiv
> Если оптимизатор совсем тупой, переписываем
>
> SELECT *
> FROM Tovar_history
> WHERE @date_now between DateStart and DateEnd
> union all
> SELECT *
> FROM Tovar_history
> WHERE DateEnd >= @date_now and DateStart IS NULL
> union all
> SELECT *
> FROM Tovar_history
> WHERE DateStart <= @date_now and DateEnd IS NULL
>
> union all
> SELECT *
> FROM Tovar_history
> WHERE DateStart IS NULL and DateEnd IS NULL
>
> и приплыли...
Куда приплыли-то? Чем вам это не нравится, даже если добавить ваш запрос ?
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35654214
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv> union all
> SELECT *
> FROM Tovar_history
> WHERE DateStart IS NULL and DateEnd IS NULL
>
> и приплыли...
Куда приплыли-то? Чем вам это не нравится, даже если добавить ваш запрос ?
Например, Оракл не хранит в индексе те записи, у которых все поля в составе этого индекса IS NULL. Т.е. ни индекс (DateStart, DateEnd), ни индекс (DateEnd, DateStart) здесь не помогут. Можно, конечно, добавить третье поле, которое всегда NOT NULL, или на базе фукнции NVL сделать FBI-индекс.
Но это решение уже
а) обретает привязку к СУБД
б) требует преобразования запроса, что не всегда возможно.
в) реальный запрос может быть намного сложнее и это преобразование может сильно испортить его производительность.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35655210
Bely
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bogdanov AndreyBelyВсетаки, для первого запроса надо использовать аналитические функции.Лучше не надо :)ну, для конкретно этого запрос - да, запрос без аналитики будет лучше.

ЗЫ: статистику по индексу тоже неплохо бы пересобирать :)
может тогда FTS и не будет
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35655400
Kirill Razuvaev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>> Пересечений быть не должно разрывы могут. Товар может какое-то время
>> отсутствовать
>> по разным причинам на предприятии, на это время нужно прекратить вести
>> историю,
>> после появления товара историю нужно продолжить с даты появления.
Мне кажется, стоит отделить мух от котлет.
История товара, по-моему - это история изменения его характеристик, цвета,
размера, единицы измерения, наименования и т.п.
Наличие и отсутствие - это история ДВИЖЕНИЯ товара. Характеризоваться оно
должно наличием или отсутствием его - т.е. количественной единицей.
Т.е. в Вашем случае либо не совсем корректный пример, либо стоит
скорректировать схему данных. Тогда и разрывов не будет.
Историю гораздо проще и НАДЕЖНЕЕ хранить с одной датой, т.к. поиск значения
на определенную дату легко реализуется в запросе, причем выполняет его
сервер не напрягаясь (при правильной индексации).
В предложенном Вами втором варианте есть два опасных момента:
- возможность появления разрывов с неопределенными значениями параметров
- потенциальные сложности при поиске значения
Код: plaintext
1.
select Name from 
Tovar_history where MyDate between DateStart and DateEnd
- разные
сервера могут по-разному использовать или даже НЕ использовать индексы по
этим полям.
- необходимость корректировки неограниченного количества "соседних" записей
для обеспечения непересечения и неразрывности. Ведь может потребоваться
модифицировать не одну, а несколько записей, а какие-то из них могут вообще
оказаться некорректными (целиком внутри диапазона новой записи). велики
шансы тут мертвую петлю схватить...


Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35655997
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoft пишет:

> Например, Оракл не хранит в индексе те записи, у которых все поля в
> составе этого индекса IS NULL. Т.е. ни индекс (DateStart, DateEnd), ни

Ну, значит оракл плохая СУБД, и для этой задачи не подходит. Есть другие.

> индекс (DateEnd, DateStart) здесь не помогут. Можно, конечно, добавить
> третье поле, которое всегда NOT NULL, или на базе фукнции NVL сделать
> FBI-индекс.
> Но это решение уже
> а) обретает привязку к СУБД

Это третье поле-то -- привязка к СУБД ? И что, без функции никак ?

В общем, не вижу я тут ничего страшного.
Полно у нас таких запросов, ничего, работают. (правда, не на оракле)
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35656000
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kirill Razuvaev пишет:

> Мне кажется, стоит отделить мух от котлет.
> История товара, по-моему - это история изменения его характеристик, цвета,
> размера, единицы измерения, наименования и т.п.

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

Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35656179
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bogdanov Andrey пишет:

> SQL> SELECT kod FROM hist t1
> *2* WHERE t1.dt IN (SELECT max(t2.dt) FROM hist t2
> *3* WHERE t2.dt < sysdate - *1000*);

ЧТо за волшебный такой запрос, уже второй раз его в топике вижу.

Это же

SELECT kod FROM hist t1
WHERE t1.dt = (SELECT max(t2.dt) FROM hist t2
WHERE t2.dt < sysdate - 1000);
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35656183
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bogdanov Andrey пишет:

> Блин, забыл статистику актуализировать. Вот исправленный вариант -
> разница еще более впечатляющая :)

Ну так во втором случае у вас индексы не используются, насколько я могу
понять оракловые выкладки. А в первом используется.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35656185
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bogdanov Andrey пишет:

> Блин, забыл статистику актуализировать. Вот исправленный вариант -
> разница еще более впечатляющая :)

Первый запрос я понял что такое. А второй что ?
Вроде бы второго варианта структуры там нет. Что доказывали ?
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35656188
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bogdanov Andrey пишет:

> Ну и для сравнения, вариант с двумя датами:

Ну и здесь не используется индекс. подозреваю, что изза sysdate-1000
Вы заставте его использваться, а то
так не интересно.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35656401
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv
miksoft пишет:

> Например, Оракл не хранит в индексе те записи, у которых все поля в
> составе этого индекса IS NULL. Т.е. ни индекс (DateStart, DateEnd), ни

Ну, значит оракл плохая СУБД, и для этой задачи не подходит. Есть другие.

> индекс (DateEnd, DateStart) здесь не помогут. Можно, конечно, добавить
> третье поле, которое всегда NOT NULL, или на базе фукнции NVL сделать
> FBI-индекс.
> Но это решение уже
> а) обретает привязку к СУБД

Это третье поле-то -- привязка к СУБД ? И что, без функции никак ?

В общем, не вижу я тут ничего страшного.
Полно у нас таких запросов, ничего, работают. (правда, не на оракле)
Привязка к СУБД - это знанение особенностей хранения индексов в конкретной СУБД и FBI-индексы, которые есть не во всех СУБД.

Я и не говорю, что это страшно. Я говорил, что использование констант вместо NULL-ов для обозначения диапазонов будет удачнее. Не придется переписывать запрос, не придется задумываться об особенностях СУБД, не придется создавать дополнительные индексы. И Оракл сразу перестанет быть плохим :)
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35656655
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivЧТо за волшебный такой запрос, уже второй раз его в топике вижу.Ничего волшебного (и in вполне на равенство можно заменить - на работу оптимизатора в данном случае не влияет), а второй раз видите, потому что мне было лень его самому набивать, вот я и скопипастил :)
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35657078
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv
Первый запрос я понял что такое. А второй что ?
Вроде бы второго варианта структуры там нет. Что доказывали ?

Вы не очень внимательно смотрели - там есть три варианта запроса. Первый - с одной датой, второй тоже с одной датой и с аналитической функцией (было утверждение, что в данном месте надо аналитику использовать), ну а третий - с двумя датами.

MasterZiv
Ну и здесь не используется индекс. подозреваю, что изза sysdate-1000
Вы заставте его использваться, а то так не интересно.

Эо я должен заставить? Увольте. Это пускай защитники варианта с двумя датами заставляют (подсказка: sysdate-1000 тут не причем). А потом посмотрим какой запрос в итоге проще и быстрее получится.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35658062
KOT MATPOCKuH
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bogdanov Andrey,
Если не сложно, можете для третьего своего варианта сделать два отдельных индекса по датам (оракул не под рукой, сам проверить не могу), и выложить результаты?
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35658540
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KOT MATPOCKuHBogdanov Andrey,
Если не сложно, можете для третьего своего варианта сделать два отдельных индекса по датам (оракул не под рукой, сам проверить не могу), и выложить результаты?

Пожалуйста.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
SQL> create table hist(kod integer,start_dt date,end_dt date);

Таблица создана.

SQL> create index ix_hist_1 on hist(start_dt);

Индекс создан.

SQL> create index ix_hist_2 on hist(end_dt);

Индекс создан.

SQL> insert into hist(kod, start_dt,end_dt)
   2   select lv, sysdate-lv, sysdate-lv+ 1  from
   3   (select level as lv from dual connect by level <= 1000000 ) pivot;

 1000000  строк создано.

SQL> analyze table hist compute statistics;

Таблица проанализирована.

SQL> set autotrace on   
SQL> SELECT *
   2   FROM hist t1
   3   WHERE t1.start_dt < sysdate- 1000  and t1.end_dt >=sysdate- 1000 ;

       KOD START_DT END_DT
---------- -------- --------
       1000   21 . 02 . 06   22 . 02 . 06 


План выполнения
----------------------------------------------------------

------------------------------------------------------------------------------
| Id  | Operation                   | Name      | Rows  | Bytes | Cost (%CPU)|
------------------------------------------------------------------------------
|    0  | SELECT STATEMENT            |           |   1000  |  18000  |     11    ( 0 )|
|*   1  |  TABLE ACCESS BY INDEX ROWID| HIST      |   1000  |  18000  |     11    ( 0 )|
|*   2  |   INDEX RANGE SCAN          | IX_HIST_2 |   1001  |       |      7    ( 0 )|
------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

    1  - filter("T1"."START_DT"<SYSDATE@!- 1000 )
    2  - access("T1"."END_DT">=SYSDATE@!- 1000 )

Note
-----
   - 'PLAN_TABLE' is old version


Статистика
----------------------------------------------------------
           1   recursive calls
           0   db block gets
          13   consistent gets
          10   physical reads
           0   redo size
         452   bytes sent via SQL*Net to client
         373   bytes received via SQL*Net from client
           2   SQL*Net roundtrips to/from client
           0   sorts (memory)
           0   sorts (disk)
           1   rows processed

SQL> set autotrace off
SQL> drop table hist;
Oracle тут, конечно, красавец - выбрал правильный индекс. Если поставить sysdate-990000, то он другой индекc использует. Ну а количенство чтений зависит от расстояния до ближайшего края. И в худшем случае (sysdate-500000) составляет
3591 consistent gets
1697 physical reads

В варианте с запросом по одной дате
Код: plaintext
1.
2.
SELECT kod FROM hist t1
 WHERE t1.dt IN (SELECT max(t2.dt) FROM hist t2
                  WHERE t2.dt < sysdate -  500000 );
такой зависимости нет.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35658768
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bogdanov Andrey пишет:

> Вы не очень внимательно смотрели - там есть три варианта запроса. Первый
> - с одной датой, второй тоже с одной датой и с аналитической функцией
> (было утверждение, что в данном месте надо аналитику использовать), ну а
> третий - с двумя датами.

Я это всё понял, но не про второй запрос. Теперь понял всё.

> Эо я должен заставить? Увольте. Это пускай защитники варианта с двумя
> датами заставляют (подсказка: sysdate-1000 тут не причем). А потом
> посмотрим какой запрос в итоге проще и быстрее получится.

Тогда в чем полезность вашего эксперементального сравнения ?
Оно просто безполезно.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35659402
KOT MATPOCKuH
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bogdanov Andrey,

Все-равно, чего-то я не понимаю...
Короче, не понимаю, почему оракул при условиях >, >=, <, <= для нескольких полей таблицы редко использует индексы по нескольким полям.

В приведенном примере - понятно, стало выгоднее делать TABLE ACCESS FULL и WINDOW SORT, чем поиск по индексу (START_DT, END_DT) или (START_DT). Поэтому, в первых результатах мы увидели такую картину.

А если сделать индекс по END_DT, START_DT он его схватит или нет?

Т.е. вообще иметь два индекса:
1) START_DT, END_DT
2) END_DT, START_DT

Давай попробуем вариант с такими индексами?
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35659449
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivТогда в чем полезность вашего эксперементального сравнения ?
Оно просто безполезно.Как известно, бремя доказывания лежит на утверждающем. В топике были утверждения, что две даты однозначно дают выигрыш скорости при выборках. Причем мне показалось, что у людей нет ни тени сомнения - будучи уверенными, что вариант с одной датой очень плох начали даже предложения по его оптимизации выдвигать.
Мой эксперимент показывает, что ситуация ровно обратная. С одной датой очевидное решение дает отличные результаты, тогда как в варианте с двумя датами все не столь однозначно.
По крайней мере, теперь сторонники решения с двумя датами могут хоть немного призадуматься. Вот KOT MATPOCKuH уже начал пытаться выжать максимум из двух дат :)
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35659460
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KOT MATPOCKuHДавай попробуем вариант с такими индексами?Давайте. На всякий случай привожу результаты для трех разных дат:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
SQL> create table hist(kod integer,start_dt date,end_dt date);

Таблица создана.

SQL> create index ix_hist_1 on hist(start_dt,end_dt);

Индекс создан.

SQL> create index ix_hist_2 on hist(end_dt,start_dt);

Индекс создан.

SQL> insert into hist(kod, start_dt,end_dt)
   2   select lv, sysdate-lv, sysdate-lv+ 1  from
   3   (select level as lv from dual connect by level <= 1000000 ) pivot;

 1000000  строк создано.

SQL> analyze table hist compute statistics;

Таблица проанализирована.

SQL> set autotrace on   
SQL> SELECT *
   2   FROM hist t1
   3   WHERE t1.start_dt < sysdate- 1000  and t1.end_dt >=sysdate- 1000 ;

       KOD START_DT END_DT
---------- -------- --------
       1000   22 . 02 . 06   23 . 02 . 06 

План выполнения
------------------------------------------------------------------------------
| Id  | Operation                   | Name      | Rows  | Bytes | Cost (%CPU)|
------------------------------------------------------------------------------
|    0  | SELECT STATEMENT            |           |   1000  |  18000  |     13    ( 0 )|
|    1  |  TABLE ACCESS BY INDEX ROWID| HIST      |   1000  |  18000  |     13    ( 0 )|
|*   2  |   INDEX RANGE SCAN          | IX_HIST_2 |   1000  |       |      9    ( 0 )|
------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
    2  - access("T1"."END_DT">=SYSDATE@!- 1000  AND "T1"."END_DT" IS NOT
              NULL)
       filter("T1"."START_DT"<SYSDATE@!- 1000 )

Статистика
----------------------------------------------------------
           1   recursive calls
           0   db block gets
          11   consistent gets
           9   physical reads
           0   redo size
         452   bytes sent via SQL*Net to client
         373   bytes received via SQL*Net from client
           2   SQL*Net roundtrips to/from client
           0   sorts (memory)
           0   sorts (disk)
           1   rows processed

SQL> SELECT *
   2   FROM hist t1
   3   WHERE t1.start_dt < sysdate- 990000  and t1.end_dt >=sysdate- 990000 ;

       KOD START_DT END_DT
---------- -------- --------
     990000   17 . 05 . 02   18 . 05 . 02 

План выполнения
------------------------------------------------------------------------------
| Id  | Operation                   | Name      | Rows  | Bytes | Cost (%CPU)|
------------------------------------------------------------------------------
|    0  | SELECT STATEMENT            |           |   9900  |   174K|    109    ( 2 )|
|    1  |  TABLE ACCESS BY INDEX ROWID| HIST      |   9900  |   174K|    109    ( 2 )|
|*   2  |   INDEX RANGE SCAN          | IX_HIST_1 |   9900  |       |     73    ( 3 )|
------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
    2  - access("T1"."END_DT">=SYSDATE@!- 990000  AND
              "T1"."START_DT"<SYSDATE@!- 990000 )
       filter("T1"."END_DT">=SYSDATE@!- 990000 )

Статистика
----------------------------------------------------------
           1   recursive calls
           0   db block gets
          72   consistent gets
          67   physical reads
           0   redo size
         452   bytes sent via SQL*Net to client
         373   bytes received via SQL*Net from client
           2   SQL*Net roundtrips to/from client
           0   sorts (memory)
           0   sorts (disk)
           1   rows processed

SQL> SELECT *
   2   FROM hist t1
   3   WHERE t1.start_dt < sysdate- 500000  and t1.end_dt >=sysdate- 500000 ;

       KOD START_DT END_DT
---------- -------- --------
     500000   03 . 12 . 39   04 . 12 . 39 

План выполнения
---------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)|
---------------------------------------------------------------
|    0  | SELECT STATEMENT  |      |   250K|  4394K|    978   ( 20 )|
|*   1  |  TABLE ACCESS FULL| HIST |   250K|  4394K|    978   ( 20 )|
---------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
    1  - filter("T1"."START_DT"<SYSDATE@!- 500000  AND
              "T1"."END_DT">=SYSDATE@!- 500000 )

Статистика
----------------------------------------------------------
           1   recursive calls
           0   db block gets
        3591   consistent gets
        1293   physical reads
           0   redo size
         452   bytes sent via SQL*Net to client
         373   bytes received via SQL*Net from client
           2   SQL*Net roundtrips to/from client
           0   sorts (memory)
           0   sorts (disk)
           1   rows processed
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35659491
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну и на всякий случай, зависимость(точнее, ее отсутствие) от значения параметра для варианта с одной датой в таблице:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
SQL> create table hist(kod integer,dt date);

Таблица создана.

SQL> create index ix_hist_1 on hist(dt);

Индекс создан.

SQL> insert into hist(kod, dt)
   2   select lv, sysdate-lv from
   3   (select level as lv from dual connect by level <= 1000000 ) pivot;

 1000000  строк создано.

SQL> analyze table hist compute statistics;

Таблица проанализирована.

SQL> set autotrace on   
SQL> SELECT kod FROM hist t1
   2    WHERE t1.dt = (SELECT max(t2.dt) FROM hist t2
   3                     WHERE t2.dt < sysdate -  1000 );

       KOD
----------
       1000 

План выполнения
---------------------------------------------------------------------------------
| Id  | Operation                      | Name      | Rows  | Bytes | Cost (%CPU)|
---------------------------------------------------------------------------------
|    0  | SELECT STATEMENT               |           |      1  |     11  |      7    ( 0 )|
|    1  |  TABLE ACCESS BY INDEX ROWID   | HIST      |      1  |     11  |      4    ( 0 )|
|*   2  |   INDEX RANGE SCAN             | IX_HIST_1 |      1  |       |      3    ( 0 )|
|    3  |    SORT AGGREGATE              |           |      1  |      7  |            |
|    4  |     FIRST ROW                  |           |   999K|  6829K|      3    ( 0 )|
|*   5  |      INDEX RANGE SCAN (MIN/MAX)| IX_HIST_1 |   999K|  6829K|      3    ( 0 )|
---------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
    2  - access("T1"."DT"= (SELECT MAX("T2"."DT") FROM "HIST" "T2" WHERE
              "T2"."DT"<SYSDATE@!- 1000 ))
    5  - access("T2"."DT"<SYSDATE@!- 1000 )

Статистика
----------------------------------------------------------
           1   recursive calls
           0   db block gets
           8   consistent gets
           2   physical reads
           0   redo size
         330   bytes sent via SQL*Net to client
         373   bytes received via SQL*Net from client
           2   SQL*Net roundtrips to/from client
           0   sorts (memory)
           0   sorts (disk)
           1   rows processed

SQL> SELECT kod FROM hist t1
   2    WHERE t1.dt = (SELECT max(t2.dt) FROM hist t2
   3                     WHERE t2.dt < sysdate -  990000 );

       KOD
----------
     990000 

План выполнения
---------------------------------------------------------------------------------
| Id  | Operation                      | Name      | Rows  | Bytes | Cost (%CPU)|
---------------------------------------------------------------------------------
|    0  | SELECT STATEMENT               |           |      1  |     11  |      7    ( 0 )|
|    1  |  TABLE ACCESS BY INDEX ROWID   | HIST      |      1  |     11  |      4    ( 0 )|
|*   2  |   INDEX RANGE SCAN             | IX_HIST_1 |      1  |       |      3    ( 0 )|
|    3  |    SORT AGGREGATE              |           |      1  |      7  |            |
|    4  |     FIRST ROW                  |           |  10000  |  70000  |      3    ( 0 )|
|*   5  |      INDEX RANGE SCAN (MIN/MAX)| IX_HIST_1 |  10000  |  70000  |      3    ( 0 )|
---------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
    2  - access("T1"."DT"= (SELECT MAX("T2"."DT") FROM "HIST" "T2" WHERE
              "T2"."DT"<SYSDATE@!- 990000 ))
    5  - access("T2"."DT"<SYSDATE@!- 990000 )

Статистика
----------------------------------------------------------
           1   recursive calls
           0   db block gets
           8   consistent gets
           1   physical reads
           0   redo size
         330   bytes sent via SQL*Net to client
         373   bytes received via SQL*Net from client
           2   SQL*Net roundtrips to/from client
           0   sorts (memory)
           0   sorts (disk)
           1   rows processed

SQL> SELECT kod FROM hist t1
   2    WHERE t1.dt = (SELECT max(t2.dt) FROM hist t2
   3                     WHERE t2.dt < sysdate -  500000 );

       KOD
----------
     500000 

План выполнения
---------------------------------------------------------------------------------
| Id  | Operation                      | Name      | Rows  | Bytes | Cost (%CPU)|
---------------------------------------------------------------------------------
|    0  | SELECT STATEMENT               |           |      1  |     11  |      7    ( 0 )|
|    1  |  TABLE ACCESS BY INDEX ROWID   | HIST      |      1  |     11  |      4    ( 0 )|
|*   2  |   INDEX RANGE SCAN             | IX_HIST_1 |      1  |       |      3    ( 0 )|
|    3  |    SORT AGGREGATE              |           |      1  |      7  |            |
|    4  |     FIRST ROW                  |           |   500K|  3417K|      3    ( 0 )|
|*   5  |      INDEX RANGE SCAN (MIN/MAX)| IX_HIST_1 |   500K|  3417K|      3    ( 0 )|
---------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
    2  - access("T1"."DT"= (SELECT MAX("T2"."DT") FROM "HIST" "T2" WHERE
              "T2"."DT"<SYSDATE@!- 500000 ))
    5  - access("T2"."DT"<SYSDATE@!- 500000 )

Статистика
----------------------------------------------------------
           1   recursive calls
           0   db block gets
           8   consistent gets
           2   physical reads
           0   redo size
         330   bytes sent via SQL*Net to client
         373   bytes received via SQL*Net from client
           2   SQL*Net roundtrips to/from client
           0   sorts (memory)
           0   sorts (disk)
           1   rows processed

SQL> set autotrace off
SQL> drop table hist;

Таблица удалена.

SQL> create table hist(kod integer,start_dt date,end_dt date);

Таблица создана.

SQL> create index ix_hist_1 on hist(start_dt,end_dt);

Индекс создан.

SQL> create index ix_hist_2 on hist(end_dt,start_dt);
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35659686
вопросик_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Bogdanov Andreyt1.start_dt < sysdate-500000 and t1.end_dt >=sysdate-500000
а почему вы для двух дат такое "вывернутое" условие задаете ? Намеренно сносите голову оптимизатору на специфических данных ?
Imho, нечто вроде сферического коня в вакууме.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35659709
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вопросик_а почему вы для двух дат такое "вывернутое" условие задаете ?Что именно "вывернутого" в этом условии? Как бы вы его написали? Если надо найти значение, которые было на дату sysdate-500000?
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35660430
Bely
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KOT MATPOCKuHА если сделать индекс по END_DT, START_DT он его схватит или нет?

Т.е. вообще иметь два индекса:
1) START_DT, END_DT
2) END_DT, START_DTУ меня на маленьком тесте - он схватывал индекс, но радости от этого было мало. (Oracle 9.2)

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

Есть у теста еще одна особенность - короткая запись в таблице (мало полей) из-за этого Full Table Scan иногда становится лучше чем поиск по индексу.

Я склоняюсь к мнению, что если использовать две даты, то строить надо только один индекс - по первой дате :)
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35660438
Bely
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Единственное когда две даты серьезно выиграют - это если в интервалах будут разрывы и время жизни товара не будет непрерывно.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35660868
вопросик_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Bogdanov AndreyЕсли надо найти значение, которые было на дату sysdate-500000?
Для начала определитесь - у вас в таблице хранится один товар или разные ?

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

Тогда для двух дат запрос может быть примерно(навскидку, топорно) такой:
Код: plaintext
1.
2.
3.
4.
5.
  select * 
    from
     (select * from hist t1 where start_dt < sysdate- 1000  order by start_dt desc) 
  where 
     rownum< 2  and  end_dt >=sysdate- 1000 

PS аккуратнее сравнивать нужно
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35661002
Bely
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вопросик_Если пачка разных - то тогда ваш первый запрос (который с одной датой) некорректен в приведенном вами виде;
если же один товар в таблице - то очевидно, для второго запроса (который с двумя датами) исходя из вполне здравых предположений - не должно возвращаться более одной записи(не должно быть на одну дату больше одной версии).Для этого можно использовать дополнительную группировку по типу товара и скорее всего придется добавить поле "код товара" в индекс. И что это поменяет кардинально?
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35661012
вопросик_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BelyДля этого можно использовать дополнительную группировку по типу товара и скорее всего придется добавить поле "код товара" в индекс. И что это поменяет кардинально?
Кардинально ? Если без кода товара ? Я вам привел вариант с двумя датами. У вас же oracle ? Проверьте этот вариант и сравните с тем, что приводил Bogdanov Andrey. Результаты в студию, если не трудно.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35661201
Bely
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вопросик_У вас же oracle ? Проверьте этот вариант и сравните с тем, что приводил Bogdanov Andrey. Результаты в студию, если не трудно.Оракл-то есть, со временем, к сожалению, туго...
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35661353
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вопросик_PS аккуратнее сравнивать нужноВ качестве преимущества варианта с двумя датами указывалась простота запросов и их производительность. Причем в качестве простого запроса предлагался имеено вариант "тупо" сравнивающий искомую дату с границами диапазона.
Вы предложили "сложный" запрос, который для поиска записи фактически не использует вторую дату, то есть работает также как и для таблицы с одной датой. Вторая дата в вашем запросе используется только для отсечения случая разрывов в истории. Случай разрывов для варианта с одной датой в этом треде уже рассматривался, поэтому рассматривать его снова я смысла не вижу.

PS. Читать нужно перед тем как отвечать. :)
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35661611
sp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoftMasterZivЕсли оптимизатор совсем тупой, переписываем

SELECT *
FROM Tovar_history
WHERE @date_now between DateStart and DateEnd
union all
SELECT *
FROM Tovar_history
WHERE DateEnd >= @date_now and DateStart IS NULL
union all
SELECT *
FROM Tovar_history
WHERE DateStart <= @date_now and DateEnd IS NULL
union all
SELECT *
FROM Tovar_history
WHERE DateStart IS NULL and DateEnd IS NULL

и приплыли...

вообще то нормальные люди null не заносят а заносят константы выходящие за диапазон к примеру: '01.01.1800' и '01.01.3000'
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35661626
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
spmiksoftunion all
SELECT *
FROM Tovar_history
WHERE DateStart IS NULL and DateEnd IS NULL

и приплыли...вообще то нормальные люди null не заносят а заносят константы выходящие за диапазон к примеру: '01.01.1800' и '01.01.3000'Bogdanov AndreyЧитать нужно перед тем как отвечать. :)
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35663984
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sp пишет:

> вообще то нормальные люди null не заносят а заносят константы выходящие
> за диапазон к примеру: '01.01.1800' и '01.01.3000'

Это вы что-то перепутали. как раз нормальные люди используют для этого
специально придуманный для этого NULL.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35664004
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivЭто вы что-то перепутали. как раз нормальные люди используют для этого
специально придуманный для этого NULL.
Философски тут можно поспорить. NULL - некий эквивалент бытового понятия "значение неизвестно", но для даты начала действия оно-то уж точно известно - скажем это может быть дата начала деятельности фирмы. История любой учетной величины имеет свое начало, другое дело, что разбираться с этим нет желания.
Дата конца истории тоже понятная величина - это текущее время (в будущем - это уже не история :) ). Так что никаких неизвестных величин тут нет. :)
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35664317
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bogdanov Andrey пишет:

> Философски тут можно поспорить. NULL - некий эквивалент бытового понятия
> "значение неизвестно",

Тут и спорить нечего. NULL - это и есть значение, которое заведомо
несовпадает ни с одним значением домена.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35664406
Alex S
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivТут и спорить нечего. NULL - это и есть значение, которое заведомо
несовпадает ни с одним значением домена.
Строго говоря, нельзя сказать "несовпадает" ).
К тому-же в данном случае мы имеем некие характеристики значения т.к. известно что первое значение даты меньше, а последнее больше. Т.е. уже вроде как не null.

Ну да ладно, все равно голосую за вариант с одной датой, тем более, судя по всему, у автора MSSQL, а не oracle. А значит можно использовать такой запрос:

Код: plaintext
select top  1  Name from Tovar_history where id = :id and Date <= :Date order by Date desc
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35664625
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivТут и спорить нечего. NULL - это и есть значение, которое заведомо
несовпадает ни с одним значением домена.
Ну во-первых, я предупредил, что вопрос философский, поэтому рассматривать его нужно не с практической точки зрения.
Во-вторых, у вас странное представление о NULL. NULL, это не "нечто ни с чем не совпадающее", у него вполне конкретный смысл - "значение неизвестно".
В-третьих, для случая с историей значений в качестве даты начала нужно некоторое значение "минус бесконечность" :) Так как ни один производитель СУБД еще не расширил домены данных таким значением, так каждый сам выбирает что-то из имеющегося для его замены. И в данном случае использование NULL вместо минус бесконечности будет ровно таким же частным соглашением, как и 24 августа 1572 года (оба варианта в подавляющем большинстве систем заведомо не совпадают ни с одним из допустимых значений). Более того, с практической точки зрения использование конкретной даты удобнее, так как позволяет писать более простые запросы.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35665788
Funny_Falcon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще-то Bogdanov Andrey немного неправильно построил примеры.
Более близкой аналогией будет структура таблиц:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
create table hist1(kod integer,dt date, val integer);
create index ix_hist_1_1 on hist1(dt);
create index ix_hist_1_2 on hist1(kod, dt);
-- vs
create table hist2(kod integer,start_dt date,end_dt date, val integer);
create index ix_hist_2_1 on hist2(start_dt);
create index ix_hist_2_2 on hist2(end_dt);
create index ix_hist_2_3 on hist2(kod, start_dt);
create index ix_hist_2_4 on hist2(kod, end_dt);

-- Прошу прощения, Oracle под рукой нет, могу ошибиться:

insert into hist(kod, dt, val)
 select kod, sysdate-value, kod+value from
 (select level as kod from dual connect by level <= 1000 ) pivot1,
 (select level as value from dual connect by level <= 10000 ) pivot2;

insert into hist(kod, start_dt, end_dt, val)
 select kod, sysdate-value, sysdate-value+ 1 , kod+value from
 (select level as kod from dual connect by level <= 1000 ) pivot1,
 (select level as value from dual connect by level <= 10000 ) pivot2;

-- И от сюда выбрать все актуальные на момент:
SELECT kod, value FROM hist1 t1
  WHERE t1.dt = (SELECT max(t2.dt) FROM hist1 t2
                   WHERE t2.dt < sysdate -  1000  and t2.kod = t1.kod);

SELECT kod, value FROM hist2 t1
  WHERE t1.start_dt < sysdate- 1000  and t1.end_dt >=sysdate- 1000 ;
Могу ошибиться, но, надеюсь, понятно, что хотел сказать.
Можно протестировать это?
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35665793
Funny_Falcon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bogdanov Andrey В-третьих, для случая с историей значений в качестве даты начала нужно некоторое значение "минус бесконечность" :) Так как ни один производитель СУБД еще не расширил домены данных таким значением,
PostgreSQL имеет '-infinity'::timestamp и 'infinity'::timestamp
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35666263
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Funny_FalconВообще-то Bogdanov Andrey немного неправильно построил примеры.
Более близкой аналогией будет структура таблиц:
Хм. Я не знаю какие именно запросы интересуют автора. Я приводил пример на тот случай, если мы пытается понять состояние одного объекта на заданную дату. Вы приводите случай, когда пытаемся получить полный срез по всем объектам. По моему опыту первая задача возникает гораздо чаще. Ну а то, что во втором случае таблица с двумя датами может выиграть я писал еще на второй странице этого топика.
Если конкретно по вашим запросам, то во втором варианте все равно имеем full scan, а в первом - hash join. Количество обращений к диску (и время выполнения операций) очень сильно зависит от соотношения длины истории и количества объектов. При относительно малом числе объектов (разлиных значений поля kod) с длинной историей выигрывает первый вариант, при большом количестве объектов с короткой историей - второй.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35666286
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Funny_FalconPostgreSQL имеет '-infinity'::timestamp и 'infinity'::timestampСпасибо, буду знать. А где можно посмотреть на описание? Интересно как реализована арифметика и логические операцити с этим. А для числовых типов что-то подобное есть?
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35666522
Bely
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bogdanov AndreyFunny_FalconВообще-то Bogdanov Andrey немного неправильно построил примеры.
Более близкой аналогией будет структура таблиц:
Хм. Я не знаю какие именно запросы интересуют автора. Я приводил пример на тот случай, если мы пытается понять состояние одного объекта на заданную дату. Вы приводите случай, когда пытаемся получить полный срез по всем объектам. По моему опыту первая задача возникает гораздо чаще. Ну а то, что во втором случае таблица с двумя датами может выиграть я писал еще на второй странице этого топика.Есть подозрение, что это будет примерно одинаковов по эффективности.

Стоит посмотреть на такой запрос для одной даты и на составной индекс "kod, dt"
Код: plaintext
1.
2.
3.
4.
5.
SELECT kod, value FROM hist1 t1
  WHERE  (t1.kod,t1.dt) = 
           (SELECT t2.kod, max(t2.dt) FROM hist1 t2
            WHERE t2.dt < sysdate -  1000 
            GROUP BY t2.kod);

Запрос, составленный Funny_Falcon , не очень верный - дает неверный результат.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35666573
expla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Bely,

на философский вопрос не может быть практического ответа. В зависимости от СУБД ваш запрос (даже если его оптимизировать) может быть как быстрее так и медленнее простого

Код: plaintext
select * from t where id = :n and :date beetween d_from and d_to;

Если ваша СУБД хорошо переваривает такой запрос, то и нечего извращаться с одной датой.

А представьте, если нужно сопоставить состояния нескольких объектов, да не в определённый момент времени, а в исторической перспективе. Что тогда деать с одной датой?
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35666594
Bely
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
explaBely,

на философский вопрос не может быть практического ответа. В зависимости от СУБД ваш запрос (даже если его оптимизировать) может быть как быстрее так и медленнее простого

Код: plaintext
select * from t where id = :n and :date beetween d_from and d_to;
1. Эти запросы не эквивалентны друг-другу, поэтому филосовствовать по их поводу - бессмысленно.
2. Свои филосовские измышления я строю на пониамнии того как примерно будет выбирать сервер данные.

explaЕсли ваша СУБД хорошо переваривает такой запрос, то и нечего извращаться с одной датой.Здесь вопрос стоит не столько в том сколько дат использовать, а втом - сколько дат включать в индекс и какие индексы строить в разных вариантах.

explaА представьте, если нужно сопоставить состояния нескольких объектов, да не в определённый момент времени, а в исторической перспективе. Что тогда деать с одной датой?Собственно, базовый запрос нарисован - надо будет только запустить его на выполнение и анализировать :).
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35666612
expla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BelyЯ склоняюсь к мнению, что если использовать две даты, то строить надо только один индекс - по первой дате :)

Практика показывает, что для Оракла лучше индексировать обе даты. Тогда ещё на этапе сканирования индекса SQL машина отбросит нерелевантные данные и выполнит единственное чтение блока БД. Когда одна из дат не входит в индекс, а предикат на индексированную дату возврашает много строк SQL машина будет вынуждена дёрнуть каждую строку из блоков БД, чтобы проверить ограничение на непроиндексированную дату.

Опять же, практика показывает, что извращения с min(dt) ни чуть не быстрее сканирования индекса с двумя датами, но при этом такие запросы решают лишь малый класс задач.

Дополнительная память мало сказывается на скорости, потому как индекс обычно содержит много других данных, как минимум одну из дат и ROWID, ID объекта и т.п..
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35666628
expla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Bogdanov AndreyFunny_FalconPostgreSQL имеет '-infinity'::timestamp и 'infinity'::timestampСпасибо, буду знать. А где можно посмотреть на описание? Интересно как реализована арифметика и логические операцити с этим. А для числовых типов что-то подобное есть?

Нужно не путать понятие математической бесконечности, как предела некоторой бесконечной последовательности и специального значения переменной в дискретной ЭВМ.
Для типа date всегда определена самая ранняя и самая поздняя дата, которые этот тип может принять. Собственно эти даты и можно использовать в качестве самой большой и самой маленькой даты. Бесконечно большая и бесконечно малая даты несут в себе семантику недостижимой величины которую нельзя ни с чем сравнить (природа этой величины - некая неопределённось, которую можно раскрыть только аналитическими методами, но не численными). Такие даты вряд ли имеют практический смысл в нашем бренном мире, тем более для дискретных вычислительных машин.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35666684
Funny_Falcon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bogdanov AndreyFunny_FalconPostgreSQL имеет '-infinity'::timestamp и 'infinity'::timestampСпасибо, буду знать. А где можно посмотреть на описание? Интересно как реализована арифметика и логические операцити с этим. А для числовых типов что-то подобное есть?
8.5.1.5. Special Values
8.1.3. Floating-Point Types
Тесты в версии PostgreSQL 8.3
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
test1=# select timestamp '-infinity' < now(), timestamp 'infinity' > now(), timestamp 'infinity' > timestamp '-infinity';
 ?column? | ?column? | ?column?
----------+----------+----------
 t        | t        | t
( 1  запись)

test1=# select timestamp '-infinity' + interval '1 day', timestamp '-infinity' - interval '1 day';
 ?column?  | ?column?
-----------+-----------
 -infinity | -infinity
( 1  запись)

test1=# select timestamp 'infinity' + interval '1 day', timestamp 'infinity' - interval '1 day';
 ?column? | ?column?
----------+----------
 infinity | infinity
( 1  запись)

test1=# select timestamp 'infinity' - timestamp '-infinity';
ERROR:  cannot subtract infinite timestamps

test1=# select timestamp 'infinity' - now();
ERROR:  cannot subtract infinite timestamps

test1=# select now() - timestamp 'infinity';
ERROR:  cannot subtract infinite timestamps
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
test1=# select 'infinity'::float8 > 1e100, '-infinity'::float8 < -1e100, 'infinity'::float8 > 'infinity'::float8  ;
 ?column? | ?column? | ?column?
----------+----------+----------
 t        | t        | t
( 1  запись)

-- С сожалением обнаружил что:
test1=# select  1 /'infinity'::float8;
ERROR:  value out of range: underflow

test1=# select  1 . 0 ::float8 * 'infinity'::float8,  1  + 'infinity'::float8,  1  - 'infinity'::float8,  1  - '-infinity'::float8,  1  + '-infinity'::float8;
 ?column? | ?column? | ?column?  | ?column? | ?column?
----------+----------+-----------+----------+-----------
 Infinity | Infinity | -Infinity | Infinity | -Infinity
( 1  запись)

test1=# select 'infinity'::float8 - 'infinity'::float8, 'infinity'::float8 - '-infinity'::float8, 'infinity'::float8 + '-infinity'::float8;
 ?column? | ?column? | ?column?
----------+----------+----------
      NaN | Infinity |      NaN
( 1  запись)

К сожалению это только для чисел с плавающей точкой, numeric 'infinity' не поддерживает
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35666754
expla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добавлю 5 копеек по теме.

История сущности может характеризоваться её состояниями и переходами этих состояний (как граф, можно описывать и рёбрами и узлами). В этом смысле второй вариант (с диапазоном дат) реализует модель с истории состояний. Что касается переходов, то переход характеризуется исходным и конечным состоянием и датой. В этом смысле первому варианту не хватает полей для хранения предыдущего состояния.

Принцип один факт, одна запись для второго случая нужно рассмотреть с другой стороны. Факт перехода состояния мы не регистрируем в БД, мы регистрируем два факта - завершение старого сотояние и создание нового состояния, отсюда и вовлечение в транзакцию двух записей.

Обеспечение целостности в обеих случаях для современных реляционных СУБД, которые ориентированы на хранение состояния системы на один момент времени, задача нетривиальная. Ну нету в них адекватных декларативных ограничений целостности! То что говорили о зависимости записей, то Primary Key пример такой зависимости, т.е. возможность изменять значения ключевого поля одной записи зависит от значений этого поля в других записях таблицы и это нормально!

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

В первом случае мы наблюдаем лишь иллюзию надёжности по той причине, что в записи о переходе состояния нет данных о прежнем состоянии. Таким образом можно в историческую последовательность воткнуть произвольную запись, которая логически не могла быть результатом перехода из предыдущего состояния, и не может быть исходным состоянием для следующего перехода. Проверка корректности таких переходов опять же лежит на совести программного обеспечения БД.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35666926
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
expla пишет:

> времени, задача нетривиальная. Ну нету в них адекватных декларативных
> ограничений целостности! То что говорили о зависимости записей, то

Да есть, только недекларативные - триггерами.
Кстати, тут вот R:Base вспоминали. Так там, если не
изменяет память, как раз были check constraint-ы, позволяющие
внутри писать запрос ЛЮБОЙ СЛОЖНОСТИ, и даже из других таблиц.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35667074
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Funny_FalconТесты в версии PostgreSQL 8.3Спасибо. Исчерпывающе.

Тут кстати и объяснение для expla почему специальный литерал лучше, чем некоторая "самая ранняя дата" из поддерживаемых системой. Вряд ли для самой ранней даты будут выполняться приведенные арифметические правила. Ну а то, что этот литерал не является эквивалентом "математической бесконечности" меня не смущает. Мне математическая бесконечность и не нужна. :)
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35667176
Фотография призрак коммунизма
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv
expla пишет:

> времени, задача нетривиальная. Ну нету в них адекватных декларативных
> ограничений целостности! То что говорили о зависимости записей, то

Да есть, только недекларативные - триггерами.
Кстати, тут вот R:Base вспоминали. Так там, если не
изменяет память, как раз были check constraint-ы, позволяющие
внутри писать запрос ЛЮБОЙ СЛОЖНОСТИ, и даже из других таблиц.
А в других СУБД разве нельзя в constraint`ах использовать функции?
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35667263
KOT MATPOCKuH
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
expla
Практика показывает, что для Оракла лучше индексировать обе даты.
Что за практика? Чем лучше?

expla
Тогда ещё на этапе сканирования индекса SQL машина отбросит нерелевантные данные и выполнит единственное чтение блока БД. Когда одна из дат не входит в индекс, а предикат на индексированную дату возврашает много строк SQL машина будет вынуждена дёрнуть каждую строку из блоков БД, чтобы проверить ограничение на непроиндексированную дату.

Я тоже так считал, но показанные Bogdanov Andrey результаты говорят об обратном (почти).
Данных-то читать - один блок. А сколько блоков индекса читать?

expla
Опять же, практика показывает, что извращения с min(dt) ни чуть не быстрее сканирования индекса с двумя датами, но при этом такие запросы решают лишь малый класс задач.

Дак познакомьте с практикой! Очень интересно! Надо бы по конкретнее

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

Короче, мозк нада было включить!!!

Очень понравилось то, что SELECT MAX(x) from t where x<:1 и для условия и для агрегирующей функции используется один индекс и один проход!!! Собственно это и победило при выборе алгоритма! Можно использовать две даты (если бизнес-логика хочет), запрос будет - как в варианте с одной датой, дополненный в конце условием на вторую дату (если есть "дыры").
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35667274
Bely
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KOT MATPOCKuH,
+1 - после показанных тестов вопрос что лучше перестает быть однозначным.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35667293
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
explaОпять же, практика показывает, что извращения с min(dt) ни чуть не быстрее сканирования индекса с двумя датамиПриведенные выше примеры как раз иллюстируют то, что "извращения" намного быстрее. Не буду спорить с тем, что у меня руки кривые, но других цифр пока никто не привел. Только теоретизируют. Ссылаясь на "практика показывает" постарайтесь приводить хоть какие-то доказательства.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35667308
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
призрак коммунизма пишет:

> А в других СУБД разве нельзя в constraint`ах использовать функции?
Функции можно как правило. Запросы нельзя.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35667350
Bely
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv> А в других СУБД разве нельзя в constraint`ах использовать функции?
Функции можно как правило. Запросы нельзя.
Тут есть тонкость - запрос сегодня может возвращать одно, завтра другое. В зависимости от данных, которые лежат в БД.
В таком случае может получиться, что те данные, которые были введены вчера - сегодня уже неверные. Как серверу поступать с ними?

Типичный пример недетерминированного правила:
Код: plaintext
date_fm > sysdate- 1 
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668049
вопросик_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Bogdanov AndreyПриведенные выше примеры как раз иллюстируют то, что "извращения" намного быстрее . Не буду спорить с тем, что у меня руки кривые, но других цифр пока никто не привел. Только теоретизируют. Ссылаясь на "практика показывает" постарайтесь приводить хоть какие-то доказательства. Передергиваете. Я приводил пример оптимизированного запроса с двумя датами для вашей модели. Индекс только по start_dt. Чтений там будет меньше, чем у вас раза в полтора-два (думаю, вы и сами это проверили) - за счет однократного прохода индекса.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668050
expla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Bogdanov AndreyexplaОпять же, практика показывает, что извращения с min(dt) ни чуть не быстрее сканирования индекса с двумя датамиПриведенные выше примеры как раз иллюстируют то, что "извращения" намного быстрее. Не буду спорить с тем, что у меня руки кривые, но других цифр пока никто не привел. Только теоретизируют. Ссылаясь на "практика показывает" постарайтесь приводить хоть какие-то доказательства.

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

с min(dt) требуется двойной поиск по индексу, сначала чтобы вычислить min, потом, чтобы найти ROWID искомой записи. Для between требуется лишь одно сканирование индекса, но в зависимости от того, что мы чаще ищем - записи в далёком прошлом или самые последние записи следует строить индекс либо по ключу (ID, DT_FROM, DT_TO) или (ID, DT_TO, DT_FROM) соответственно. В принципе, если данные таковы, что в большинстве случаев проверка второй даты не уменьшает количество возвращаемых строк (мне обычно нужно искать текущее состояние объекта и это состояние является крайним в последовательности состояний), то можно ограничиться индексом (ID, DT_FROM) или (ID, DT_TO) соответственно для поиска древних и молодых записей.

Если нужна взвешенная оценка, составте таблицу вида "аспект" X "вариант решения".

Аспект\РешениеПереходыСостоянияКод транзакцииПростой 3Сложный 1Код запросов Сложный 0 Простой 5Эффективность Средняя 3 Средняя 3Итого: 6 9

Это таблица для моих задач, и я свой вывод уже сделал. 3 - средняя оценка. Наибольший вес имеет аспект "Код запросов", поскольку в первую очередь нужно разработать приложения БД. Если из-за сложности модели данных это сделать не удасться, то всё остальное будет не важно. Запросов к БД обычно значительно больше, чем процедур, которые её изменяют, поэтому аспект "Код транзакции" имеет средний вес. Эффективность может быть разная. На моей БД она получается примерно одинаковой, кроме того скорость запросов для меня не является очень критично, поэтому я поставил среднюю оценку.

Аспекты, оценки и их вес в общем итоге вы определяете сами исходя из своих задач.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668070
expla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BelyMasterZiv> А в других СУБД разве нельзя в constraint`ах использовать функции?
Функции можно как правило. Запросы нельзя.
Тут есть тонкость - запрос сегодня может возвращать одно, завтра другое. В зависимости от данных, которые лежат в БД.
В таком случае может получиться, что те данные, которые были введены вчера - сегодня уже неверные. Как серверу поступать с ними?

Типичный пример недетерминированного правила:
Код: plaintext
date_fm > sysdate- 1 


Оракл на этот счёт уже не париться. Например, он уже определил UNIQUE без проверки. Т.е. старые данные, которые были заведены до создания UNIQUE могут содержать дубликаты, вновь создаваемые записи будут подвергаться проверке. Такое декларативное ограничение целостности можно рассматривать как бизнес правило, которое действует только во время изменения данных, но не является инвариантом всей БД.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668099
Bely
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вопросик_Чтений там будет меньше, чем у вас раза в полтора-два (думаю, вы и сами это проверили) - за счет однократного прохода индекса.1.Вы думаете, что поиск значения в индексе - медленнее, чем сканирование части индекса?
Веть для того, чтобы отсортировать результат - именно так и придется делать.
Одна надежда на то, что оптимизатор сам перевернет этот запрос к поиску max(dt_start)
2. Если строить индекс только по одной колонке, то это слабо отличается от варианта одной даты.
Я бы сказал - практически никак.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668104
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вопросик_Bogdanov AndreyПриведенные выше примеры как раз иллюстируют то, что "извращения" намного быстрее . Не буду спорить с тем, что у меня руки кривые, но других цифр пока никто не привел. Только теоретизируют. Ссылаясь на "практика показывает" постарайтесь приводить хоть какие-то доказательства. Передергиваете. Я приводил пример оптимизированного запроса с двумя датами для вашей модели. Индекс только по start_dt. Чтений там будет меньше, чем у вас раза в полтора-два (думаю, вы и сами это проверили) - за счет однократного прохода индекса.Вы как раз приводили пример с "извращениями" - когда используется поиск минимального значения одной даты. expla утверждал, что "извращения с min(dt) ни чуть не быстрее сканирования индекса с ДВУМЯ датами" вы при этом ссылаетесь на пример с индексом по ОДНОЙ дате и говорите, что я передергиваю. Предлагаю извиниться.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668111
Bely
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
explaОракл на этот счёт уже не париться. Например, он уже определил UNIQUE без проверки. Т.е. старые данные, которые были заведены до создания UNIQUE могут содержать дубликаты, вновь создаваемые записи будут подвергаться проверке.Имеете ввиду NOVALIDATE?
Ну - это не совсем то же, что и "сегодня вставленная запись правильная, а завтра стала неверной".
Это скорее "Я знаю, что у меня нормальные данные - не надо зря шуршать дисками".
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668126
вопросик_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Bely ...Вы думаете, что поиск значения в индексе - медленнее, чем сканирование части индекса? ... Если строить индекс только по одной колонке, то это слабо отличается от варианта Я бы сказал - практически никак.
У вас появилось время ? выполните тест, чтений там наверняка будет меньше. И это простейшем запросе по одному товару. Когда позиций будет больше - ситуация будет еще значительней отличаться.
Две даты оставляют больше места для оптимизации при необходимости. При том, что в ряде случаев запросы при двух датах будут проще.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668129
KOT MATPOCKuH
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
expla...с min(dt) требуется двойной поиск по индексу, сначала чтобы вычислить min, потом, чтобы найти ROWID искомой записи
А зачем искать "...ROWID искомой записи"? Дата есть в индексе (речь о конкретном запросе)
И зачем двойной поиск? В одном все делается не плохо
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668136
KOT MATPOCKuH
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вопросик_
При том, что в ряде случаев запросы при двух датах будут проще.
Проще для программиста или быстрее для оракла?
Пока не ответим на этот вопрос - бодаться бессмысленно
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668138
expla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Bely,

Да я NOVALIDATE. Я о том, что обычно декларативные ограничения целостности рассматривают только как инвариант всей БД. Но не редко нам нужно проверить только постусловие транзакции, и это постусловие может меняться со временем, как из-за недетерминированных функций, типа sysdate, так и из-за изменения кода процедуры проверки. Видимо речь об этом.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668140
Bogdanov Andrey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
explaУ каждого саоя практика.Нисколько не сомневаюсь в вашей практике, но здесь от вас вижу одну лишь теорию.

explaЕсли нужна взвешенная оценка, составте таблицу вида "аспект" X "вариант решения".В данном случае меня не интересуют ни взвешенные оценки, ни выбор какого-то варианта. В данном топике я лишь приводил примеры, доказывающие, что вопрос быстродействия для случая с двумя датами не столь очевиден. Вы взялись это оспорить, но ни одного подтверждающего примера не привели. В вопросе о быстродействии я воспринимаю только результаты экспериментов. Все остальные аргументы адресуйте кому-нибудь другому.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668143
Фотография ChA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivФункции можно как правило. Запросы нельзя.А что мешает убрать запрос под функцию ?
MS SQL 2000
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
USE pubs
GO
CREATE TABLE t (id int PRIMARY KEY)
GO
CREATE FUNCTION tcnt()
RETURNS int
BEGIN
RETURN (SELECT COUNT(*) FROM t)
END
GO
ALTER TABLE t ADD CONSTRAINT tcheck CHECK (dbo.tcnt() <  3 )
GO
INSERT INTO t SELECT  1 
INSERT INTO t SELECT  2 
INSERT INTO t SELECT  3 
SELECT * FROM t
GO
DROP TABLE t
DROP FUNCTION tcnt
Эффект практически тот же самый. Невозможность указания запроса в констрейнте может являтся лишь формальным, синтаксическим, ограничением.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668166
вопросик_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Bogdanov Andrey но других цифр пока никто не привел. Только теоретизируют. Ссылаясь на "практика показывает" постарайтесь приводить хоть какие-то доказательства
...
Вы как раз приводили пример с "извращениями" - когда используется поиск минимального значения одной даты. expla утверждал, что "извращения с min(dt) ни чуть не быстрее сканирования индекса с ДВУМЯ датами" вы при этом ссылаетесь на пример с индексом по ОДНОЙ дате и говорите, что я передергиваю. Предлагаю извиниться.
Отвечал именно на выделенное.
Далее - про "ссылаетесь на пример с индексом по ОДНОЙ" - индекс по двум датам - ситуация будет еще лучше в общем случае (например, когда нет актуальной записи на заданную дату), т.к. проверка по end_dt будет выполнена на индексном уровне.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668168
expla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
KOT MATPOCKuHexpla...с min(dt) требуется двойной поиск по индексу, сначала чтобы вычислить min, потом, чтобы найти ROWID искомой записи
А зачем искать "...ROWID искомой записи"? Дата есть в индексе (речь о конкретном запросе)
И зачем двойной поиск? В одном все делается не плохо

Как оракл выполняет запрос

Код: plaintext
1.
2.
3.
4.
5.
6.
select *
from t e
where (id, dt) in
 (select id, min(dt)
  from t i
  where e.id=i.id and :p < i.dt
 )

1. В индексе находит наименьшее значение dt большее :p, это и есть min(td)
... Замечу, что в старых версиях оракл SQL машина выгребала из индекса все подходящие ключи, сортировала их с группировкой, а затем возвращала min(dt).
2. В индексе находит ключ для искомой записи. Это уже второй поиск по индексу.
3. Используя полученный ROWID находит блок таблицы и извлекает из него нужную запись.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668193
expla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Bogdanov AndreyВ данном топике я лишь приводил примеры, доказывающие, что вопрос быстродействия для случая с двумя датами не столь очевиден.

Так и я о том же. И без всяких тестов ясно, что производительность будет зависеть от данных. Только, ИМХО, в данном случае производительность дело десятое.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668203
вопросик_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
explaИ без всяких тестов ясно, что производительность будет зависеть от данных. Только, ИМХО, в данном случае производительность дело десятое.
+1.
Если уже сильно прижмет (или запросы изначально часто выполняться будут) - всегда можно оптимизировать.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668229
Bely
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вопросик_Если уже сильно прижмет (или запросы изначально часто выполняться будут) - всегда можно оптимизировать.Ну-ну...
"Пытайтесь все делать как можно лучше! Плохо - оно само получится" (с) Гоблин
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668260
вопросик_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Прикинем что-нибудь более приближенное к жизни. по товару - как часто меняется цена ?
Пусть блок в бд - 8K. Пусть в среднем ключ займет leaf-блоке 40 байт. Т.е. в одном блоке поместятся примерно >~200 изменений цены. Поэтому в таком случае простой запрос с двумя датами будет работать шустро без всяких оптимизаций.
Для каких-то особых случаев повторяться не буду.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668297
Bely
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вопросик_Для каких-то особых случаев повторяться не буду.Да никаких особых случаев...
табличка SYS_FBA_HIST_xxx по одной нашей таблице за месяц ТЕСТИРОВАНИЯ уже насобирала 4 млн. записей. Данные пока загружены не в полном объеме (одна сотая часть).
эта системная таблица выглядит так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
CREATE TABLE sys_fba_hist_19511
    (rid                            VARCHAR2( 4000 ),
    startscn                       NUMBER,
    endscn                         NUMBER,
    xid                            RAW( 8 ),
    operation                      VARCHAR2( 1 ),
    list_id                        NUMBER( 38 , 0 ),
    object_id                      NUMBER( 9 , 0 ),
    status_id                      NUMBER( 38 , 0 ),
    priority                       NUMBER( 38 , 0 ),
    workflow_step_id               NUMBER( 38 , 0 ),
    recall_date                    DATE)
Для незнакомых с Oracle - SCN можно перетранслировать в TIMESTAMP.
Так что для кого-то работа с такими данными "ничего можно не делать", для кого-то потенциальная головная боль.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668302
вопросик_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Belyвопросик_Если уже сильно прижмет (или запросы изначально часто выполняться будут) - всегда можно оптимизировать.Ну-ну...
Извините, вы реально сталкивались с процессом разработки ?

1) Примерно известно цели систем, характер данных, которые она будет обрабатывать, исходя из этого выстраивается логика обработки данных
2) Всегда прикидываются критичные запросы, они "вылизываются".
3) Выполняется тестирование системы.
На этапе пробной эксплуатации(и последующей) выявляются "узкие" места.

Вот про строить суперуниверсальную систему, сразу оптимизированную на зарнее неизвестные, все возможные в жизни случаи, которые неожиданно, не понятно откуда могут возникнут, вот это действительно - "ну-ну..."
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668331
expla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Belyвопросик_Если уже сильно прижмет (или запросы изначально часто выполняться будут) - всегда можно оптимизировать.Ну-ну...
"Пытайтесь все делать как можно лучше! Плохо - оно само получится" (с) Гоблин

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

Тем временем тест - "выбрать текущие состояния всех объектов":

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
select count(sddc) from (
select /*+ no_merge index(e tp$id) use_nl(e) */ *
from tp e
where (id, d_to) in
 (select /*+ leading(i) index(e tp$id) */ id, min(d_to)
  from tp i
  where sysdate <= i.d_to
  group by id
 )
)

~  0 . 1  sec

select count(sddc) from (
select /*+ no_merge index(e tp$id)  */ *
from tp e
where sysdate between d_from and d_to
)

~  0 . 05  sec

Индекс tp$id это (id, d_to, d_from). Возможно доработка индекса немного ускорит первый запрос (но скорее всего и первый запрос тоже ускорится), но даже в силу того, что первый код существенно сложнее я не буду его использовать.

Замечу, что оракл в данном случае предпочитает не использовать индексы вообще, но тут суть в том, чтобы запрос выполнил много операций поиска по индексу.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668360
Bely
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вопросик_Извините, вы реально сталкивались с процессом разработки ?
...
Вот про строить суперуниверсальную систему, сразу оптимизированную на зарнее неизвестные, все возможные в жизни случаи, которые неожиданно, не понятно откуда могут возникнут, вот это действительно - "ну-ну..."Сталкивался и продолжаю сталкиваться .

Кроме этого видел как реально работающие и протестированные системы начинали загибаться после того как менялась учетная политика организации и в системе появлялось в 10 раз больше проводимых документов.

Так что к вашим пунктам надо добавить "планирование будующих потоков данных".
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668373
вопросик_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Belyвопросик_Для каких-то особых случаев повторяться не буду.Да никаких особых случаев...
табличка SYS_FBA_HIST_xxx по одной нашей таблице за месяц ТЕСТИРОВАНИЯ уже насобирала 4 млн. записей. Данные пока загружены не в полном объеме (одна сотая часть).
эта системная таблица выглядит так:
Ну и ? Не можете оптимизировать обработку и, почитав этот топик решили, что без end_scn будет быстрее ? :)

Андрей специально привел некий особый случай данных, на которых "лобовой" запрос с двумя данными проигрывал. Для тех же данных я привел другой (не сложнее по содержанию запроса Андрея) запрос с двумя датами, который работает оптимальней для поставленной задачи.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668403
expla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
вопросик_,

+1. С двумя датами открывается широкое поле возможностей оптимизации. И индексы можно покрутить и запросы и планы. Оратная сторона вопроса, легко наткнуться на плохой вариант.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668410
Bely
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вопросик_Ну и ? Не можете оптимизировать обработку и, почитав этот топик решили, что без end_scn будет быстрее ? :) Да можем мы все, просто не стоит забывать, что песочницы у всех разного размера. Если данных мало - то индекс вобще лучше не строить.

Почитав этот топик я понял, что когда придет время - надо будет тестировать, а не просто строить индекс по двум SCN.
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35668666
Фотография призрак коммунизма
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
select * from table1 where sysdate between start_date and end_date
принципиально не используете?
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35669543
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
expla пишет:

> У каждого саоя практика. Речь лишь о том, что на разных СУБД, на разных
> экземплярах СУБД и на разных экземплярах БД результат может быть разным,
> в пользу любого из решений.

Я очень сильно сомневаюсь, что здесь есть какая-то специфика СУБД.
B+tree индексы есть в любой СУБД, и почти одинаковы. А вот от специфики задачи
может зависить многое. Хорошую вы табличку нарисовали.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35669550
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ChA пишет:

> CREATE TABLE t (id int PRIMARY KEY)
> GO
> CREATE FUNCTION tcnt()
....
> ALTER TABLE t ADD CONSTRAINT tcheck CHECK (dbo.tcnt() < *3*)

В некоторых СУБД нет и функций, определяемых пользователем.
Или функций, которые могут делать запросы.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35670108
KOT MATPOCKuH
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
призрак коммунизмаselect * from table1 where sysdate between start_date and end_date
принципиально не используете?
Да, потому что не верно.
Т.к. тема - история изменения значения, то в момент end_date данные этой строки не актуальны (уже другая строка должна действовать).
Читайте внимательнее ;)
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35670900
Фотография призрак коммунизма
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KOT MATPOCKuHпризрак коммунизмаselect * from table1 where sysdate between start_date and end_date
принципиально не используете?
Да, потому что не верно.
Т.к. тема - история изменения значения, то в момент end_date данные этой строки не актуальны (уже другая строка должна действовать).
Читайте внимательнее ;) Кто-то мешает при добавлении новой "исторической" записи изменить end_date предыдущей записи?

(естественно, надо сначала определиться с точностью - день/час/секунда/...)
...
Рейтинг: 0 / 0
История одна дата vs две. Что лучше?
    #35671609
Funny_Falcon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Postgresql >= 8.1
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
create type time_interval as (
  start timestamp,
  stop timestamp
);
-- + ешё 9kb исходников

create table test1 ( 
	id int4,
	period time_interval,
	value varchar
);
create unique index uix on test1 (id, period time_interval_ops );
create index ix on test1( id, ( (period).start ) );
create index ix1 on test1( ( (period).start ) );

insert into test1( id, period, value )
select i, (now - (j)*'1 day'::interval, now - (j- 1 )*'1 day'::interval)::time_interval,
    'value '||i||' '||j
from generate_series(  1 ,  500  ) as i, generate_series(  1 ,  400  ) as j,
     ( select date_trunc('day', now()) as now ) as t;

select * from test1 where id =  333  and period = now()::timestamp-'10 week'::interval;
id; period; value
--------------------------------------------------------
 333 ;"(" 2008 - 09 - 15   00 : 00 : 00 "," 2008 - 09 - 16   00 : 00 : 00 ")";"value 333 70"

explain analyze select * from test1 where id =  333  and period = now()::timestamp-'10 week'::interval;
---------------------------------------------------
"Index Scan using uix on test1  (cost=0.26..338.95 rows=196 width=49) (actual time=0.402..0.407 rows=1 loops=1)"
"  Index Cond: ((id = 333) AND (period = ((now())::timestamp without time zone - '70 days'::interval)))"
"Total runtime: 0.492 ms"

explain analyze select * from test1 where id =  333  and
	    (period).start <= now()::timestamp-'10 week'::interval 
	and (period).stop > now()::timestamp-'10 week'::interval;
----------------------------------------------------
"Index Scan using ix on test1  (cost=0.01..233.28 rows=44 width=49) (actual time=0.933..0.935 rows=1 loops=1)"
"  Index Cond: ((id = 333) AND ((period).start <= ((now())::timestamp without time zone - '70 days'::interval)))"
"  Filter: ((period).stop > ((now())::timestamp without time zone - '70 days'::interval))"
"Total runtime: 0.886 ms"

insert into test1( id, period, value )
select  333 , (now() - '11 day'::interval, now() - '10 day'::interval)::time_interval,
    'value '|| 333 ||' '|| 10 ;
----------------------------------------------------
ERROR:  duplicate key value violates unique constraint "uix"

********** Ошибка **********

ERROR: duplicate key value violates unique constraint "uix"
SQL state:  23505 

Как видим, целостность можно обеспечить.
Равно как и ускорить поиск, задействующий id, приблизительно в два раза.

А вот выбор среза быстрее с одним индексом:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
explain analyze select * from test1 where period = now()::timestamp-'10 week'::interval;
---------------------------------------------------------------------------------------
"Index Scan using uix on test1  (cost=0.26..16802.73 rows=100000 width=49) (actual time=1.637..789.308 rows=500 loops=1)"
"  Index Cond: (period = ((now())::timestamp without time zone - '70 days'::interval))"
"Total runtime: 789.974 ms"

explain analyze select * from test1 where
	    (period).start <= now()::timestamp-'10 week'::interval 
	and (period).stop > now()::timestamp-'10 week'::interval;
---------------------------------------------------------------------------------------
"Bitmap Heap Scan on test1  (cost=1241.84..5303.85 rows=22222 width=49) (actual time=115.540..458.447 rows=500 loops=1)"
"  Recheck Cond: ((period).start <= ((now())::timestamp without time zone - '70 days'::interval))"
"  Filter: ((period).stop > ((now())::timestamp without time zone - '70 days'::interval))"
"  ->  Bitmap Index Scan on ix1  (cost=0.00..1236.28 rows=66667 width=0) (actual time=114.911..114.911 rows=165500 loops=1)"
"        Index Cond: ((period).start <= ((now())::timestamp without time zone - '70 days'::interval))"
"Total runtime: 459.885 ms"
Однако это потому, что нельзя построить btree индекс по полю period без поля id - пересекающиеся периоды не поддерживаются.
Однако, думаю можно будет прикрутить GIST индекс - по аналогии с RTree индексами.
...
Рейтинг: 0 / 0
129 сообщений из 129, показаны все 6 страниц
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / История одна дата vs две. Что лучше?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]