JSON 배열에서 요소를 찾기 위한 색인
다음과 같은 테이블이 있습니다.
CREATE TABLE tracks (id SERIAL, artists JSON);
INSERT INTO tracks (id, artists)
VALUES (1, '[{"name": "blink-182"}]');
INSERT INTO tracks (id, artists)
VALUES (2, '[{"name": "The Dirty Heads"}, {"name": "Louis Richards"}]');
이 질문과 관련이 없는 다른 열이 몇 개 있습니다.JSON으로 저장해야 하는 이유가 있습니다.
특정 아티스트 이름이 있는 트랙(정확한 일치)을 검색하려고 합니다.
이 쿼리를 사용하고 있습니다.
SELECT * FROM tracks
WHERE 'ARTIST NAME' IN
(SELECT value->>'name' FROM json_array_elements(artists))
예를들면
SELECT * FROM tracks
WHERE 'The Dirty Heads' IN
(SELECT value->>'name' FROM json_array_elements(artists))
그러나 이것은 전체 테이블 스캔을 수행하며 그리 빠르지 않습니다.GIN 인덱스를 작성하려고 함수로 시도했습니다.names_as_array(artists)
, 및 사용'ARTIST NAME' = ANY names_as_array(artists)
그러나 인덱스는 사용되지 않으며 쿼리는 실제로 상당히 느립니다.
jsonb
Postgres 9.4 이상
이진 JSON 데이터 유형은 인덱스 옵션을 크게 개선합니다.이제 GIN 인덱스를 사용할 수 있습니다.jsonb
직접 배열:
CREATE TABLE tracks (id serial, artists jsonb); -- !
CREATE INDEX tracks_artists_gin_idx ON tracks USING gin (artists);
어레이를 변환하기 위한 함수는 필요 없습니다.이는 쿼리를 지원합니다.
SELECT * FROM tracks WHERE artists @> '[{"name": "The Dirty Heads"}]';
@>
GIN 인덱스를 사용할 수 있는 "포함" 연산자가 됩니다(비포함).json
,오직.jsonb
!)
또는 인덱스에 대해 보다 전문적인 기본값이 아닌 GIN 연산자 클래스를 사용할 수 있습니다.
CREATE INDEX tracks_artists_gin_idx ON tracks
USING gin (artists jsonb_path_ops); -- !
같은 쿼리입니다.
현재의jsonb_path_ops
서포트하고 있는@>
교환입니다.하지만 일반적으로 훨씬 작고 빠릅니다.더 많은 인덱스 옵션이 있습니다. 자세한 내용은 매뉴얼을 참조하십시오.
컬럼의 경우] 컬럼artists
는 예시와 같이 이름만 보유하므로 값만 JSON 텍스트 프리미티브로 저장하는 것이 효율적이며 다중 키는 열 이름이 될 수 있습니다.
JSON 개체와 원시 유형의 차이점에 주의하십시오.
CREATE TABLE tracks (id serial, artistnames jsonb);
INSERT INTO tracks VALUES (2, '["The Dirty Heads", "Louis Richards"]');
CREATE INDEX tracks_artistnames_gin_idx ON tracks USING gin (artistnames);
쿼리:
SELECT * FROM tracks WHERE artistnames ? 'The Dirty Heads';
?
오브젝트 값에는 기능하지 않습니다.키와 배열 요소만 사용할 수 있습니다.
또는 다음 중 하나를 선택합니다.
CREATE INDEX tracks_artistnames_gin_idx ON tracks
USING gin (artistnames jsonb_path_ops);
쿼리:
SELECT * FROM tracks WHERE artistnames @> '"The Dirty Heads"'::jsonb;
이름이 매우 중복될 경우 더 효율적입니다.
json
Postgres 9.3 이상
이것은, 다음의 기능과 함께 동작합니다.
CREATE OR REPLACE FUNCTION json2arr(_j json, _key text)
RETURNS text[] LANGUAGE sql IMMUTABLE AS
'SELECT ARRAY(SELECT elem->>_key FROM json_array_elements(_j) elem)';
CREATE INDEX tracks_artists_gin_idx ON tracks
USING gin (json2arr(artists, 'name'));
그리고 이런 질문을 사용하세요.의 표현은WHERE
절은 인덱스의 절과 일치해야 합니다.
SELECT * FROM tracks
WHERE '{"The Dirty Heads"}'::text[] <@ (json2arr(artists, 'name'));
코멘트 피드백으로 갱신되었습니다.GIN 인덱스를 지원하려면 어레이 연산자를 사용해야 합니다.
이 경우 "contained by" 연산자는 다음과 같습니다.
기능 변동성에 관한 주의사항
기능을 선언할 수 있습니다.IMMUTABLE
라 할지라도json_array_elements()
하지 않다 그렇지 않았다.
대부분의.JSON
기존에는 기능만STABLE
,것은 아니다.IMMUTABLE
그것을 바꾸기 위해 해커 리스트에 대한 논의가 있었다.대부분은IMMUTABLE
지금 바로 확인:
SELECT p.proname, p.provolatile
FROM pg_proc p
JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE n.nspname = 'pg_catalog'
AND p.proname ~~* '%json%';
기능 인덱스는 다음과 같이만 작동합니다.IMMUTABLE
★★★★★★★★★★★★★★★★★★.
언급URL : https://stackoverflow.com/questions/18404055/index-for-finding-an-element-in-a-json-array
'source' 카테고리의 다른 글
한 프로젝트의 spring-config.xml을 다른 프로젝트의 spring-config.xml로 Import하려면 어떻게 해야 합니까? (0) | 2023.03.27 |
---|---|
$scope의 차이는 무엇입니까?$root 및 $rootScope? (0) | 2023.03.27 |
이름 또는 슬래그로 WooCommerce 제품 카테고리의 ID를 가져옵니다. (0) | 2023.03.27 |
여러 열을 여러 변수로 선택 (0) | 2023.03.27 |
WordPress에서 검색 쿼리와 일치하는 게시물을 프로그래밍 방식으로 가져오는 방법은 무엇입니까? (0) | 2023.03.27 |