В таблице SQL person_rate мы сохранили значение с плавающей ставкой, которое изменяется во времени. Колонки:Скорость изменения хранилища SQL во времени и скорость SELECT, действительная для определенного момента времени
id (serial, PK)
person_id (int)
date_from (date)
rate (float)
(person_id, date_from)
уникален, потому что в большинстве одно изменение в день допускается (возможно, это может быть ПК, но это не важно)
Оценить значение для данного person_id действует на временном интервале от date_from
Дата следующей записи с успешным date_from
, или к будущему будущему, если такой записи нет. Пример:
id person_id date_from rate
101 1 2011-01-01 100.0
145 1 2012-01-01 180.0
193 1 2012-05-01 140.0
Теперь мне нужен запрос SELECT, который для каждого person_id
возвращающую rate
действителен в течение некоторого заданного момента $. Скажем, на 2012-03-01 это 180; на 2012-05-02 это 140 и так.
Solutions Я протестированные:
1) состояние date_from <= $date
+ использовать оконную функцию rank() OVER (PARTITION BY person_id ORDER BY date_from DESC
+ в superselect WHERE rank = 1
2) аналогично 1), но использовать SELECT DISTINCT ON (person_id)
вместо ограничения ранга 1
Оба 1) и 2) не работает хорошо, EXPLAIN показывает, что db должен сортировать все записи для каждого person_id
, а затем ограничивать 1 первым. Вероятно, этот тип запроса не может полностью использовать индекс на date_from
?
IDEA - добавить date_to
столбец, который будет немного излишним, так как значение будет «date_from из succesive записи, минус 1 день» (или + infty, если нет succesive записи). Но тогда запрос мог бы быть с date_from <= $date AND date_to >= $date
- который, вероятно, имел бы хорошую производительность с индексами на date_from и date_to.
Но я немного боюсь, как управлять целостностью данных в этом случае - как установить ограничение, которое [date_from .. date_to] интервалов для одного person_id shoud не перекрывается?
Какое оптимальное решение для postgresql для этого типа запросов? Загрузка наиболее читается, а не много пишет в таблицу person_rate. Типичный запрос был бы внутренне необходим для получения ставки за каждый день в месяце ...
Возможно, это SQL query for index/primary key ordinal с новыми индексами на стр. 9.2 может как-то помочь?
Спасибо для этого «медленно меняйте таблицы размеров», похоже, это то, что мне нужно, подобно ИДЕИ, которую я объяснил. Ограничение ненасыщения может быть реализовано с помощью триггера insert. – vlastik
триггеры плохой дизайн. вам нужно задать себе один важный вопрос - ваша система делает больше DML или выбирает? если ваша система делает больше DML, вы можете отказаться от 'to_date', потому что для каждого обновления/вставки потребуется два обновления (текущая строка и to_date предыдущего). если ваша система делает больше выбора - вы можете рассмотреть возможность уплаты штрафа во время вставки, чтобы облегчить выбор. я дам вам эмпирическое правило - * если у вас есть триггеры, синонимы или слишком много просмотров, вы делаете что-то неправильно *. – haki
По сравнению с выборами обновление/вставка почти не будет. Таким образом, два обновления, безусловно, в порядке. Я думаю о триггерах, вероятно, только для проверки ограничений последовательности, например. не допускать вставки [от, до] интервала, который перекрывает другой. – vlastik