0

У меня есть таблица с ~ 30M кортежами. Таблица выглядит так:Медленный запрос на большой таблице при использовании порядка

id | first_name | last_name | email 
----------------------------------------- 
1 | foo  | bar  | [email protected] 

Также есть индекс (индекс btree) для first_name и прочее для last_name.

Запрос ниже Наталья принимает около 200 мс для возврата результатов:

SELECT 
    * 
FROM my_table 
WHERE (first_name ILIKE 'a%') 
LIMIT 10 OFFSET 0 

Но следующий Наталья принимает около 15 секунд (добавление заказа по)

SELECT 
    * 
FROM my_table 
WHERE (first_name ILIKE 'a%') 
ORDER BY last_name asc, first_name asc 
LIMIT 10 OFFSET 0 

Что я могу сделать, чтобы улучшить производительность последнего запроса?

+2

Индекс last_name, first_name. – jarlh

+0

@jarlh Я попробую, спасибо – Victor

+0

@jarlh написать ответ, чтобы принять этот –

ответ

2

У вас есть два варианта индексов для этого запроса:

SELECT t.* 
FROM my_table 
WHERE first_name ILIKE 'a%' 
ORDER BY last_name asc, first_name asc 
LIMIT 10 OFFSET 0 ; 

Один за пунктом WHERE. Лучший индекс для этого - my_table(first_name). Вторая возможность - использовать индекс для ORDER BY, my_table(last_name, first_name).

Это лучше зависит от данных, которые у вас есть. Возможно, вы захотите попробовать, чтобы увидеть, какая из них работает лучше, если общая производительность является целью.

Наконец, вычисленный индекс может быть лучшим способом. В вашем случае, написать запрос, как:

SELECT t.* 
FROM my_table 
WHERE lower(substr(first_name, 1, 1)) = 'a' 
ORDER BY last_name asc, first_name asc 
LIMIT 10 OFFSET 0 ; 

Затем индекс вы хотите mytable(lower(substr(first_name, 1, 1)), last_name, first_name). Этот индекс может использоваться как для WHERE, так и для ORDER BY, что должно быть оптимальным для этого запроса.

1

Я предполагаю, что следующий индекс ускорит ORDER BY:

create index my_table_lname_fname on my_table (last_name, first_name) 
0

CREATE INDEX my_table_idx1 ON my_table (last_name ASC NULLS LAST, first_name ASC NULLS LAST);

Некоторые ноты в произвольном порядке:

  • АГО NULLS ПОСЛЕДНИЙ по умолчанию, но я думал, Я бы проиллюстрировал это на случай, если вы захотите сыграть в порядке.
    • Это одно из тех редких случаев, когда вам поможет индекс нескольких столбцов. Как правило, вам рекомендуется создавать многочисленные индексы с одним столбцом и разрешать оптимизатору запросов роскошь выбирать индексы для использования, а не заставлять его принимать решения.
    • Я заметил там ILIKE, который не работает и может быть вашей реальной проблемой , если только вы используете пакет pg_trgm вместе с индексом GIST.
Смежные вопросы