Как стать автором
Обновить

Комментарии 11

А почему в плане нет сортировки? Или план на скриншоте не относится к приведённому
Вопрос снимается, разглядел название. Вообще, конечно, тяжело читать статью про оптимизацию запросов без ddl таблиц и индексов.
И какой в итоге получился план?

тяжело читать статью про оптимизацию запросов без ddl таблиц и индексов
Благодарю за обратную связь. Пожалуй, стоило добавить схему упомянутых таблиц.

Итоговый план получился не самым идеальным, но вполне подходящим для «бюджета мощности».

Спасибо. Не очень силён в чтении планов Postgre — правильно ли я понял, что в индексе по arena_participations первым идёт поле arena_profile_id?

Кстати, забавно. На плане в посте на скриншоте у вас условие по bet <= 96.5, а индекс по created_at отфильтрован по bet<= 98.3, т.е. с таким условием СУБД приходилось сканировать весь индекс, чтобы выдрать оттуда подходящие по условию записи. И большая часть времени тратится как раз на него, а не на NOT EXISTS, который пролетает достаточно быстро не смотря на не самый подходящий индекс.
А в итоговом плане, из комментария, у вас используется новый индекс index_arena_battles_on_bet_partial_status, про который в посте ни слова.

Многовато умолчаний о том, что было сделано, для статьи об оптимизации запроса.

Играй в детектива, возможно тебе даже выдадут значок.

Можно мне значок?
Можно мне значок?

охренеть я детектив, сорян :(
писать пьяный больше не буду

Перечитайте публикацию на свежую голову. Буду рад подискутировать.

Да, ещё раз извините за выступление).
SELECT "arena_battles".* 
FROM "arena_battles" 
WHERE "arena_battles"."status" = 'waiting_for_players' 
   AND (arena_battles.bet <= 98.13) 
   AND (NOT EXISTS (
            SELECT 1 FROM arena_participations
            WHERE arena_battle_id = arena_battles.id
              AND (arena_profile_id = 46809)
          )) 
ORDER BY "arena_battles"."created_at" ASC 
LIMIT 10 OFFSET 0

Предполагаю, что индекс по created_at, bet where «status» = 'waiting_for_players' в «arena_battles» и индекс по arena_battle_id, arena_profile_id в arena_participations должны будут сделать с exists быстрее, чем итоговый с left join, в крайнем случае, не медленнее. Искать несуществующее по подходящему индексу — это, наверное, самое быстрое, что может сделать оптимизатор.
Когда я обсуждал решение с left join в этом кейсе с коллегами, в дискуссии звучали предположения что джоины будут могут работать медленно. На практике у меня не вышло подтвердить или опровергнуть это. Цель была не максимально ускорить, а уложиться в «бюджет мощности» сервера БД.

Спасибо за предположение. Стало интересно это проверить.
У вас фильтрация по частичному индексу идет по bet (полю индекса), но оно не используется именно как индексное (нет Index Cond) — вычитываются все 73 строки из этого индекса.
При этом сортировка потом идет по created_at, и остается всего 10 записей из 73. Попробуйте сделать частичный индекс с тем же условием, но по created_at — должно получиться еще быстрее.
Выглядит логично. Спасибо. Проверю эту гипотезу как будет время.

Полагаю, вы описали внутренний глубинный мотив многих разработчиков, выбравших Ruby и Ruby On Rails. По крайней мере, мой мотив точно.
Покрасоваться.
По моему скромному мнению, язык, фреймворк и большая часть всей экосистемы ruby, сложились вокруг этой потребности.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации