색인을 추가하여 변경하기 위해 복사 할 약 100M 행의 테이블이 있습니다. 새 테이블을 만드는 데 걸리는 시간은별로 신경 쓰지 않지만 데이터를 삽입하기 전에 테이블을 변경하거나 데이터를 먼저 삽입 한 다음 인덱스를 추가하면 생성 된 인덱스가 더 효율적일까요?
답변:
데이터 삽입 후 색인을 생성하는 것이 더 효율적인 방법입니다 (일괄 가져 오기 전과 가져 오기 후에 색인을 다시 생성하는 것이 좋습니다).
구문 예제 (PostgreSQL 9.1, 느린 개발 시스템, 백만 행) :
CREATE TABLE test1(id serial, x integer);
INSERT INTO test1(id, x) SELECT x.id, x.id*100 FROM generate_series(1,1000000) AS x(id);
-- Time: 7816.561 ms
CREATE INDEX test1_x ON test1 (x);
-- Time: 4183.614 ms
인덱스 삽입 후 생성-약 12 초
CREATE TABLE test2(id serial, x integer);
CREATE INDEX test2_x ON test2 (x);
-- Time: 2.315 ms
INSERT INTO test2(id, x) SELECT x.id, x.id*100 FROM generate_series(1,1000000) AS x(id);
-- Time: 25399.460 ms
색인 생성 후 삽입-약 25.5 초 (2 배 이상 느림)
행을 추가 한 후 인덱스를 만드는 것이 좋습니다. 더 빠를뿐만 아니라 트리 밸런싱이 더 좋을 것입니다.
편집 "밸런싱"은 아마도 여기에서 최상의 용어 선택이 아닐 것입니다. b- 트리의 경우 정의에 따라 균형을 이룹니다. 그러나 이것이 b- 트리가 최적의 레이아웃을 가지고 있다는 것을 의미하지는 않습니다. 부모 내의 자식 노드 분포는 고르지 않을 수 있으며 (향후 업데이트에서 더 많은 비용이 발생 함) 업데이트 중에 균형 조정이 신중하게 수행되지 않으면 트리 깊이가 필요 이상으로 깊어 질 수 있습니다. 행이 추가 된 후 인덱스가 생성되면 더 나은 분포를 가질 가능성이 높습니다. 또한 디스크의 인덱스 페이지는 인덱스가 작성된 후 조각화가 적을 수 있습니다. 여기에 더 많은 정보
다음과 같은 이유로이 문제는 중요하지 않습니다.
O(n*log(N))
더 길어집니다 ( n
행이 추가 된 위치). 트리 발아 시간은 O(N*log(N))
이전 데이터와 새 데이터로 분할하면 O((X+n)*log(N))
간단히 변환 할 수 있으며이 O(X*log(N) + n*log(N))
형식으로 추가로 기다리는 시간을 볼 수 있습니다.n
새 행이 있음) O(log(N))
에 새 요소를 추가 한 후 트리 구조를 재생성하는 데 필요한 추가 시간을 삽입 할 수 있습니다 (인덱스가 이미 존재하고 새 행이 추가되었으므로 인덱스를 다시 생성하여 균형을 유지해야합니다). 구조물이 선정 인덱스 전원에게이다 [인덱스 요소] ). 당신이 마지막으로 당신이 다음 새 행을 다음 요약 추가 시간.O(log(P))
P
n
n * O(log(N))
O(n*log(N))