2016-12-09 5 views
2

이메일 메시지를 저장하는 데이터베이스에서 두 개의 쿼리 속도를 높일 수 있는지 알아 내려고하고 있습니다.느린 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로 주문하는 것이 왜 그렇게 느린가요?

+1

'groupid = 1886'의 레코드 수는 얼마나됩니까? 어쩌면'(groupid, id)'와'(groupid, created) '에 인덱스를 추가하는 것이 도움이 될 것입니다. –

+0

groupid = 1886에 200,563 개의 행이 있습니다. –

+1

코멘트에 색인을 추가해보십시오. 이제는 postgres가 느리게 진행되는 200,000 개의 레코드를 정렬해야합니다. 'OFFSET'이없는 쿼리는 빠르지 만 인덱스를 사용하면 문제를 정렬해야합니다. –

답변

3

groupid=1886 (메모 : 200,563) 레코드가 여러 개있는 경우 정렬 된 하위 행 집합의 OFFSET 레코드를 얻으려면 정렬이 필요합니다 (또는 동일한 힙 알고리즘).

이것은 색인을 추가하여 해결할 수 있습니다. 이 경우 하나는 (groupid,id)이고 다른 하나는 (groupid,created)입니다.

댓글 :이게 참으로 도움이되었습니다. 런타임을 5ms-10ms로 단축했습니다.