이메일 메시지를 저장하는 데이터베이스에서 두 개의 쿼리 속도를 높일 수 있는지 알아 내려고하고 있습니다.느린 Postgres 9.3 쿼리
\d messages;
Table "public.messages"
Column | Type | Modifiers
----------------+---------+-------------------------------------------------------
id | bigint | not null default nextval('messages_id_seq'::regclass)
created | bigint |
updated | bigint |
version | bigint |
threadid | bigint |
userid | bigint |
groupid | bigint |
messageid | text |
date | bigint |
num | bigint |
hasattachments | boolean |
placeholder | boolean |
compressedmsg | bytea |
revcount | bigint |
subject | text |
isreply | boolean |
likes | bytea |
isspecial | boolean |
pollid | bigint |
username | text |
fullname | text |
Indexes:
"messages_pkey" PRIMARY KEY, btree (id)
"idx_unique_message_messageid" UNIQUE, btree (groupid, messageid)
"idx_unique_message_num" UNIQUE, btree (groupid, num)
"idx_group_id" btree (groupid)
"idx_message_id" btree (messageid)
"idx_thread_id" btree (threadid)
"idx_user_id" btree (userid)
출력
SELECT relname, relpages, reltuples::numeric, pg_size_pretty(pg_table_size(oid)) FROM pg_class WHERE oid='messages'::regclass;
에서
relname | relpages | reltuples | pg_size_pretty
----------+----------+-----------+----------------
messages | 1584913 | 7337880 | 32 GB
일부 가능한 관련 포스트 그레스의 설정 값입니다 : 여기에 테이블입니다
: 여기shared_buffers = 1536MB
effective_cache_size = 4608MB
work_mem = 7864kB
maintenance_work_mem = 384MB
Analyze (분석) 설명 출력은
explain analyze SELECT * FROM messages WHERE groupid=1886 ORDER BY id ASC LIMIT 20 offset 4440;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=479243.63..481402.39 rows=20 width=747) (actual time=14167.374..14167.408 rows=20 loops=1)
-> Index Scan using messages_pkey on messages (cost=0.43..19589605.98 rows=181490 width=747) (actual time=14105.172..14167.188 rows=4460 loops=1)
Filter: (groupid = 1886)
Rows Removed by Filter: 2364949
Total runtime: 14167.455 ms
(5 rows)
두 번째 쿼리는 :
이는 SSD에explain analyze SELECT * FROM messages WHERE groupid=1886 ORDER BY created ASC LIMIT 20 offset 4440;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=538650.72..538650.77 rows=20 width=747) (actual time=671.983..671.992 rows=20 loops=1)
-> Sort (cost=538639.62..539093.34 rows=181490 width=747) (actual time=670.680..671.829 rows=4460 loops=1)
Sort Key: created
Sort Method: top-N heapsort Memory: 7078kB
-> Bitmap Heap Scan on messages (cost=7299.11..526731.31 rows=181490 width=747) (actual time=84.975..512.969 rows=200561 loops=1)
Recheck Cond: (groupid = 1886)
-> Bitmap Index Scan on idx_unique_message_num (cost=0.00..7253.73 rows=181490 width=0) (actual time=57.239..57.239 rows=203423 loops=1)
Index Cond: (groupid = 1886)
Total runtime: 672.787 ms
(9 rows)
8GB의 램 인스턴스는,로드 평균은 일반적으로 약 0.15이다.
저는 전문가가 아닙니다. 디스크 전체에 퍼져있는 데이터의 경우입니까? CLUSTER를 사용하는 유일한 해결책은 무엇입니까?
두 번째 쿼리의 인덱스로 idx_unique_message_num
을 사용하는 이유는 무엇입니까? ID로 주문하는 것이 왜 그렇게 느린가요?
'groupid = 1886'의 레코드 수는 얼마나됩니까? 어쩌면'(groupid, id)'와'(groupid, created) '에 인덱스를 추가하는 것이 도움이 될 것입니다. –
groupid = 1886에 200,563 개의 행이 있습니다. –
코멘트에 색인을 추가해보십시오. 이제는 postgres가 느리게 진행되는 200,000 개의 레코드를 정렬해야합니다. 'OFFSET'이없는 쿼리는 빠르지 만 인덱스를 사용하면 문제를 정렬해야합니다. –