2011-11-25 4 views
5

수백만 (또는 수십억) 개의 행을 포함하는 새로운 PostgreSQL 9 데이터베이스를 설정 중입니다. 그래서 PostgreSQL 상속을 사용하여 데이터를 분할하기로 결정했습니다.올바른 분할 규칙 선택

CREATE TABLE mytable 
(
    user_id integer, 
    year integer, 
    CONSTRAINT pk_mytable PRIMARY KEY (user_id, year) 
); 

그리고 10 파티션 테이블 :

나는 (예를 들어 간체)과 같은 마스터 테이블을 생성

CREATE TABLE mytable_0() INHERITS (mytable); 
CREATE TABLE mytable_1() INHERITS (mytable); 
... 
CREATE TABLE mytable_9() INHERITS (mytable); 

I 행은 항상 고유를 사용하여 응용 프로그램에서 액세스 할 것이라는 점을 알고있다 user_id 조건. 그래서 나는 user_id에 기반한 규칙을 사용하여 10 개의 테이블에 데이터를 "똑같이"퍼뜨리고 싶습니다.

마스터 테이블에 조정 쿼리에

, 내 첫번째 생각은 계수 점검 제한 조건을 사용하는 것이었다 :

ALTER TABLE mytable_0 ADD CONSTRAINT mytable_user_id_check CHECK (user_id % 10 = 0); 
ALTER TABLE mytable_1 ADD CONSTRAINT mytable_user_id_check CHECK (user_id % 10 = 1); 
... 

문제이고, 나는 USER_ID, PostgreSQL을에 조건 마스터 테이블 "MYTABLE"를 쿼리 할 때 분석기는 모든 테이블을 확인하고 점검 제한 조건에서 혜택을받지 않습니다

EXPLAIN SELECT * FROM mytable WHERE user_id = 12345; 

"Result (cost=0.00..152.69 rows=64 width=36)" 
" -> Append (cost=0.00..152.69 rows=64 width=36)" 
"  -> Seq Scan on mytable (cost=0.00..25.38 rows=6 width=36)" 
"    Filter: (user_id = 12345)" 
"  -> Seq Scan on mytable_0 mytable (cost=0.00..1.29 rows=1 width=36)" 
"    Filter: (user_id = 12345)" 
"  -> Seq Scan on mytable_1 mytable (cost=0.00..1.52 rows=1 width=36)" 
"    Filter: (user_id = 12345)" 
... 
"  -> Seq Scan on mytable_9 mytable (cost=0.00..1.52 rows=1 width=36)" 
"    Filter: (user_id = 12345)" 

반면 나는 (그 규칙과 일치하는 재분할와) 같은 고전적인 점검 제한 조건을 사용하는 경우 :

ALTER TABLE mytable_0 ADD CONSTRAINT mytable_user_id_check CHECK (user_id BETWEEN 1 AND 10000); 
ALTER TABLE mytable_1 ADD CONSTRAINT mytable_user_id_check CHECK (user_id BETWEEN 10001 AND 20000); 
... 

가 (이 예에서 MYTABLE 및 mytable_1) 조건에 일치하는 테이블 만 스캔 :

"Result (cost=0.00..152.69 rows=64 width=36)" 
" -> Append (cost=0.00..152.69 rows=64 width=36)" 
"  -> Seq Scan on mytable (cost=0.00..25.38 rows=6 width=36)" 
"    Filter: (user_id = 12345)" 
"  -> Seq Scan on mytable_1 mytable (cost=0.00..1.52 rows=1 width=36)" 
"    Filter: (user_id = 12345)" 

그러나 그러한 점검 제한 조건을 사용하여 유지하기 어려운 때문으로 채워집니다 사용자의 범위 테이블은 수년에 걸쳐 변화 할 것입니다. 수천 먼저, 어쩌면 수백만 또는 가까운 미래에 ...

체크 제약 조건의 혜택을 누릴 수있는 10 개의 테이블에 똑같은 방식으로 데이터를 분할 할 때 어떤 규칙을 사용하면 마스터 테이블의 SELECT 만 스캔 할 수 있습니까? 오른쪽 테이블 ...?

감사 니코

답변

5

제한은 플래너보다는 파티셔닝 자체이다. 그것은 일부 세부 설명서에 덮여 :

http://www.postgresql.org/docs/9.1/static/ddl-partitioning.html

그 필요성이 고려되어야하지만 당신이 언급 두 가지가 있습니다.

먼저 모든 액세스가 기본 키를 통해 이루어집니다. 즉, 파티셔닝으로 얻을 수있는 성능상의 이점은 없습니다 (적어도 정상적인 사용에는 해당되지 않음). 각 파티션의 색인은 작을지라도 PG는 먼저 확인할 파티션을 선택해야합니다. 다시 색인화해야 할 경우 어디에서 얻을 것인가? 각 파티션을 별도로 다시 색인 할 수 있습니다.

둘째, 수천에서 수십억 개의 행이있을 수 있다고 말합니다. 이것은 두 가지 결론을 이끌어 낸다.

  1. 나중에 결정을 남겨두기 바란다. 파티션을 나눌 때까지 기다리십시오.
  2. 2 천 2 십억 개의 정확히 10 개의 파티션을 원하지는 않습니다.

파티션을 만들려면 범위별로 - 파티션 당 100,000 개의 행 또는 1 백만 개를 지정하십시오. cron-job을 추가하여 사용 된 최대 ID를 확인하고 필요할 경우 (아마도 하루에 한 번) 새 파티션을 만듭니다.

개인적으로는 필자가 필요할 때까지 개인적으로 맡겨 두었습니다. 어쩌면 나중에 필요할 때가 아니라는 생각이 들더라도 단일 파티션을 포괄적으로 사용할 수 있습니다.

1

WHERECHECK과 동일한 표현식이어야합니다. 즉, 쿼리 계획자는 user_id = 12345이 결론을 허용한다는 것을 깨닫지 못할 것입니다. user_id % 10 = 5. , 내가 좋아하는 것이라고 말했다

EXPLAIN SELECT * FROM mytable WHERE user_id = 12345 AND user_id % 10 = 5; 

시도하는 두 번째 Richard Huxton's answer에서 당신이 데이터 세트의 크기에 대한 자세한 정보를 얻을 때까지 조기 최적화를 피할 수있는 eidea 번째, 분할을 연기 할 수도있다. 포스트그레스는 다소 큰 테이블에서 매우 빠르다. 파티셔닝없이 꽤 오래 걸릴 것이다.