此查询会获取您关注的人创建的帖子列表.您可以关注无限数量的人,但大多数人关注<另外1000人 使用这种查询方式,明显的优化是缓存“Post”ID,但遗憾的是我现在没有时间.
EXPLAIN ANALYZE SELECT "Post"."id","Post"."actionId","Post"."commentCount",... FROM "Posts" AS "Post" INNER JOIN "Users" AS "user" ON "Post"."userId" = "user"."id" LEFT OUTER JOIN "ActivityLogs" AS "activityLog" ON "Post"."activityLogId" = "activityLog"."id" LEFT OUTER JOIN "WeightLogs" AS "weightLog" ON "Post"."weightLogId" = "weightLog"."id" LEFT OUTER JOIN "Workouts" AS "workout" ON "Post"."workoutId" = "workout"."id" LEFT OUTER JOIN "WorkoutLogs" AS "workoutLog" ON "Post"."workoutLogId" = "workoutLog"."id" LEFT OUTER JOIN "Workouts" AS "workoutLog.workout" ON "workoutLog"."workoutId" = "workoutLog.workout"."id" WHERE "Post"."userId" IN ( 201486,1825186,998608,340844,271909,308218,341986,216893,1917226,... -- many more ) AND "Post"."private" IS NULL ORDER BY "Post"."createdAt" DESC LIMIT 10;
产量:
Limit (cost=3.01..4555.20 rows=10 width=2601) (actual time=7923.011..7973.138 rows=10 loops=1) -> Nested Loop Left Join (cost=3.01..9019264.02 rows=19813 width=2601) (actual time=7923.010..7973.133 rows=10 loops=1) -> Nested Loop Left Join (cost=2.58..8935617.96 rows=19813 width=2376) (actual time=7922.995..7973.063 rows=10 loops=1) -> Nested Loop Left Join (cost=2.15..8821537.89 rows=19813 width=2315) (actual time=7922.984..7961.868 rows=10 loops=1) -> Nested Loop Left Join (cost=1.71..8700662.11 rows=19813 width=2090) (actual time=7922.981..7961.846 rows=10 loops=1) -> Nested Loop Left Join (cost=1.29..8610743.68 rows=19813 width=2021) (actual time=7922.977..7961.816 rows=10 loops=1) -> Nested Loop (cost=0.86..8498351.81 rows=19813 width=1964) (actual time=7922.972..7960.723 rows=10 loops=1) -> Index Scan using posts_createdat_public_index on "Posts" "Post" (cost=0.43..8366309.39 rows=20327 width=261) (actual time=7922.869..7960.509 rows=10 loops=1) Filter: ("userId" = ANY ('{201486,... many more ...}'::integer[])) Rows Removed by Filter: 218360 -> Index Scan using "Users_pkey" on "Users" "user" (cost=0.43..6.49 rows=1 width=1703) (actual time=0.005..0.006 rows=1 loops=10) Index Cond: (id = "Post"."userId") -> Index Scan using "ActivityLogs_pkey" on "ActivityLogs" "activityLog" (cost=0.43..5.66 rows=1 width=57) (actual time=0.107..0.107 rows=0 loops=10) Index Cond: ("Post"."activityLogId" = id) -> Index Scan using "WeightLogs_pkey" on "WeightLogs" "weightLog" (cost=0.42..4.53 rows=1 width=69) (actual time=0.001..0.001 rows=0 loops=10) Index Cond: ("Post"."weightLogId" = id) -> Index Scan using "Workouts_pkey" on "Workouts" workout (cost=0.43..6.09 rows=1 width=225) (actual time=0.001..0.001 rows=0 loops=10) Index Cond: ("Post"."workoutId" = id) -> Index Scan using "WorkoutLogs_pkey" on "WorkoutLogs" "workoutLog" (cost=0.43..5.75 rows=1 width=61) (actual time=1.118..1.118 rows=0 loops=10) Index Cond: ("Post"."workoutLogId" = id) -> Index Scan using "Workouts_pkey" on "Workouts" "workoutLog.workout" (cost=0.43..4.21 rows=1 width=225) (actual time=0.004..0.004 rows=0 loops=10) Index Cond: ("workoutLog"."workoutId" = id) Total runtime: 7974.524 ms
如何才能暂时优化?
我有以下相关索引:
-- Gets used CREATE INDEX "posts_createdat_public_index" ON "public"."Posts" USING btree("createdAt" DESC) WHERE "private" IS null; -- Don't get used CREATE INDEX "posts_userid_fk_index" ON "public"."Posts" USING btree("userId"); CREATE INDEX "posts_following_index" ON "public"."Posts" USING btree("userId","createdAt" DESC) WHERE "private" IS null;
也许这需要一个带有createdAt和userId的大型部分复合索引,其中private IS NULL?
不要使用巨大的IN列表,而是连接VALUES表达式,或者如果列表足够大,请使用临时表,对其进行索引,然后加入它.
如果Postgresql可以在内部和外部执行此操作,那就太好了.自动,但此时规划师不知道如何.
类似主题:
> https://stackoverflow.com/q/24647503/398670
> https://stackoverflow.com/q/17813492/398670