Используя PostgreSQL 9.2, у меня проблемы с медленными запросами к относительно большой таблице (более 200 миллионов строк). Я не делаю ничего сумасшедшего, просто добавляю исторические ценности. Ниже приведен запрос и вывод плана запроса.
Моя таблица раскладок:
Table "public.energy_energyentry"
Column | Type | Modifiers
-----------+--------------------------+-----------------------------------------------------------------
id | integer | not null default nextval('energy_energyentry_id_seq'::regclass)
prop_id | integer | not null
timestamp | timestamp with time zone | not null
value | double precision | not null
Indexes:
"energy_energyentry_pkey" PRIMARY KEY, btree (id)
"energy_energyentry_prop_id" btree (prop_id)
"energy_energyentry_prop_id_timestamp_idx" btree (prop_id, "timestamp")
Foreign-key constraints:
"energy_energyentry_prop_id_fkey" FOREIGN KEY (prop_id) REFERENCES gateway_peripheralproperty(id) DEFERRABLE INITIALLY DEFERRED
Данные варьируются с 2012-01-01 по настоящее время, постоянно добавляются новые данные. Во внешнем ключе около 2,2 тыс. Различных значений prop_id
, распределенных равномерно.
Я заметил, что оценки строк не за горами, но оценки затрат кажутся в 4 раза больше. Вероятно, это не проблема, но могу ли я что-нибудь с этим сделать?
Я ожидаю, что доступ к диску может быть проблемой, так как таблица не находится в памяти все время.
EXPLAIN ANALYZE
SELECT SUM("value")
FROM "energy_energyentry"
WHERE
"prop_id"=82411
AND "timestamp">'2014-06-11'
AND "timestamp"<'2014-11-11'
;
Aggregate (cost=214481.45..214481.46 rows=1 width=8) (actual time=51504.814..51504.814 rows=1 loops=1) -> Index Scan using energy_energyentry_prop_id_timestamp_idx on energy_energyentry (cost=0.00..214434.08 rows=18947 width=8) (actual time=136.030..51488.321 rows=13578 loops=1) Index Cond: ((prop_id = 82411) AND ("timestamp" > '2014-06-11 00:00:00+00'::timestamp with time zone) AND ("timestamp" < '2014-11-11 00:00:00+00'::timestamp with time zone)) Total runtime: 51504.841 ms
Любые предложения, как сделать это быстрее?
Я тоже в порядке, просто услышав, что я не сделал ничего странного.
prop_time_idx
, а определение таблицы показываетentry_prop_id_timestamp_idx
. Это тот же индекс? Пожалуйста исправьте.prop
)? Если бы только небольшой процент, возможно, индекс("timestamp", prop)
был бы лучше. Несколько индексов с одинаковыми ведущими столбцами (prop
в вашем случае) также часто являются избыточными.Ответы:
Ваша таблица большая , как и любой индекс, охватывающий всю таблицу. При условии, что:
timestamp = now()
вводятся только новые данные (с )Я бы предложил частичный, многостолбцовый (охватывающий!) Индекс :
Включайте только диапазон времени, который запрашивается регулярно. Эффективность ухудшается со временем с новыми записями. Время от времени воссоздайте индекс. (Возможно, вам придется адаптировать ваши запросы.) См. Связанный ответ ниже.
Значение последнего столбца включено только для получения результатов сканирования только по индексу . Агрессивная настройка автоочистки может помочь, поддерживая карту видимости в актуальном состоянии, как уже упоминалось @jjanes .
Частичный индекс должен легче помещаться в ОЗУ и оставаться там дольше.
Возможно, вам придется включить это
WHERE
условие в запросы, чтобы планировщик понял, что индекс применим к запросу, например:Поскольку ваш запрос суммирует много строк (
rows=13578
), это займет некоторое время, даже при сканировании только по индексу. Это не должно быть где-то около 50 секунд, хотя. Меньше секунды на любом наполовину приличном оборудовании.Связанные (но игнорируйте
CLUSTER
иFILLFACTOR
, и то , и другое не имеет значения, если вы можете получить из этого сканирование только по индексу) :Помимо:
Так как вы в настоящее время имеют индекс
(prop_id, "timestamp")
, дополнительный индекс только(prop_id)
может стоить больше , чем это стоит:источник
Если вы создадите индекс для (prop_id, "timestamp", "value"), то он может использовать сканирование только по индексу для вычисления значения, даже не посещая таблицу. Это может сэкономить много случайного доступа к диску.
Чтобы получить максимальную выгоду, вы должны быть настойчивы в уборке стола. Настройки автозапуска по умолчанию недостаточно агрессивны для таблиц только для вставки, в которых вы хотите эффективно поддерживать сканирование только по индексу.
источник