(where deleted_at IS NULL)
- products_created_by_id_idx
- index_products_on_title
есть достаточно простая кверя:
SELECT "products".* FROM "products" INNER JOIN "users" ON "products"."created_by_id" = "users"."id" WHERE "users"."company_id" = 1422 AND "products"."deleted_at" IS NULL ORDER BY "products"."title" ASC LIMIT 10 OFFSET 0
На массиве данных отрабатывает чудовищно долго, 2 минуты. Explain этого запроса: https://explain.dalibo.com/plan/qU . Судя по тому что я тут вижу, для выборки по created_by_id почему-то (очевидно из-за сортировки, но все же) используезтся индекс on_title вместо любого из created_by_id_*.
Есть другая кверя, где к INNER JOIN я добавил подзрапрос по created_by_id на уровне таблицы products:
SELECT "products".* FROM "products" INNER JOIN "users" ON "products"."created_by_id" = "users"."id" WHERE "users"."company_id" = 1422 AND "products"."deleted_at" IS NULL AND "products"."created_by_id" IN (SELECT "users"."id" FROM "users" WHERE "users"."company_id" = 1422) ORDER BY "products"."title" ASC LIMIT 10
Работает быстро: https://explain.dalibo.com/plan/E80 , используется индекс по products_created_by_id_updated_at__partial_idx
Но тут INNER JOIN по большому счету ведь не нужен, можно оставить только subquery, подумал я:
SELECT "products".* FROM "products" WHERE "products"."deleted_at" IS NULL AND "products"."created_by_id" IN (SELECT "users"."id" FROM "users" WHERE "users"."company_id" = 1422) ORDER BY "products"."title" ASC LIMIT 10
Но не тут то было, explain точно такой же как в первом варианте - https://explain.dalibo.com/plan/OxV , нужный индекс не используется.
Очевидным и напрашивающимся решением было бы добавить индекс по created_by_id + title (тем более что created_by_id тут выступает в роли TenantID), что я и сделал:
CREATE INDEX CONCURRENTLY products_created_by_id_title_idx ON products (created_by_id, title) WHERE (deleted_at IS NULL)
Но это не помогло, постгря его игнорирует. Так же игнорирует и обратный индекс (on title, on created_by_id)
Я не понимаю почему JOIN + Subquery вместе делают кверю быстрой, а по отдельности нет. И как бы обойтись только чем-то одним. Есть идеи? За любую подсказку в каком направлении копать буду признателен.
Есть вот такая идея — все эти планы бесполезны для анализа. ;) Выложите лучше EXPLAIN (ANALYZE, BUFFERS) на https://explain.depesz.com/ Ах да, и определения индексов мы должны угадать из их названий? Покажите лучше \d products и \d users.
Обсуждают сегодня