簡體   English   中英

為什么此查詢不使用我創建的索引?

[英]Why doesn't this query use the indexes i've created?

運行postgres 9.5

SELECT events.id, events.start_time, events.host_id, events.title from events
JOIN accountsevents ON accountsevents.events_id = events.id
WHERE accountsevents.accounts_id = %(account_id)s OR events.host_id = %(account_id)s
GROUP BY events.id
ORDER BY start_time DESC

我有這個查詢,postgres說費用超過10萬。 似乎過多。 這是我唯一沒有使用為每個表創建的索引的查詢。

Indexes:
    "events_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "events_host_id_fkey" FOREIGN KEY (host_id) REFERENCES accounts(id)
Referenced by:
    TABLE "accountsevents" CONSTRAINT "accountsevents_events_id_fkey" FOREIGN KEY (events_id) REFERENCES events(id)
    TABLE "eventsinterests" CONSTRAINT "eventsinterests_events_id_fkey" FOREIGN KEY (events_id) REFERENCES events(id)


Indexes:
    "accountsevents_pkey" PRIMARY KEY, btree (id, accounts_id, events_id)
Foreign-key constraints:
    "accountsevents_accounts_id_fkey" FOREIGN KEY (accounts_id) REFERENCES accounts(id)
    "accountsevents_events_id_fkey" FOREIGN KEY (events_id) REFERENCES events(id)

我覺得索引設置錯誤,或者查詢中缺少內容。 最初的序列掃描正在殺死它。

添加詳細說明

"Sort  (cost=124388.27..124390.10 rows=732 width=40) (actual time=1533.902..1533.928 rows=470 loops=1)"
"  Output: events.id, events.start_time, events.host_id, events.title"
"  Sort Key: events.start_time DESC"
"  Sort Method: quicksort  Memory: 66kB"
"  ->  HashAggregate  (cost=124346.12..124353.44 rows=732 width=40) (actual time=1533.658..1533.759 rows=470 loops=1)"
"        Output: events.id, events.start_time, events.host_id, events.title"
"        Group Key: events.id"
"        ->  Hash Join  (cost=4912.30..124344.29 rows=732 width=40) (actual time=56.671..1532.831 rows=971 loops=1)"
"              Output: events.id, events.start_time, events.host_id, events.title"
"              Hash Cond: (accountsevents.events_id = events.id)"
"              Join Filter: ((accountsevents.accounts_id = 1) OR (events.host_id = 1))"
"              Rows Removed by Join Filter: 2761882"
"              ->  Seq Scan on public.accountsevents  (cost=0.00..45228.52 rows=2762852 width=8) (actual time=0.005..466.094 rows=2762853 loops=1)"
"                    Output: accountsevents.events_id, accountsevents.accounts_id"
"              ->  Hash  (cost=2795.91..2795.91 rows=104191 width=40) (actual time=53.579..53.579 rows=104181 loops=1)"
"                    Output: events.id, events.start_time, events.host_id, events.title"
"                    Buckets: 65536  Batches: 4  Memory Usage: 2462kB"
"                    ->  Seq Scan on public.events  (cost=0.00..2795.91 rows=104191 width=40) (actual time=0.004..26.171 rows=104181 loops=1)"
"                          Output: events.id, events.start_time, events.host_id, events.title"
"Planning time: 0.201 ms"
"Execution time: 1534.024 ms"

沒有索引可以幫助您進行此查詢。

問題是您在WHERE條件下具有OR ,因此無法連接表之前應用過濾器,這是索引可以為您提供幫助的地方。 嘗試用AND替換OR AND然后看看PostgreSQL如何做得更好。

這樣,PostgreSQL必須計算整個聯接,並且之后只能過濾掉行–請參閱Join Filter刪除的大量

索引唯一可用於的是嵌套循環連接,這將花費更多。 因此,我認為此查詢沒有更好的計划。

您可以看到PostgreSQL對行數的估計是相當不錯的,通常這表明PostgreSQL確實做了正確的事。

也許您可以通過以下查詢來做得更好

SELECT * FROM
   (SELECT ... FROM events JOIN accountsevents ON ...
       WHERE accountsevents.accounts_id = 1
    UNION
    SELECT ... FROM events JOIN accountsevents ON ...
       WHERE events.host_id = 1) sub
GROUP BY ... ORDER BY ...

但我不會打賭。
(請注意:此查詢在語義上略有不同,但對於您的情況可能並不重要。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM