singalen: (Johnny)
singalen ([personal profile] singalen) wrote2009-08-19 01:57 pm
Entry tags:

Любителям SQL - классическая задача на исторические данные

Нужно выбрать последний, скажем, курс валюты, за каждый час.
Я делаю так:
select *
from currency_course c
where
  c.id in
  (select max(grouped.id) from currency_course grouped where
     grouped.timestamp between :from and :to
     group by year(grouped.timestamp), month(grouped.timestamp), day(grouped.timestamp), hour(grouped.timestamp)
  )

Заодно исполняется и на HQL.

Исполняется, инфекция, разумеется, фулсканом. На MySQL несчастные полторы тыщи записей по этим формулам группируются минуту. На hsql - пять минут.

1. К сожалению, индекс по функции от поля строитс не в каждой СУБД. Не получится написать
create index blabla on currency_course(
year(grouped.timestamp), month(grouped.timestamp), day(grouped.timestamp), hour(grouped.timestamp) )
. А очень жаль.

2. Можно или вынести в отдельную таблицу "дайджест" - уже подготовленные последние записи.

3. Или выставить в таблице currency_course поля-флажки "последний за час/день/неделю", проиндексировать их и выгребать по ним.
Пока собираюсь так.

Кстати, инфекция, в HQL нет функции week(). И произвольного выкусывания части даты тоже нет 8(

[identity profile] rioman.livejournal.com 2009-08-19 11:28 am (UTC)(link)
Валюта одна и id монотонный?

[identity profile] rioman.livejournal.com 2009-08-19 11:33 am (UTC)(link)
Угу.

Я б наверно дайджест делал. Только не целыми строками, а только id-шники. Триггер в любом случае надо вешать и работать он будет примерно одинаково, а выборка быстрее.

Или выбирать надо представителей не только за час, а и за все другие перечисленные интервалы?

[identity profile] rioman.livejournal.com 2009-08-19 11:38 am (UTC)(link)
> Триггеру отказать
Ну, это уже детали.

> решается разными дайджестами.
Ну да. По сути то же, что и разные индексы. Только в п.2 все данные наружу, а в п.3 спрятаны в системе.

[identity profile] rioman.livejournal.com 2009-08-19 11:37 am (UTC)(link)
А, блин. Я идиот. Неправильно прочитал п. 3.
По сути одно и то же, но в таком виде, как в п.3 получается более универсально.

[identity profile] bogdanv.livejournal.com 2009-08-19 11:51 am (UTC)(link)
если нельзя функциональный индекс, то почему не писать в отдельные поля год, месяц, день?

[identity profile] rioman.livejournal.com 2009-08-19 12:02 pm (UTC)(link)
Можно, но с привлечением таких же дополнительных ресурсов можно решить задачу более эффективно.