Таблицы календаря реализуют компромисс между пространством и временем.Используя больше места, некоторые виды запросов выполняются за меньшее время, потому что они могут использовать преимущества индексов.Они безопасны, если вы осторожны с ограничениями CHECK () и если у вас есть административные процессы, чтобы позаботиться о любых ограничениях, которые не поддерживает ваша dbms.
Если ваша гранулярность равнаодну минуту, вам нужно будет генерировать около полумиллиона строк для каждого года.Минимальная таблица календаря будет выглядеть следующим образом.
2011-01-01 00:00:00
2011-01-01 00:01:00
2011-01-01 00:02:00
2011-01-01 00:03:00
2011-01-01 00:04:00
Если вы выполняете анализ "корзины", вам может быть лучше что-то вроде этого.
bucket_start bucket_end
--
2011-01-01 00:00:00 2011-01-01 00:01:00
2011-01-01 00:01:00 2011-01-01 00:02:00
2011-01-01 00:02:00 2011-01-01 00:03:00
2011-01-01 00:03:00 2011-01-01 00:04:00
2011-01-01 00:04:00 2011-01-01 00:05:00
Так как SQL BETWEENОператор включает в себя конечные точки, вам обычно нужно избегать его использования.Это потому, что он включает в себя конечные точки, и трудно выразить bucket_end как «bucket_start плюс одну минуту, минус наименьшее количество времени, которое этот сервер может распознать».(Опасность - это значение, которое на микросекунду больше, чем bucket_end, но все же меньше, чем следующее значение для bucket_start.)
Если бы я собирался построить эту таблицу, я, вероятно, сделал бы это так.(Хотя я бы подумал, стоит ли мне называть это «календарем».)
create table calendar (
bucket_start timestamp primary key,
bucket_end timestamp unique,
CHECK (bucket_end = bucket_start + interval '1' minute)
-- You also want a "no gaps" constraint, but I don't think you
-- can do that in a CHECK constraint in PostgreSQL. You might
-- be able to use a trigger that counts the rows, and compares
-- that count to the number of minutes between min(bucket_start)
-- and max(bucket_start). Worst case, you can always run a report
-- that counts the rows and sends you an email.
);
Ограничение UNIQUE создает неявный индекс в PostgreSQL.
Этот запрос будет вставлять строки за один день (24 часа * 60 минут) за один раз.
insert into calendar
select coalesce(
(select max(bucket_start) from calendar),
cast('2011-01-01 00:00:00' as timestamp)
)
+ cast((n || 'minute') as interval) as bucket_start,
coalesce(
(select max(bucket_start) from calendar),
cast('2011-01-01 00:00:00' as timestamp)
)
+ cast((n + 1 || ' minute') as interval) as bucket_end
from generate_series(1, (24*60) ) n;
Вы можете заключить это в функцию, чтобы генерировать год за один раз.Вероятно, я бы попытался зафиксировать менее полумиллиона строк за один раз.
Для создания 20 миллионов строк для тестирования не потребуется слишком много времени и еще 20 миллионов строк "календарных" минут.Длинный обедМожет быть, полдень на солнце.