简体   繁体   中英

Postgres Left Join with and condition too slow

I have two tables

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 table might contain some SleepIds and if it does, I need to pick that WakeupTime (from sleepudates and not sleeps table).

I thought left join should work for this with coalesce but it looks like its taking too much time!

It seems to scan the left table before it filter based on condition

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

I need help in above query.

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;

The SleepId is primary key in sleeps table

You are returning every row of sleeps. The s."SleepId"='141b40f7-688b-43af-8266-3cc4612b8f98 condition needs to be in a WHERE clause, not in the ON.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM