Postgresql に 1,500 万行を超えるテーブルがあります。ユーザーはこれらの行 (アイテムとしましょう) をライブラリに保存でき、ユーザーがライブラリを要求すると、システムはユーザーのライブラリをロードします。
Postgresql のクエリは次のようになります
SELECT item.id, item.name
FROM items JOIN library ON (library.item_id = item.id)
WHERE library.user_id = 1
、テーブルは既にインデックスが作成され、非正規化されているため、他の JOIN は必要ありません。
ユーザーがライブラリに多数のアイテム (1,000 個のアイテムなど) を持っている場合、クエリ時間は通常増加します。(たとえば、1k アイテムの場合、クエリ時間は 7 秒です) 私の目的は、大規模なデータセットのクエリ時間を短縮することです。
私はすでにSolrを全文検索に使用しており、次のようなクエリを試し?q=id:1 OR id:100 OR id:345
ましたが、Solrで効率的かどうかはわかりません。
このデータセットをクエリするための代替手段を知りたいです。私のシステムのボトルネックは、ディスク速度のようです。15 GB を超えるメモリを搭載したサーバーを購入し、shared_memory
オプションを増やして Postgresql を使用するか、Mongodb や別のメモリ ベースのデータベースなどを試すか、またはクラスター システムを作成して Postgresql にデータを複製する必要がありますか?
items:
Column | Type
--------------+-------------------
id | text
mbid | uuid
name | character varying
length | integer
track_no | integer
artist | text[]
artist_name | text
release | text
release_name | character varying
rank | numeric
user_library:
Column | Type | Modifiers
--------------+-----------------------------+--------------------------------------------------------------
user_id | integer | not null
recording_id | character varying(32) |
timestamp | timestamp without time zone | default now()
id | integer | primary key nextval('user_library_idx_pk'::regclass)
-------------------
explain analyze
SELECT recording.id,name,track_no,artist,artist_name,release,release_name
FROM recording JOIN user_library ON (user_library.recording_id = recording.id)
WHERE user_library.user_id = 1;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
Nested Loop (cost=0.00..10745.33 rows=1036539 width=134) (actual time=0.168..57.663 rows=1000 loops=1)
Join Filter: (recording.id = (recording_id)::text)
-> Seq Scan on user_library (cost=0.00..231.51 rows=1000 width=19) (actual time=0.027..3.297 rows=1000 loops=1) (my opinion: because user_library has only 2 rows, Postgresql didn't use index to save resources.)
Filter: (user_id = 1)
-> Append (cost=0.00..10.49 rows=2 width=165) (actual time=0.045..0.047 rows=1 loops=1000)
-> Seq Scan on recording (cost=0.00..0.00 rows=1 width=196) (actual time=0.001..0.001 rows=0 loops=1000)
-> Index Scan using de_recording3_table_pkey on de_recording recording (cost=0.00..10.49 rows=1 width=134) (actual time=0.040..0.042 rows=1 loops=1000)
Index Cond: (id = (user_library.recording_id)::text)
Total runtime: 58.589 ms
(9 rows)