2016-10-13 2 views
0

実行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のを持っているが、コストが100Kを超えていると言います。過度だと思う。これは、私が各テーブル用に作成したインデックスを利用していない唯一のクエリです。

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) 

インデックスが誤って設定されていると感じたり、クエリに何か不足しています。最初のシーケンススキャンでそれを殺しています。

追加されませインデックスは、このクエリのお手伝いをしませんVERBOSE

"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" 
+1

質問を編集し、 'explain(analyze、verbose) 'を使用して生成された実行計画を追加してください。 [_Formatted_](http://stackoverflow.com/editing-help#code)**テキスト**お願い、[スクリーンショットなし](http://meta.stackoverflow.com/questions/285551/why-may-i 285557#285557) –

+0

説明を追加しました – DigitalDisaster

+0

3つの列にインデックスがあり、2つの列しか使用していないように見えますクエリ内にあります。インデックスにはすべて3が必要です。(id、accounts_id、events_id)idを主キーインデックスとして使用し、accounts_id&events_idに別のインデックスを追加します。 – winkbrace

答えて

3

EXPLAIN。

問題は、あなたがWHERE状態でORを持っているということですので、前にテーブルは、インデックスがあなたを助けることができる場所である、接合されたフィルタを適用することはできません。 ORANDに置き換えて、PostgreSQLがもっとうまくいく方法を見てみてください。

PostgreSQLは全体を計算している。この方法では、参加して、フィルタのみに参加することによって除去行の偉大な数を見–その後の行をフィルタリングすることができます。

インデックスが使用できる唯一のことは、ネストされたループ結合であり、それははるかに高価になります。だから私はこのクエリのためのより良い計画があるとは思わない。

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 ... 

のようなクエリを使用して、より良い行うことができますが、私はそれに賭けていないでしょう。
(注:このクエリは意味的にわずかですが、場合によっては問題ではありません)

関連する問題