Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Составление SQL-запросов > Как заставить Postgres использовать определенный и


Автор: polin11 6.6.2018, 16:28
Есть запрос, использую СУБД Postgres 
Код

SELECT DISTINCT
"Field1"
FROM
"Table"
WHERE "Field2" LIKE 'val1%' AND "Field3" ='val2' 
LIMIT 100


В базе есть индекс по полю Field1 и составной индекс по 2 полям
(Field2 и Field3).
Если в запросе указать ограничение LIMIT, то используется индекс
по полю Field1 и потребляется много ресурсов.
Если в запросе убрать ограничение LIMIT, то используется составной
индекс (Field2 и Field3) ресурсов тратиться в 2 раза меньше, но
время выполнения запроса в несколько раз больше.
Вопрос можно ли в запросе оставить LIMIT 100 и 
обязать Postgres использовать составной индекс?

Автор: Akina 6.6.2018, 16:36
Увы, в постгрессе нет такой штуки как index hints. Как нет и INCLUDE.

Автор: Snowy 6.6.2018, 17:25
Код

ORDER BY "Field2", "Field3"
LIMIT 100;

Автор: polin11 6.6.2018, 17:38
Если добавить 
Код

ORDER BY "Field2", "Field3"
LIMIT 100;

то нужно менять запрос на  
Код

SELECT DISTINCT
"Field1",  "Field2", "Field3" 
FROM
"Table"
WHERE "Field2" LIKE 'val1%' AND "Field3" ='val2' 
ORDER BY "Field2", "Field3"
LIMIT 100


то используется составной индекс (Field2 и Field3), но время выполнения также увеличивается в несколько раз,
даже просто 
Например, если изменить запрос на 
Код

SELECT DISTINCT
"Field1",  "Field2"
FROM
"Table"
WHERE "Field2" LIKE 'val1%' AND "Field3" ='val2' 
LIMIT 100


то используется составной индекс (Field2 и Field3), но время выполнения также увеличивается в несколько раз

Автор: Snowy 7.6.2018, 01:46
1. Не используй limit без order by
2. Не пользуйся distinct, если в выборке больше 1000+ записей. Это очень медленная операция. Замени на group by, вложенный селект с limit 1, агрегатные функции, рекурсивные запросы, оконные функции. Что угодно, но не distinct. Особенно, если у тебя текстовые данные. distinct применим только на малых выборках. На больших вызывает бешенный сиквенсскан по всему результату. И вообще лучше никогда не использовать distinct, distinct on и IN.
3. А тебе действительно нужен составной индекс? У Field3 так много вариаций? Если вариантов не больше 10, то может обойтись просто индексом по Field2?
4. Увеличь shared_buffers и work_mem в настройках postgres.conf - на дефолтных значениях далеко не уедешь. Особенно с дистинктом или вложенными запросами. Больше памяти позволит уменьшить фрагментарность запросов и ускорит большие выборки в разы.

Как вариант:
Код
SELECT "Field1",  "Field2", "Field3" 
FROM "Table"
WHERE "Field2" LIKE 'val1%' AND "Field3" = 'val2' 
GROUP BY "Field2", "Field3", "Field1"
ORDER BY "Field2", "Field3"
LIMIT 100;

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)