2013-10-03 2 views
4

프로덕션 환경에서는 느리지 만 개발 컴퓨터에서는 빠르게 쿼리를 디버깅하려고합니다. 내 dev에 상자는 불과 며칠 오래된 prod 데이터베이스의 스냅 샷을 가지고 있으므로 두 DB의 내용은 거의 같습니다.Postgresql 쿼리 계획 불일치

쿼리는 다음과 같습니다

select count(*) from big_table where search_column in ('something') 

참고 :

  • big_table 약 35M 행이 snapshot materialized view하고 매일
  • search_column 갱신 B-tree 인덱스를 가지고있다. explain analyze
  • 자극이
  • 디바이스가 OS 9.0 우분투 9.1 인 X

쿼리 계획

결과 :

자극 :

QUERY PLAN                      
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
Aggregate (cost=1119843.20..1119843.21 rows=1 width=0) (actual time=467388.276..467388.278 rows=1 loops=1) 
    -> Bitmap Heap Scan on big_table (cost=10432.55..1118804.45 rows=415497 width=0) (actual time=116891.126..466949.331 rows=210053 loops=1) 
     Recheck Cond: ((search_column)::text = 'something'::text) 
     -> Bitmap Index Scan on big_table_search_column_index (cost=0.00..10328.68 rows=415497 width=0) (actual time=8467.901..8467.901 rows=337164 loops=1) 
       Index Cond: ((search_column)::text = 'something'::text) 
Total runtime: 467389.534 ms 
(6 rows) 

dev :

QUERY PLAN                     
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
Aggregate (cost=524011.38..524011.39 rows=1 width=0) (actual time=209.852..209.852 rows=1 loops=1) 
    -> Bitmap Heap Scan on big_table (cost=5131.43..523531.22 rows=192064 width=0) (actual time=33.792..194.730 rows=209551 loops=1) 
     Recheck Cond: ((search_column)::text = 'something'::text) 
     -> Bitmap Index Scan on big_table_search_column_index (cost=0.00..5083.42 rows=192064 width=0) (actual time=27.568..27.568 rows=209551 loops=1) 
       Index Cond: ((search_column)::text = 'something'::text) 
Total runtime: 209.938 ms 
(6 rows) 

및 자극 및 디바이스에 대한 두 개의 쿼리의 실제 결과는 각각 210,053 및 209,551의 행이다.

두 계획의 구조는 동일하지만 각 DB의 테이블에 대략 동일한 수의 행이있는 경우 위의 비용 차이를 설명 할 수 있습니까?

자극 :

current_database | schemaname |   tablename   | tbloat | wastedbytes |        iname        | ibloat | wastedibytes 
------------------+------------+---------------------------------+--------+-------------+---------------------------------------------------------------+--------+-------------- 
my_db   | public  | big_table      | 1.6 | 7965433856 | big_table_search_column_index         | 0.1 |   0 

블로 @의 BMA의 제안에

, 여기에 자극 및 디바이스 및 관련 테이블/인덱스에 대한 "팽창"쿼리의 결과는 dev :

current_database | schemaname |   tablename   | tbloat | wastedbytes |        iname        | ibloat | wastedibytes 
------------------+------------+---------------------------------+--------+-------------+---------------------------------------------------------------+--------+-------------- 
my_db   | public  | big_table      | 0.8 |   0 | big_table_search_column_index         | 0.1 |   0 

바일 라, 여기에 차이가 있습니다.

나는 vacuum analyze big_table;을 실행했지만 카운트 쿼리의 실행 시간과 큰 차이가없는 것처럼 보입니다.

구성

SELECT name, current_setting(name), source FROM pg_settings WHERE source NOT IN ('default', 'override');

결과 BMA에 의해 제안 :

자극 :

  name   |   current_setting   |  source   
----------------------------+----------------------------------+---------------------- 
application_name   | psql        | client 
DateStyle     | ISO, MDY       | configuration file 
default_text_search_config | pg_catalog.english    | configuration file 
effective_cache_size  | 6GB        | configuration file 
external_pid_file   | /var/run/postgresql/9.1-main.pid | configuration file 
listen_addresses   | *        | configuration file 
log_line_prefix   | %t        | configuration file 
log_timezone    | localtime      | environment variable 
max_connections   | 100        | configuration file 
max_stack_depth   | 2MB        | environment variable 
port      | 5432        | configuration file 
shared_buffers    | 2GB        | configuration file 
ssl      | on        | configuration file 
TimeZone     | localtime      | environment variable 
unix_socket_directory  | /var/run/postgresql    | configuration file 
(15 rows) 

dev에 :

  name   |  current_setting  |  source   
----------------------------+-------------------------+---------------------- 
application_name   | psql     | client 
DateStyle     | ISO, MDY    | configuration file 
default_text_search_config | pg_catalog.english  | configuration file 
effective_cache_size  | 4GB      | configuration file 
lc_messages    | en_US     | configuration file 
lc_monetary    | en_US     | configuration file 
lc_numeric     | en_US     | configuration file 
lc_time     | en_US     | configuration file 
listen_addresses   | *      | configuration file 
log_destination   | syslog     | configuration file 
log_directory    | ../var     | configuration file 
log_filename    | postgresql-%Y-%m-%d.log | configuration file 
log_line_prefix   | %t      | configuration file 
log_statement    | all      | configuration file 
log_timezone    | Australia/Hobart  | command line 
logging_collector   | on      | configuration file 
maintenance_work_mem  | 512MB     | configuration file 
max_connections   | 50      | configuration file 
max_stack_depth   | 2MB      | environment variable 
shared_buffers    | 2GB      | configuration file 
ssl      | off      | configuration file 
synchronous_commit   | off      | configuration file 
TimeZone     | Australia/Hobart  | command line 
timezone_abbreviations  | Default     | command line 
work_mem     | 100MB     | configuration file 
(25 rows) 
+2

테스트 전에 프로덕션 db에서 "ANALYZE"를 실행 했습니까? 또한 dev 버전은 최적 상태에있을 가능성이 높습니다. 데이터는 디스크에서 연속적입니다. 여기서 생산 (정상적인 UPDATE/DELETE 사용을 가정 할 때)은 그렇지 않습니다. 또한 : bloat : http://wiki.postgresql.org/wiki/Show_database_bloat를 확인하고 서버마다 다른 구성 설정이 있는지 표시하십시오. SELECT 이름, current_setting (이름), 소스 발신자 번호 pg_settings 소스 없음 IN ('default', 'override'); – bma

+0

다시 분석 : DB에 대해 자동 실행 프로세스가 실행 중입니다 - 분석 실행 중인지 어떻게 확인합니까? –

+0

Re UPDATE/DELETE - 테이블이 구체화 된 뷰에 대한 추가 참고 사항을 참조하십시오. - 이것은 연속성이라는 측면에서 볼 때 두 가지 환경이 상당히 비슷하다는 것을 의미한다고 가정합니다. –

답변

1

와일드 gues 코멘트가 너무 길어서 ...) : 매트보기를 새로 고치는 데 사용되는 쿼리 계획이 데이터 분포로 인해 매우 다르기 때문에 매트보기가 완전히 다른 방식으로 채워지는 결과를 초래할 수 있습니다.

이렇게하면 비슷한 비트 맵 인덱스 스캔 계획이 생길 수 있지만, 후자의 경우에는 많은 양의 프로덕션과 달리 편리하게 몇 개의 설치 디스크 페이지를 방문해야합니다.

이 리드가 의미가있는 경우 실제로 매트보기를 새로 고치거나 새로 고치는 데 사용되는 쿼리 계획을 게시 할 수 있습니까? 이들이 크게 다른 경우 (비용 견적, 계획 등) 매트 뷰 (가능하면 search_column 자체)에 클러스터 된 인덱스를 작성하여 중요한 차이가 있는지 확인하십시오. (그렇게 한 후에 분석하는 것을 잊지 마십시오.)

1

이 구체화 된보기 테이블에 대한 대부분의 쿼리가 search_column으로 제한되는 경우 새로 고치면 cluster big_table using big_table_search_column_index; reindex big_table;을 실행하는 것이 좋습니다.

이 작업은 실행 중일 때 약간의 시간이 걸리며이 테이블을 차단합니다.이 테이블은이 search_column에 의해 정렬 된 디스크에 저장됩니다. 따라서 search_column 값으로 제한된 모든 쿼리는 제한된 수의 디스크 블록 만 검색하고 디스크 플래터의 제한된 위치에서도 검색해야합니다. 색인을 다시 작성하면 cluster 이후 색인이 부 풀릴 수 있습니다.

당신의 dev 컴퓨터에는 SSD 드라이브가있어 데이터가 흩어져있는 위치에서 검색하는 것이 좋습니다. 프로덕션에는 고전적인 회전식 자기 디스크 또는 디스크가있을 것입니다.이 디스크는 끔찍합니다. 또한 최근에 생성되었으므로 부 풀리지 않습니다 (데이터 삭제 후 남은 구멍). 그리고 이것은 이것이 수십 배의 속도 저하를 초래한다고 생각합니다.

+0

이것은 합리적인 제안입니다. 그러나 'search_column'만 인덱싱 된 열이 아니므로 클러스터링을 사용하면 다른 검색을 희생 시키더라도 속도가 빨라질 수 있습니다. 테이블이 인덱스를 기반으로 "clustered"된 방법을 측정 할 수 있으므로 실제로 프로덕션 DB를 수정하지 않아도됩니까? –

+0

Re SSD, 내 컴퓨터에는 확실히 전통적인 자기, 하드 디스크가 있습니다. –