2016-12-09 3 views
0

私はコミュニティのWebアプリケーションを作っています。投稿のホットスコアをクエリするには?私のクエリはpostgresqlで遅い

以下のコードは、小さなローカルテストデータでうまく動作します。

しかし、多くのデータ(10k以上)では非常に遅いです。ここで

は、PostgreSQLのクエリプランが

"Limit (cost=6653.10..6653.13 rows=10 width=641) (actual time=355.355..355.357 rows=10 loops=1)" 
" Output: id, title, content, like_count, comment_count, view_count, scrap_count, deleted, has_img, has_video, created_at, updated_at, author_id, forum_id, prefix_id, width, height, link_id, ((log((GREATEST(like_count, 1))::double precision) + (date_part(' (...)" 
" -> Sort (cost=6653.10..6903.41 rows=10width=641) (actual time=355.353..355.353 rows=10 loops=1)" 
"  Output: id, title, content, like_count, comment_count, view_count, scrap_count, deleted, has_img, has_video, created_at, updated_at, author_id, forum_id, prefix_id, width, height, link_id, ((log((GREATEST(like_count, 1))::double precision) + (date_ (...)" 
"  Sort Key: ((log((GREATEST(tc_posts.like_count, 1))::double precision) + (date_part('epoch'::text, age(tc_posts.created_at, now()))/'45000'::double precision))) DESC, tc_posts.created_at DESC, tc_posts.id DESC" 
"  Sort Method: top-N heapsort Memory: 27kB" 
"  -> Seq Scan on public.tc_posts (cost=0.00..4489.48 rows=10width=641) (actual time=0.029..188.306 rows=100109 loops=1)" 
"    Output: id, title, content, like_count, comment_count, view_count, scrap_count, deleted, has_img, has_video, created_at, updated_at, author_id, forum_id, prefix_id, width, height, link_id, (log((GREATEST(like_count, 1))::double precision) + ((...)" 
"    Filter: (NOT tc_posts.deleted)" 
"    Rows Removed by Filter: 24" 
"Planning time: 0.194 ms" 
"Execution time: 355.427 ms" 

です。これは、クエリプランでは300以上のミリ秒かかります。 以下のクエリを最適化するにはどうすればよいですか?

SELECT *, 
     LOG(GREATEST(like_count, 1)) + EXTRACT(EPOCH FROM age(tc_posts.created_at, NOW()))/45000 AS hot 
FROM "tc_posts" 
WHERE "deleted" = FALSE 
ORDER BY "hot" DESC, 
     "created_at" DESC, 
     "id" DESC, 
LIMIT 10; 

答えて

1

だけでいくつかのヒントので、私はあなたのデータを知らない:

  • が高いwork_memを設定するようにしてください - EXPLAIN前にこのset work_mem = '128MB';のようなコマンドを追加して、セッションごとに異なるwork_mem設定をテストします。しかし、これを使用できるかどうかは、使用しているメモリーの数と使用しているセッションの数によって異なります。

  • SELECT *は、実際にすべての列が必要な場合を除き、常にパフォーマンスキラーです。

  • 私は出力にSeq Scan on public.tc_posts ... Filter: (NOT tc_posts.deleted)を見ることができます - それはあなたのすべてのためのいくつかのmimisecondsが保存されます - PostgreSQLは新しいセッションを開くと、あなたが取引でプールでpgbouncer使用することができますので、多分、いくつかの遅延があるtc_posts.deleted

  • にインデックスを追加することを検討接続