#sql #postgresql #query-optimization
#sql #postgresql #оптимизация запроса
Вопрос:
У меня есть этот запрос, который, на мой взгляд, довольно медленный :
select * from "cams" where
"bust" is not null and
"figure" is not null and
"age" is not null and
"hair" is not null and
"ethnicity" is not null
and "status" = 'online' and
"cams"."deleted_at" is null
order by ethnicity = 'white' DESC,
age = 22 DESC,
(age >= 18 AND age <= 35) DESC,
bust = 'medium' DESC,
figure = 'petite' DESC,
hair = 'blonde' DESC
limit 10
Объяснение результатов анализа
Limit (cost=10045.82..10045.84 rows=10 width=318) (actual time=754.187..754.190 rows=10 loops=1)
-> Sort (cost=10045.82..10047.15 rows=532 width=318) (actual time=754.182..754.183 rows=10 loops=1)
Sort Key: ((ethnicity = 'white'::ethnicity)) DESC, ((age = 22)) DESC, (((age >= 18) AND (age <= 35))) DESC, ((bust = 'medium'::bust)) DESC, ((figure = 'petite'::figure)) DESC, ((hair = 'blonde'::hair_color)) DESC
Sort Method: top-N heapsort Memory: 33kB
-> Bitmap Heap Scan on cams (cost=1328.15..10034.32 rows=532 width=318) (actual time=580.008..745.590 rows=5092 loops=1)
Recheck Cond: ((hair IS NOT NULL) AND (age IS NOT NULL) AND (status = 'online'::cam_status))
Filter: ((bust IS NOT NULL) AND (figure IS NOT NULL) AND (ethnicity IS NOT NULL) AND (deleted_at IS NULL))
Rows Removed by Filter: 2414
Heap Blocks: exact=49643
-> Bitmap Index Scan on cams_online_rank_age (cost=0.00..1328.02 rows=2406 width=0) (actual time=567.587..567.587 rows=4715231 loops=1)
Index Cond: ((hair IS NOT NULL) AND (age IS NOT NULL))
Planning Time: 1.526 ms
Execution Time: 754.464 ms
Есть ли индекс, который я могу добавить, чтобы ускорить это (имея в виду, что значения для order by будут динамическими)? Я думал о частичном индексе, в котором бюст, фигура, возраст, этническая принадлежность волос не равны нулю, а статус = ‘онлайн’, но затем не уверен, по какому столбцу ранжировать, поскольку порядок по является динамическим (я пытаюсь найти элемент, похожий на post, для определенного элемента).
Ответ №1:
Ваша единственная надежда — это индекс на (status, deleted_at)
. Это, по крайней мере, соответствует условиям равенства в where
предложении. Если вы знаете, что другой столбец содержит большую долю null
значений, вы можете включить это в качестве третьего ключа.
Это может ограничить сканирование таблицы. Однако производительность может быть в большей степени основана на сортировке для order by
, чем на сканировании таблицы.