クエリが複雑で、複数の内部結合とサブ選択があります。それはものすごく実行されます。ここではJOINとサブSELECTのクエリパフォーマンスを改善しました
EXPLAIN ANALYZE SELECT
SUM(weekly_baskets.servings/2) AS sum_weekly_baskets_servings_2,
meal_selections.meal_id AS meal_selections_meal_id
FROM
"meal_selections"
INNER JOIN
"weekly_baskets" "weekly_baskets_meal_selections"
ON "weekly_baskets_meal_selections"."id" = "meal_selections"."weekly_basket_id"
INNER JOIN
"weekly_baskets"
ON "meal_selections"."weekly_basket_id" = "weekly_baskets"."id"
WHERE
"weekly_baskets"."menu_id" = 344
AND (
NOT (EXISTS (SELECT
1
FROM
"cancellations"
WHERE
("cancellations"."cancellable_id" = "weekly_baskets"."id")
AND ("cancellations"."cancellable_type" = 'WeeklyBasket')
AND "cancellations"."active" = 't'))
)
GROUP BY
meal_selections.meal_id
は、クエリプランです:
HashAggregate (cost=122273.42..122275.79 rows=787 width=8) (actual time=32313.598..32313.602 rows=13 loops=1)
Group Key: meal_selections.meal_id
-> Nested Loop (cost=26501.36..122208.17 rows=43504 width=8) (actual time=97.199..32292.526 rows=48594 loops=1)
-> Nested Loop (cost=26501.28..119314.73 rows=19567 width=12) (actual time=97.175..20446.310 rows=16067 loops=1)
-> Nested Loop Anti Join (cost=26501.19..87846.01 rows=19567 width=8) (actual time=97.146..20274.526 rows=16067 loops=1)
-> Bitmap Heap Scan on weekly_baskets (cost=26501.11..62382.74 rows=33112 width=8) (actual time=97.049..15395.178 rows=34502 loops=1)
Recheck Cond: (menu_id = 344)
Heap Blocks: exact=12414
-> Bitmap Index Scan on index_weekly_baskets_on_user_id_and_menu_id (cost=0.00..26499.45 rows=33112 width=0) (actual time=94.135..94.135 rows=34514 loops=1)
Index Cond: (menu_id = 344)
-> Index Only Scan using uidx_cancellations_for_active on cancellations (cost=0.08..0.77 rows=1 width=4) (actual time=0.141..0.141 rows=1 loops=34502)
Index Cond: ((cancellable_id = weekly_baskets.id) AND (cancellable_type = 'WeeklyBasket'::text) AND (active = true))
Heap Fetches: 12907
-> Index Only Scan using weekly_baskets_pkey on weekly_baskets weekly_baskets_meal_selections (cost=0.09..1.61 rows=1 width=4) (actual time=0.004..0.010 rows=1 loops=16067)
Index Cond: (id = weekly_baskets.id)
Heap Fetches: 16595
-> Index Only Scan using index_meal_selections_on_weekly_basket_id_and_meal_id on meal_selections (cost=0.09..0.14 rows=4 width=8) (actual time=0.508..0.737 rows=3 loops=16067)
Index Cond: (weekly_basket_id = weekly_baskets_meal_selections.id)
Heap Fetches: 47391
Planning time: 1.568 ms
Execution time: 32313.715 ms
は明らかにこれは非常に痛いです。私はこのクエリを最適化するために潜在的にLATERAL
ジョインを使用するのは難しいですが、その周りに私の頭を包み込むことができませんでした。
最後にテーブルを真空引きしたか、真空引きしたのはいつですか?スロー・アイ・ネストされたループがいくつかありますが、大きな時間を取るのはインデックスのみのスキャン( 'meal_selections'と' cancellations')であり、インデックス・ヒープは 'weekly_baskets'にフェッチします。これらのテーブルには注意が必要な場合や、非常に大きい場合があります。 – jmelesky
最後のvacuum'd約6日前に、完全なマニュアルの真空だった。死んだ行数はかなり少ないです。あなたが正しいです、 'meal_selections'は〜5mの行を持ち、' cancellations'は〜1.1mの行を持っています。 –
あなたの参加 "weekly_baskets" "weekly_baskets_meal_selections"はどこにも使われていないようです。削除する必要があります。可能であればクエリを誤読している場合を除き、 –