Конференция "Базы" » Индекс с интервалами дат
 
  • Дмитрий С © (14.03.15 17:31) [0]
    Добрый день.

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

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

    Как организовать индекс для поиска?
  • DVM © (14.03.15 17:32) [1]
    составной индекс по двум полям можно сделать
  • TohaNik © (14.03.15 18:30) [2]
    Нет такого индекса, нужно номер какой то, ФИО, ну или еще что то подобное..
    Составной можно, но не та задача, ИМХО.
  • Ega23 © (14.03.15 19:29) [3]
    where (eventEndDate >= UserStartDate) and (eventStartDate <= userEndDate)
  • ВладОшин © (14.03.15 21:21) [4]
    интересно.. именно индекс имхо никак

    проверять  на
    if exists( selct 1 where UserStartDate between eventStartDate and eventEndDate)
    set i := i +1
    if exists( selct 1 where UserEndtDate between eventStartDate and eventEndDate)
    set i := i +10

    интерпретировать
    select case
    when i = 0 then 'мимо'
    when i in  (1,10) then case
                                  when i = 1 then 'рана слева '
                                  when i = 10 then 'рана справа '
                                  утв
    when i =11 then 'убил'
  • ВладОшин © (14.03.15 21:21) [5]
    интересно.. именно индекс имхо никак

    проверять  на
    if exists( selct 1 where UserStartDate between eventStartDate and eventEndDate)
    set i := i +1
    if exists( selct 1 where UserEndtDate between eventStartDate and eventEndDate)
    set i := i +10

    интерпретировать
    select case
    when i = 0 then 'мимо'
    when i in  (1,10) then case
                                  when i = 1 then 'рана слева '
                                  when i = 10 then 'рана справа '
                                  утв
    when i =11 then 'убил'
  • TohaNik © (14.03.15 21:46) [6]

    > составной индекс по двум полям можно сделать

    или не правильно понял... или вообще не понял:(
    по трем полям?
  • Кщд © (14.03.15 22:33) [7]
    >TohaNik ©   (14.03.15 21:46) [6]
    по двум
    по этим: Ega23 ©   (14.03.15 19:29) [3]

    >ВладОшин ©   (14.03.15 21:21) [4]
    тяжёлая неделя выдалась?)
  • Ega23 © (15.03.15 10:33) [8]
    Тащемта Влад жжот например. Нопалмом.
  • ВладОшин © (15.03.15 11:49) [9]
    да..  каюсь, был не трезв :)
  • Дмитрий С © (16.03.15 12:55) [10]

    > Ega23 ©   (14.03.15 19:29) [3]
    > ?
    > 1
    > where (eventEndDate >= UserStartDate) and (eventStartDate
    > <= userEndDate)

    Спасибо за подсказку!

    Но даже в этом случае построить индекс не представляю как.
    Похоже придется использовать какие-то трюки.
  • Кщд © (16.03.15 12:59) [11]
    Дмитрий С ©   (16.03.15 12:55) [10]
    >Но даже в этом случае построить индекс не представляю как.
    вот так: eventStartDate, eventEndDate
  • Дмитрий С © (16.03.15 13:42) [12]

    > Кщд ©   (16.03.15 12:59) [11]

    В этом случае, чем дальшебудет eventStartDate от userEndDate, тем менее эффективным будет индекс. Если eventStartDate = userStartDate - вообще бесполезным.
  • Кщд © (16.03.15 14:07) [13]
    >Дмитрий С ©   (16.03.15 13:42) [12]
    оба утверждения не соответствуют действительности
  • Дмитрий С © (16.03.15 14:07) [14]

    > Кщд ©   (16.03.15 14:07) [13]

    Объясни.
  • Кщд © (16.03.15 16:05) [15]
    >Дмитрий С ©   (16.03.15 14:07) [14]

    - Рок-н-ролл мёртв из-за того, что Земля плоская в крапинку, т.к. хорёк
    - Это не так
    - Объясни?
    ))

    Не знаю, о каких "индексах" говорили Вы, а наиболее распространённый в БД индекс - B*-tree (индекс на основе сбалансированного B-дерева).
    Это ответ на все Ваши вопросы.
  • Дмитрий С © (16.03.15 16:42) [16]

    > Кщд ©   (16.03.15 16:05) [15]

    При eventStartDate = userStartDate по первому измерению индекса (eventStartDate) выберет все элементы, поэтому подобный индекс будет неэффективным.
  • Кщд © (16.03.15 17:07) [17]
    >Дмитрий С ©   (16.03.15 16:42) [16]
    индекс становится неэффективным, когда по нему выбирается свыше 25-33% (в разных источниках - по-разному) записей от общего числа
    если в Вашем случае (магия данных, ага) это так, то - неэффективен
    рассуждения о каких-либо измерениях в случае с бинарным деревом - фтопку

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

    ответ был дан ещё в "DVM ©   (14.03.15 17:32) [1]"
    если он Вас не устраивает, это Ваше личное дело
  • sniknik © (16.03.15 17:23) [18]
    http://developerguru.net/post/date_range_intersection_condition/

    какого то особого индекса не нужно, по времени начала и конца достаточно, условие отбора в ссылке (только not добавить, т.к. там на НЕ пересечение)
  • Дмитрий С © (16.03.15 17:56) [19]

    > sniknik ©   (16.03.15 17:23) [18]
    > http://developerguru.net/post/date_range_intersection_condition/
    >
    > какого то особого индекса не нужно, по времени начала и
    > конца достаточно, условие отбора в ссылке (только not добавить,
    >  т.к. там на НЕ пересечение)

    Так вот Ega23 это и предложил в [3].

    where (eventEndDate >= UserStartDate) and (eventStartDate <= userEndDate)

    Но как при этом работает индекс по двум полям (eventStartDate, eventEndDate)?
    Расскажу как понимаю я, поправьте если что. Прошу не цепляться к словам.

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

    Мы строим индекс по полям дат: (eventStartDate, eventEndDate).
    Заполняем равномерно данными данными с 2000 по 2015 год.

    А затем выбираем последние два месяца 2015 года:
    where (eventEndDate >= '2015-11-01') and (eventStartDate <= '2015-12-31')

    В этом случае СУБД начнет поиск по индексу следующим образом: Сначала выбирает по полю eventStartDate, затем из тех что выбралось выбирает по полю eventEndDate.
    Но! Но по условию eventStartDate <= '2015-12-31' будут выбраны все данные, а по второму полю индекса субд будет сделать N выборок (N=количество записей 1 измерения индекса).
  • sniknik © (16.03.15 20:38) [20]
    > В этом случае СУБД начнет поиск по индексу следующим образом:
    не думай за нее... просто посмотри план запроса. в последних версиях тебе еще и совет даст какой индекс выгоднее.
  • Ega23 © (16.03.15 22:54) [21]

    > Но как при этом работает индекс по двум полям (eventStartDate,
    >  eventEndDate)?


    А зачем тебе индекс по двум полям? Сделай два индекса, один по eventStartDate, другой по eventEndDate.
    Ну и планы запроса смотреть, как минимум есть от чего отталкиваться.
  • Ega23 © (16.03.15 22:55) [22]

    > Сначала строится индекс по первому полю, а затем, для каждой
    > записи индекса строится индекс по второму полю.


    Это зависит от конкретной СУБД и работы оптимизатора.
  • Кщд © (17.03.15 09:44) [23]
    >Ega23 ©   (16.03.15 22:54) [21]
    >Сделай два индекса, один по eventStartDate, другой по eventEndDate.
    если речь о index_join, то затея плохая, т.к. тогда ситуация будет ровно как в
    >Дмитрий С ©   (16.03.15 17:56) [19]

    т.е. будут извлечены два набора (по каждому индексу) и уже затем объединены
    "Но по условию eventStartDate <= '2015-12-31' будут выбраны все данные", т.е. индекс по eventStartDate - будет неэффективен

    >Дмитрий С ©   (16.03.15 17:56) [19]
    >Сначала строится индекс по первому полю, а затем, для каждой записи >индекса строится индекс по второму полю.
    нет
    никаких подиндексов
    ответьте себе на вопрос, в чём отличие двух наборов:
    order by field_
    и
    order by field_, field_2

    подскажу: ни в чём
    это просто определённым образом отсортированные наборы
    а по одному полю или десяти - не важно
  • Кщд © (17.03.15 09:49) [24]
    >sniknik ©   (16.03.15 17:23) [18]
    если применить "not" к выражению по ссылке и раскрыть скобки, то получится: Ega23 ©   (14.03.15 19:29) [3]
 
Конференция "Базы" » Индекс с интервалами дат
Есть новые Нет новых   [118240   +21][b:0][p:0.001]