2013-11-23 2 views
0

나는 이것을 약 4 번 보았고, 여전히 이러한 결과에 당황 스럽다. 왜 내 날짜 차원 테이블이 쓸모 없습니까? (PostgreSQL storage에 대한 혼란 ...)

DROP TABLE IF EXISTS just_dates CASCADE; 
DROP TABLE IF EXISTS just_date_ids CASCADE; 

CREATE TABLE just_dates AS 
    SELECT a_date AS some_date 
    FROM some_table; 

/* ==> [ SELECT 769411 ] */ 

CREATE TABLE just_date_ids AS 
    SELECT d.id 
    FROM just_dates jd 
    INNER JOIN dim_calendar d 
    ON d.day_id = jd.some_date; 

/* ==> [ SELECT 769411 ] */ 

ALTER TABLE just_date_ids ADD CONSTRAINT jdfk FOREIGN KEY (id) REFERENCES dim_calendar (id); 

혼란 - -

테스트
-- Some output omitted 

DROP TABLE IF EXISTS dim_calendar CASCADE; 

CREATE TABLE dim_calendar (
    id SMALLSERIAL PRIMARY KEY, 
    day_id DATE NOT NULL, 
    year SMALLINT NOT NULL, -- 2000 to 2024 
    month SMALLINT NOT NULL, -- 1 to 12 
    day SMALLINT NOT NULL, -- 1 to 31 
    quarter SMALLINT NOT NULL, -- 1 to 4 
    day_of_week SMALLINT NOT NULL, -- 0() to 6() 
    day_of_year SMALLINT NOT NULL, -- 1 to 366 
    week_of_year SMALLINT NOT NULL, -- 1 to 53 
    CONSTRAINT con_month CHECK (month >= 1 AND month <= 31), 
    CONSTRAINT con_day_of_year CHECK (day_of_year >= 1 AND day_of_year <= 366), -- 366 allows for leap years 
    CONSTRAINT con_week_of_year CHECK (week_of_year >= 1 AND week_of_year <= 53), 
    UNIQUE(day_id) 
); 

INSERT INTO dim_calendar (day_id, year, month, day, quarter, day_of_week, day_of_year, week_of_year) (
    SELECT ts, 
    EXTRACT(YEAR FROM ts), 
    EXTRACT(MONTH FROM ts), 
    EXTRACT(DAY FROM ts), 
    EXTRACT(QUARTER FROM ts), 
    EXTRACT(DOW FROM ts), 
    EXTRACT(DOY FROM ts), 
    EXTRACT(WEEK FROM ts) 
    FROM generate_series('2000-01-01'::timestamp, '2024-01-01', '1day'::interval) AS t(ts) 
); 

/* ==> [ INSERT 0 8767 ] */ 

테이블 -

날짜 차원 테이블 (나는 원래 here을 게시하는) 다음에서보세요
pocket=# SELECT pg_size_pretty(pg_relation_size('dim_calendar')); 

pg_size_pretty 
---------------- 
448 kB 
(1 row) 

pocket=# SELECT pg_size_pretty(pg_relation_size('just_dates')); 
pg_size_pretty 
---------------- 
27 MB 
(1 row) 

pocket=# SELECT pg_size_pretty(pg_relation_size('just_date_ids')); 
pg_size_pretty 
---------------- 
27 MB 
(1 row) 

왜 작은 테이블이 여러 개의 날짜로 구성된 테이블과 같은 크기로 구성된 테이블입니까? 그리고 나는 이전에 dim_calendar.id이 정상인 SERIAL 일 때 27MB과 같은 결과를 주었다고 언급해야합니다. 또한, 더 중요한

- 은 왜 하나의 SMALLINT 필드 769411 기록이있는 테이블은 > 32bytes/record입니다 27MB의 크기를해야합니까 ???

P. 예, 수십억 개 (또는 최소 수억 개)의 레코드가 필요하며 가능하면 성능 및 공간 최적화를 추가하려고합니다.

편집, 함께 할 수있는 뭔가가 너무 거기에 던지는 수

-

pocket=# select count(id) from just_date_ids group by id; 
count 
-------- 
409752 
359659 
(2 rows) 
+0

당신이 공간 필요 조건을 최소로하고 싶다면 ** 왜 ** 당신이 dim_calendar에 모든 파생 된 필드를 저장하고 있는가? – wildplasser

+0

결국 나는 할 것이다. 요점 이외의 종류. 이것은 링크 된 페이지의 기사에서 작성된 치수 테이블을 기반으로 한 테스트에 불과합니다. 결과가 내가 예상했던대로가 아닌 이유에 대해서만 관심이 있습니다. – Ryan

+0

그리고 실제로 다른 테이블과 관련하여 추가 7 열의 추가 공간은 오히려 (완전히, 전혀) 중요하지 않습니다. – Ryan

답변

3

표에서 하나 또는 두 개의 열이있는, 크기의 가장 큰 부분은 항상 튜플이다 머리글.

여기를 보시려면 http://www.postgresql.org/docs/current/interactive/storage-page-layout.html, 데이터 저장 방법을 설명하십시오. 위 페이지에서 귀하의 질문과 가장 관련이있는 부분을 인용합니다.

모든 테이블 행은 같은 방식으로 구성되어 있습니다. 고정 크기 헤더 (대부분의 시스템에서 23 바이트 차지), 선택적 널 비트 맵, 선택적 오브젝트 ID 필드 및 사용자 데이터가 뒤 따른다.

이 대부분 왜 하나 SMALLINT 필드 769411 개 레코드가있는 테이블이> 32 바이트/기록이다 27메가바이트의 크기를 가지고 않습니다 질문

을 설명 ???

질문의 다른 부분은 postgres 데이터의 바이트 정렬과 관련이 있습니다. 작은 값은 2 바이트 오프셋으로 정렬되지만 int (물론 날짜 ... 은 모두 int4입니다.)는 4 바이트 오프셋으로 정렬됩니다. 따라서 테이블 열이 제거되는 순서가 중요한 역할을합니다.

smallint, date, smallint가있는 테이블을 사용하면 사용자 데이터에 대해 12 바이트 (오버 헤드는 계산하지 않음)가 필요하며 smallint, smallint, date는 8 바이트 만 필요합니다.위대한 (그리고 놀랍게도 받아 들여지지 않은) 대답을 여기에서 보아라. Calculating and saving space in PostgreSQL

관련 문제