설명서 에서이 질문에 대한 명확한 대답을 찾을 수 없습니다. 열이 배열 유형 인 경우 입력 한 모든 값이 개별적으로 색인화됩니까?
하나의 int[]
열이 있는 간단한 테이블을 만들고 고유 한 인덱스를 넣었습니다. 동일한 int 배열을 추가 할 수 없다는 것을 알았습니다. 따라서 색인은 각 항목의 색인이 아닌 배열 항목의 합성이라고 생각하게됩니다.
INSERT INTO "Test"."Test" VALUES ('{10, 15, 20}');
INSERT INTO "Test"."Test" VALUES ('{10, 20, 30}');
SELECT * FROM "Test"."Test" WHERE 20 = ANY ("Column1");
색인이이 쿼리에 도움이됩니까?
답변
예, 배열을 인덱싱 할 수 있지만 배열 연산자 와 GIN- 인덱스 유형 을 사용해야합니다 .
예:
CREATE TABLE "Test"("Column1" int[]);
INSERT INTO "Test" VALUES ('{10, 15, 20}');
INSERT INTO "Test" VALUES ('{10, 20, 30}');
CREATE INDEX idx_test on "Test" USING GIN ("Column1");
-- To enforce index usage because we have only 2 records for this test...
SET enable_seqscan TO off;
EXPLAIN ANALYZE
SELECT * FROM "Test" WHERE "Column1" @> ARRAY[20];
결과:
Bitmap Heap Scan on "Test" (cost=4.26..8.27 rows=1 width=32) (actual time=0.014..0.015 rows=2 loops=1)
Recheck Cond: ("Column1" @> '{20}'::integer[])
-> Bitmap Index Scan on idx_test (cost=0.00..4.26 rows=1 width=0) (actual time=0.009..0.009 rows=2 loops=1)
Index Cond: ("Column1" @> '{20}'::integer[])
Total runtime: 0.062 ms
노트
많은 경우 gin__int_ops 옵션이 필요한 것으로 보입니다.
create index <index_name> on <table_name> using GIN (<column> gin__int_ops)
gin__int_ops 옵션없이 && 및 @> 연산자와 함께 작동하는 경우를 아직 보지 못했습니다.
답변
@Tregoreg는 제안 된 현상금에 대한 의견에서 질문 을 제기했습니다 .
현재 답변이 작동하지 않습니다. 배열 유형 컬럼에서 GIN 인덱스를 사용하면 ANY () 연산자의 성능이 향상되지 않습니다. 실제로 해결책이 없습니까?
@ 프랭크의 허용 대답은 사용 할 것을 배열 연산자 인, 아직 정확한 포스트 그레스 (11)에 대한 매뉴얼 :
… PostgreSQL의 표준 배포에는 다음 연산자를 사용하여 인덱스 된 쿼리를 지원하는 배열에 대한 GIN 연산자 클래스가 포함되어 있습니다.
<@ @> = &&
표준 배포판의 GIN 인덱스에 대한 내장 연산자 클래스의 전체 목록은 다음과 같습니다.
Postgres에서 색인은 데이터 유형이나 함수 또는 다른 것이 아닌 연산자 (특정 유형에 대해 구현 됨)에 바인딩됩니다 . 그것은 Postgres의 원래 버클리 디자인의 유산 이며 지금은 변경하기가 매우 어렵습니다. 그리고 그것은 일반적으로 잘 작동합니다. Tom Lane이 pgsql-bugs에 대한 주석을 작성했습니다.
(와 같은 ) 일부 PostGis 함수는ST_DWithin()
이 원칙을 위반하는 것으로 보이지만 그렇지 않습니다. 이러한 함수는 각 연산자 를 사용하기 위해 내부적으로 다시 작성 됩니다.
색인화 된 표현식은 연산자 의 왼쪽 에 있어야합니다 . 위의 모든 것을 포함하여 대부분의 연산자의 경우 인덱스 플래너를 정의한대로 오른쪽에 배치하면 쿼리 플래너가 피연산자를 뒤집어이를 달성 할 수 있습니다 COMMUTATOR
. ANY
구조체는 다양한 연산자 병용 조작자 자체 없다 할 수있다. 배열 요소constant = ANY (array_expression)
에서 =
연산자를 지원하는 인덱스로만 사용될 경우에 대한 정류자가 필요합니다 . GIN 지수가 부족합니다.= ANY()
Postgres는 현재 GIN- 인덱싱 가능한 표현을 도출 할만큼 똑똑하지 않습니다. 우선, constant = ANY (array_expression)
이다 완전히 동일하지 에 array_expression @> ARRAY[constant]
. NULL 요소 가 관련된 경우 배열 연산자는 오류를 반환 하지만 ANY
구문은 양쪽에서 NULL을 처리 할 수 있습니다. 그리고 데이터 유형 불일치에 대해 다른 결과가 있습니다.
관련 답변 :
옆으로
값이 없는 integer
배열 ( int4
, not int2
또는 int8
)을 사용 하는 동안 NULL
(예를 들어 암시하는 것처럼) intarray
전문적이고 빠른 연산자와 색인 지원을 제공 하는 추가 모듈을 고려하십시오 . 보다:
UNIQUE
대답하지 않은 질문 의 제약에 관해서는 : 그것은 전체 배열 값 에 대해 btree 인덱스로 구현되었으며 (예상 한 것처럼) 요소 검색에 전혀 도움이되지 않습니다 . 세부:
답변
이제 개별 배열 요소를 색인화 할 수 있습니다. 예를 들면 다음과 같습니다.
CREATE TABLE test (foo int[]);
INSERT INTO test VALUES ('{1,2,3}');
INSERT INTO test VALUES ('{4,5,6}');
CREATE INDEX test_index on test ((foo[1]));
SET enable_seqscan TO off;
EXPLAIN ANALYZE SELECT * from test WHERE foo[1]=1;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------
Index Scan using test_index on test (cost=0.00..8.27 rows=1 width=32) (actual time=0.070..0.071 rows=1 loops=1)
Index Cond: (foo[1] = 1)
Total runtime: 0.112 ms
(3 rows)
이것은 적어도 Postgres 9.2.1에서 작동합니다. 각 배열 인덱스에 대해 별도의 인덱스를 작성해야합니다.이 예제에서는 첫 번째 요소 만 인덱싱했습니다.