색인 최대 행 크기 오류


12

array열에 대한 상한이 있습니까?

배열 필드에 삽입 할 때이 오류가 발생합니다-

PG::Error: ERROR:  index row size 3480 exceeds maximum 2712 for index "ix_data"

여기 내 테이블 정의가 있습니다-

create table test_array(id varchar(50), data text[]);

ALTER TABLE test_array ADD PRIMARY KEY (id);

CREATE INDEX ix_data ON test_array USING GIN (data);

조회를 수행하기 때문에 배열 필드에 색인이 필요합니다.


Scott Snyder의 관련 블로그 게시물data 에서 시연 한 것과 같은 태그 목록 이 포함되어 있을 수 있습니까? 이 경우 더 나은 솔루션이있을 수 있습니다.
Erwin Brandstetter

user310525, 나는 dba.se에서 이것이 더 좋을 것이라고 Erwin의 제안을 두 번째로하고 싶습니다. 계정을 만들고 기꺼이 마이그레이션하도록 플래그 지정 하시겠습니까?
잭 topanswers.xyz 시도라고

답변:


14

문제

다음은 pgsql.general에서 논의 된 매우 유사한 사례 입니다. b-tree 인덱스의 제한 사항에 관한 것이지만 GIN 인덱스는 내부적 으로 키에 b-tree 인덱스를 사용 하므로 일반 b- 트리 의 항목 크기 대신 크기에 대해 동일한 제한을 갖기 때문에 모두 동일합니다. 인덱스).

GIN 인덱스 구현에 대한 매뉴얼을 인용하십시오 .

내부적으로 GIN 인덱스에는 키에 대해 구성된 B- 트리 인덱스가 포함되어 있습니다. 여기서 각 키는 하나 이상의 인덱싱 된 항목의 요소입니다.

어느 쪽이든, 열에서 하나 이상의 배열 요소data 가 너무 커서 색인을 생성 할 수 없습니다. 이것이 단수의 괴물 값이거나 어떤 종류의 사고 일 경우 값을 자르고 끝낼 수 있습니다.

다음 데모의 목적을 위해 다른 방법으로 가정합니다. 배열에 긴 텍스트 값이 많이 있습니다.

간단한 솔루션

배열의 요소를 해시 값data 에 따라 바꿀 수 있습니다 . 동일한 해시 함수를 통해 조회 값을 보냅니다. 물론 어딘가에 원본을 저장하고 싶을 수도 있습니다. 그것으로, 우리는 거의 두 번째 변형에 도착합니다 ...

고급 솔루션

serial대리 기본 키 (효과적으로 근본적인 해시 값)로 열 이있는 배열 요소에 대한 룩업 테이블을 만들 수 있습니다. 관련 요소 값이 고유하지 않은 경우 더욱 흥미 롭습니다.

CREATE TABLE elem (
  elem_id serial NOT NULL PRIMARY KEY
, elem    text UNIQUE NOT NULL
);

우리가보고 싶은 때문에 elem- 우리는 인덱스 추가 하지만 식에 인덱스를 전용으로, 이번에 처음 10 개 문자 긴 텍스트의 색입니다. 대부분의 경우 검색 범위를 하나 또는 몇 개의 검색 범위로 좁히기에 충분합니다. 데이터 배포에 맞게 크기를 조정하십시오. 또는보다 정교한 해시 함수를 사용하십시오.

CREATE INDEX elem_elem_left10_idx ON elem(left(elem,10));

그러면 열 data이 유형이 int[]됩니다. 나는 테이블의 이름을 바꾸고 귀하의 예에서 data불길한 varchar(50)것을 제거했습니다 .

CREATE TEMP TABLE data(
  data_id serial PRIMARY KEY
, data int[]
);

의 각 배열 요소는을 data나타냅니다 elem.elem_id. 이 시점에서 배열 열을 n : m 테이블로 바꾸어 스키마를 정규화하고 Postgres가 참조 무결성을 강화하도록 고려할 수 있습니다. 인덱싱 및 일반 처리가 쉬워집니다 ...

그러나 성능상의 이유로 int[]GIN 인덱스와 결합 된 컬럼이 우수 할 수 있습니다. 스토리지 크기가 훨씬 작습니다. 이 경우 GIN 인덱스가 필요합니다.

CREATE INDEX data_data_gin_idx ON data USING GIN (data);

이제 GIN 인덱스의 각 (= 배열 요소)는 long integer대신입니다 text. 색인은 몇 자릿수 씩 작아지며 결과적으로 검색 속도 가 훨씬 빨라집니다.

단점 : 실제로 검색을 수행하기 전에 elem_id테이블에서 를 찾아야 합니다 elem. 새로 도입 된 기능 색인을 사용하면 elem_elem_left10_idx훨씬 빠릅니다.

하나의 간단한 쿼리로 모든 작업을 수행 할 수 있습니다 .

SELECT d.*, e.*
FROM   elem e
JOIN   data d ON ARRAY[e.elem_id] <@ d.data
WHERE  left(e.elem, 10) = left('word1234word', 10) -- match index condition
AND    e.elem = 'word1234word';  -- need to recheck, functional index is lossy

intarray추가 연산자 및 연산자 클래스를 제공 하는 확장 기능에 관심이있을 수 있습니다 .

sqlfiddle에서 완벽하게 기능하는 라이브 데모.


2

필드가 ix_data아닌 index에 오류가 text[]있습니다. 특정 인덱스 유형에서 행의 최대 크기는 2712바이트 로 제한됩니다 . 색인을 삭제하고 다시 삽입을 시도하면 효과가 있습니다. 더 큰 필드를 인덱싱해야하는 경우 postgres의 전체 텍스트 인덱싱 기능을 살펴볼 수 있습니다.


2

나는 이것을 PostGIS 지리 칼럼에서 얻었습니다. 실수로 색인을 잘못 작성했기 때문입니다. 이러한 색인을 작성할 때 USING GIST 매개 변수를 포함시켜야합니다.


고마워-그게 다야! 와우, 지금까지 가져 왔습니다. 시간을 절약했을 수 있습니다. 특히 GiST가 기본적으로 사용되었다고 생각했지만 실수로 b-tree를 사용하려고합니다.
Jonas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.