【发布时间】:2012-09-30 07:55:41
【问题描述】:
我在 Postgresql 中有一个超过 15m 行的表。用户可以将这些行(比如项目)保存到他们的库中,当他们请求他们的库时,系统会加载用户的库。
Postgresql 中的查询是这样的
SELECT item.id, item.name
FROM items JOIN library ON (library.item_id = item.id)
WHERE library.user_id = 1
,表已经被索引和非规范化,所以我不需要任何其他的 JOIN。
如果用户在库中有很多项目(例如 1k 个项目),则查询时间通常会增加。 (例如对于 1k 个项目,查询时间是 7 秒)我的目标是减少大型数据集的查询时间。
我已经使用 Solr 进行全文搜索,我尝试过像 ?q=id:1 OR id:100 OR id:345 这样的查询,但我不确定它在 Solr 中是否有效。
我想知道查询此数据集的替代方法。我系统的瓶颈似乎是磁盘速度。我应该购买一个内存超过 15gb 的服务器并在增加 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)
【问题讨论】:
-
为什么要在内存中加载 1K+ 行?您肯定不会一次将所有这些都显示到用户屏幕上吗?
-
我的意思不是只将特定的行加载到内存中。我的意思是加载所有 15m 行并在内存中工作。它确实加快了查询速度,但我需要额外的 ~8gb 内存。
-
在您的查询中显示
explain的结果 -
如果您有超过 1 台服务器怎么办?您将如何处理更新/插入?内存可以加快速度,但也有成本。您可以一次只处理一部分数据吗?顺便说一句,这是一个网络应用程序吗?
-
我猜7s的查询时间并不是真正的查询时间而是检索时间。将 1k 行从服务器传输到客户端所需的时间。什么是客户,您如何衡量查询时间?如果你这样做
explain analyze,它将显示真正的查询时间。
标签: database postgresql solr replication scalability