2017-09-29 5 views
1

私はpostgres EXPLAINの出力からいくつかの意味を作ろうとしています。さまざまなシナリオでインデックスをどこに配置するかを知りたい。Postgres EXPLAINとインデックスを置く場所

一つの例は次のとおりです。

EXPLAIN for: SELECT "users".* FROM "users" INNER JOIN "user_sessions" ON "user_sessions"."user_id" = "users"."id" WHERE "user_sessions"."token" = $1 AND (user_sessions.expires_at > '2017-09-29 08:56:26.388291') [["token", "foo"]] 

は私を与える:

Nested Loop (cost=0.30..16.35 rows=1 width=192) 
    -> Index Scan using index_user_sessions_on_token on user_sessions (cost=0.15..8.17 rows=1 width=4) 
     Index Cond: ((token)::text = 'foo'::text) 
     Filter: (expires_at > '2017-09-29 08:56:26.388291'::timestamp without time zone) 
    -> Index Scan using users_pkey on users (cost=0.15..8.17 rows=1 width=192) 
     Index Cond: (id = user_sessions.user_id) 

単一のインデックス[user_id, token, expires_at]user_id[token, expires_at]を持つ2つのインデックスよりも "より" が適切であろうか?

+0

注:複数の一致するuser_sessions行が見つかると、クエリの結果は重複します。 (私はEXISTS()構文を使用することをお勧めします) – joop

答えて

2

tokenにインデックスを追加し、(token, expires_at)のインデックスに置き換えると、改善することができます。 user_sessionsの条件全体を索引条件として使用すると、不要な索引の読取りとヒープのチェックが不要になり、問合せの効率が向上します。

実際に多くの影響があるかどうかを確認するには、どちらの場合もEXPLAIN (ANALYZE, BUFFERS)を実行します。フィルタによって多くの行が削除され、より多くのブロックがタッチされた場合、クエリは遅くなります。まず、PostgreSQLはtokenexpires_at上の条件に基づいてuser_session内のすべての行を見つけ、それはusersに一致するすべての行を検索します。この条件が検索されないためuser_sessions (user_id)

インデックスは、まったく助けにはなりません。

+0

恐ろしい応答、最後の段落にスポットがあります。今、私はそれがどのように機能するかをよりよく理解しています。ありがとうございました! – sandelius

関連する問題