В нашей базе данных имеется множество таблиц с данными, актуальными только в течение определенного периода времени. Например, контракты, у них есть start_date и end_date. И это не обязательно полные месяцы.как смоделировать данные/индексы для быстрого поиска временных рядов
Сейчас это типичный тип запроса к таблице:
SELECT
*
FROM
contracts c
WHERE
c.start_date <= :1
AND c.end_date >= :2
AND c.region_id = :3
Поскольку мы имеем 20 лет данных в нашей таблице (~ 7000 дней), дата очень хорошие критерии фильтрации, особенно в следующих случаях: 1 и: 2 - в тот же день. Region_id не является таким хорошим критерием фильтрации, потому что их не так много (~ 50). В этом примере мы имеем (в том числе) 2 Индексы на нашем столе:
contracts_valid_index (start_date, end_date)
contracts_region (region_id)
К сожалению, выше запрос будет часто нас индекс contracts_region, потому что оптимизатор считает, что это дешевле. Причина этого проста: когда я выбираю день в середине наших данных, тогда база данных будет думать, что индекс над start_date не будет действительно хорошим, потому что он будет отфильтровывать только половину данных. И, посмотрев на end_date, это тоже самое. Поэтому оптимизатор считает, что он может отфильтровать только 1/4 моих данных. Поскольку он не знает, что start_date и end_date обычно довольно близко друг к другу, и этот индекс будет очень избирательным.
План выполнения с использованием contract_valid_index имеет более высокие затраты, чем план выполнения с использованием contract_region. Но в действительности contract_valid_index намного лучше.
В настоящее время я не думаю, что я могу ускорить свои запросы, создав лучшие индексы (кроме удаления всех, кроме contract_valid_index). Но, может быть, моя модель данных не очень хороша для оптимизатора запросов. Поэтому я предполагаю, что другие также имеют схожие потребности и хотели бы знать, как они моделировали свои данные или оптимизировали свои таблицы/индексы данных.
Любые предложения?
Это то, что я искал. Мне не нравится открытый конец интервала, но это не должно быть проблемой. Но я сомневаюсь, что я получу поддержку JPA для этого – EasterBunnyBugSmasher
. Я сделал небольшое дополнительное исследование после публикации этого сообщения, столбцы начала и конца даты могут быть либо датами, либо отметками времени, а нулевые значения рассматриваются как начало и конец времени, хотя если вы используете магические даты для этих значений, они будут продолжать работать. – Sentinel
Что касается открытых и закрытых диапазонов, я работал с ними и предпочитаю открытые. Таким образом, когда один диапазон заканчивается, а затем начинается, вы можете использовать ту же дату для конца, как и для следующего запуска, и не беспокоиться о перекрытии. И если вы используете усеченные значения для ваших дат начала и окончания, вам не нужно беспокоиться о том, что необработанная проверка диапазона падает в промежутке между одним диапазоном и началом следующего. – Sentinel