【问题标题】:Postgres Left Join with and condition too slowPostgres Left Join 和条件太慢
【发布时间】:2022-01-19 17:18:55
【问题描述】:

我有两张桌子

sleeps

SleepId SleepTime WakeupTime
141b40f7-688b-43af-8266-3cc4612b8f98 2021-11-25 22:27:30 2021-11-25 22:16:30
e91bd0f8-688b-43af-8266-dsc4612f8490 2021-11-24 22:27:30 2021-11-24 22:16:30

sleepupdates

SleepId SleepTime WakeupTime
141b40f7-688b-43af-8266-3cc4612b8f98 2021-11-25 22:27:30 2021-11-25 22:16:30

sleepupdates 表可能包含一些 SleepId,如果包含,我需要选择该 WakeupTime(来自 sleepudates 而不是 sleeps 表)。

我认为 left join 应该可以通过 coalesce 解决这个问题,但它看起来需要太多时间!

它似乎在根据条件过滤之前扫描左表

select s."SleepId", s."BedTime", s."SleepTime", coalesce(su."WakeupTime", s."WakeupTime") from sleeps s
left join sleepupdates su
on s."SleepId"=su."SleepId"
and s."SleepId"='141b40f7-688b-43af-8266-3cc4612b8f98

我在上述查询中需要帮助。

EXPLAIN ANALYZE

Text Format

explain (analyze,buffers,format text) select s."SleepId", s."BedTime", s."SleepTime", coalesce(su."WakeupTime", s."WakeupTime") from sleeps s
left join sleepupdates su
on s."SleepId"=su."SleepId"
and s."SleepId"='141b40f7-688b-43af-8266-3cc4612b8f98';
                                                           QUERY PLAN                                                           
--------------------------------------------------------------------------------------------------------------------------------
 Hash Right Join  (cost=123483.97..130997.74 rows=850932 width=40) (actual time=444.144..628.801 rows=852809 loops=1)
   Hash Cond: (su."SleepId" = s."SleepId")
   Join Filter: (s."SleepId" = '141b40f7-688b-43af-8266-3cc4612b8f98'::uuid)
   Rows Removed by Join Filter: 21396
   Buffers: shared hit=98037, temp read=4910 written=4848
   ->  Seq Scan on sleepupdates su  (cost=0.00..559.89 rows=21289 width=24) (actual time=0.005..2.806 rows=21396 loops=1)
         Buffers: shared hit=347
   ->  Hash  (cost=106199.32..106199.32 rows=850932 width=40) (actual time=438.068..438.068 rows=852809 loops=1)
         Buckets: 65536  Batches: 32  Memory Usage: 2067kB
         Buffers: shared hit=97690, temp written=4786
         ->  Seq Scan on sleeps s  (cost=0.00..106199.32 rows=850932 width=40) (actual time=0.007..263.471 rows=852809 loops=1)
               Buffers: shared hit=97690
 Planning time: 0.237 ms
 Execution time: 667.356 ms
(14 rows)

Indexes on sleepupdates

CREATE INDEX "sleepupdates_SleepId_idx"
    ON public.sleepupdates USING btree
    ("SleepId" ASC NULLS LAST)
    TABLESPACE pg_default;
-- Index: sleepupdates_SleepId_unique

-- DROP INDEX public."sleepupdates_SleepId_unique";

CREATE UNIQUE INDEX "sleepupdates_SleepId_unique"
    ON public.sleepupdates USING btree
    ("SleepId" ASC NULLS LAST, "Status" COLLATE pg_catalog."default" ASC NULLS LAST)
    TABLESPACE pg_default
    WHERE "Status" = 'PENDING'::text;
-- Index: sleepupdates_UserId_idx

-- DROP INDEX public."sleepupdates_UserId_idx";

CREATE INDEX "sleepupdates_UserId_idx"
    ON public.sleepupdates USING btree
    ("UserId" ASC NULLS LAST)
    TABLESPACE pg_default;

SleepIdsleeps 表中的主键

【问题讨论】:

  • edit您的问题并添加使用explain (analyze, buffers, format text)生成的execution plan不是只是一个“简单”解释)为formatted text,并确保保留计划的缩进。粘贴文本,然后将``` 放在计划前一行和计划后一行。还请包括所有索引的完整 create index 语句。
  • 您添加的是图像,而不是格式化文本。

标签: sql postgresql left-join


【解决方案1】:

您正在返回每一行睡眠。 s."SleepId"='141b40f7-688b-43af-8266-3cc4612b8f98 条件需要在 WHERE 子句中,而不是在 ON 中。

【讨论】:

    猜你喜欢
    • 2017-03-20
    • 2011-03-16
    • 1970-01-01
    • 2012-08-22
    • 2014-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多