Типы данных, размер и производительность
Прежде всего, тип символ (n) почти всегда является плохим выбором. Если у вас нет веских причин и вы знаете, что делаете, используйте вместо этого тип text
. Если , вам действительно нужно установить максимальную длину, используйте CONSTRAINT. Пример для столбца ticker
:
ALTER TABLE onemin_interval
ADD CONSTRAINT onemin_interval_ticker_len CHECK (length(ticker) < 11);
Очевидно, у вас есть такие значения, как 'QQQ', поэтому длина 10 кажется произвольной. Это уменьшит размер таблицы (возможно, значительно) и ускорит .. все.
Также рассмотрите возможность использования bigint
вместо numeric(13,0)
. Вы не храните дробные цифры в любом случае, это, вероятно, лучший дизайн. numeric(13,0)
требуется 13 байтов (5 + 4x2), bigint требуется 8 байтов и операции с ним выполняются быстрее во всех отношениях.
И наконец: могут ли столбцы bigint
быть простыми integer
тоже? (Если диапазон от -2147483648 до +2147483647 достаточно велик в течение срока службы таблицы.)
Основная проблема
Почему индекс idx_onemin_ticker_intervalend
не используется?
Я бы попробовал несколько вещей:
Явное приведение
Если вы не можете изменить тип данных на text
, протестируйте запрос с явным приведением к character(10)
:
WHERE ticker = 'QQQ'::character(10)
Старые версии PostgreSQL могут не использовать индекс для character(10)
для незаполненной строки из трех символов ('QQQ'
). Однако индекс равен , который использовался в PostgreSQL 8.4 и 9.1 в моих тестах.
Порядок столбцов в multi-colukmn index
Попробуйте изменить порядок столбцов в индексе нескольких столбцов.
idx_onemin_ticker_intervalend btree (interval_end DESC, ticker)
Порядок столбцов в многостолбцовом индексе соответствует . Хотя, в вашем случае, если бы все было в порядке, это должно быть неактуально , поскольку вы включаете условия в оба столбца. Я все еще проверю это.
Планировщик статистики
Планировщик запросов, по-видимому, ожидает, что условия ticker = 'QQQ' AND interval_end <= 1326810600000
будут не очень избирательными - хотя на самом деле они кажутся очень избирательными (результат 4 строки). Попробуйте поднять default_statistics_target для двух столбцов следующим образом:
ALTER TABLE onemin_ticker ALTER COLUMN interval_end SET STATISTICS 1000;
ALTER TABLE onemin_ticker ALTER COLUMN ticker SET STATISTICS 1000;
ANALYZE onemin_ticker;
Или даже больше, до 10000 (у вас есть 420k строк). По умолчанию установлено значение 100. Обычно это помогает только при неравномерном распределении данных, но при использовании огромных таблиц это должно легко окупаться.
Общая оптимизация производительности
Общие рекомендации по оптимизации производительности в PostgreSQL Wiki всегда применимы.
Наконец, имейте в виду, что этот тип запроса никогда не будет быстро светиться . Сортировка строк по 70 КБ занимает время - и движок должен отсортировать все строки 70 К, прежде чем можно будет применить LIMIT 19960
.
Как видно из вашего обновления, планировщик запросов использует индекс test11 (interval_start DESC)
, который указывает, что сортировка является самой дорогой операцией в вашем запросе.
Поскольку вы выбираете по нескольким критериям перед сортировкой, я не вижу способа, как индекс может помочь вам в этом. Ваши данные не могут быть предварительно отсортированы и предварительно выбраны - за исключением , если предложение WHERE
стабильно, то вы можете создать частичный индекс, такой как:
CREATE INDEX onemin_interval_interval_start_part_idx
ON onemin_interval (interval_start DESC)
WHERE ticker = 'QQQ'::character(10)
AND interval_end <= 1326810600000
... что приводит к осветлению жира. Но я не думаю, что тебе так повезло?
Уже очень помогло бы, если бы один из критериев был стабильным, поэтому вы можете иметь частичный индекс по этому.