18M行のビデオテーブルがあります。 IDで特定の動画を検索すると、完了するまでに最大6秒かかります。数ミリ秒かかる場合もあれば、最大6秒かかる場合もありますが、平均して約2秒です。
アプリケーションはherokuでホストされており、Craneデータベース( https://addons.heroku.com/heroku-postgresql )と410MBのRAMを使用しています。
これをスピードアップする方法はありますか?私はビデオを1秒あたり平均50回クエリしていますが、新しいビデオは1秒あたり50回の速度で挿入/更新されます。
explain analyze SELECT * FROM videos WHERE id = 17841464 LIMIT 1;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.00..6.43 rows=1 width=119) (actual time=2337.892..2337.894 rows=1 loops=1)
-> Index Scan using videos_pkey on videos (cost=0.00..6.43 rows=1 width=119) (actual time=2337.888..2337.888 rows=1 loops=1)
Index Cond: (id = 17841464)
Total runtime: 2337.943 ms
テーブルは次のようになります。
\d+ videos;
Table "public.videos"
Column | Type | Modifiers | Storage | Stats target | Description
----------------+-----------------------------+-----------------------------------------------------+----------+--------------+-------------
id | integer | not null default nextval('videos_id_seq'::regclass) | plain | |
uuid | character(11) | not null | extended | |
channel_id | integer | not null | plain | |
category_id | integer | | plain | |
title | character varying(255) | | extended | |
published_at | timestamp without time zone | | plain | |
view_count | bigint | | plain | |
like_count | integer | | plain | |
dislike_count | integer | | plain | |
favorite_count | integer | | plain | |
comment_count | integer | | plain | |
disabled | boolean | default false | plain | |
created_at | timestamp without time zone | | plain | |
updated_at | timestamp without time zone | | plain | |
Indexes:
"videos_pkey" PRIMARY KEY, btree (id)
"videos_uuid_idx" UNIQUE, btree (uuid)
"videos_latest_by_channel_idx" btree (channel_id, published_at DESC)
"videos_top_by_channel_idx" btree (channel_id, view_count DESC)
Has OIDs: no
正直なところ、単一値のbtreeルックアップにこれほど長い時間がかかることはありません。私はあなたの問題が単にあなたの質問にあるとは思いません。それは別の場所だと思います。
まず、書き込みが多いと言います。これはおそらく、バッファから多くのものを常に押し出し、ランダムなディスクI/Oを大量に実行していることを意味します。ボトルネックの多くが一般的なI/OとRAMの不足にあったとしても、私は驚かないでしょう。
1,800万行の場合、これらはそれほど大きく見えません。それらはすべてメモリに収まる場合があります。
とにかく、サーバーのコマンドラインにアクセスできる場合、最初に行うべきことは、CPU I/O待機対ユーザー時間対システム時間を取ることです(コードの他の場所で実行できる場合があります)。また、(ANALYSE、BUFFERS、VERBOSE)を設定してExplainを実行し、何が起こっているのかをより詳しく確認できるようにします。これらは、問題がCPUアクティビティ、低速のRAM、または大量のディスクI/Oであるかどうかを判断するのに役立ちますが、現状では、実行できることはほとんどありません。
あなたができる別のことはこれです:
VACUUM ANALYSE VERBOSE;
それがスピードアップするかどうかを確認してください。