[pg-sql] Indeksy jsonb na operacje @> / jsonb_contains

0

Robię takie zapytanie w PostgreSQL:

EXPLAIN ANALYZE SELECT "k3_allegro_api_offer_prop".* FROM "k3_allegro_api_offer_prop" WHERE jsonb_contains("k3_allegro_api_offer_prop"."offer_publication", '{"status":"ACTIVE"}')

co jest równoznaczne z:

SELECT "k3_allegro_api_offer_prop".* FROM "k3_allegro_api_offer_prop" WHERE "k3_allegro_api_offer_prop"."offer_publication" @> '{"status":"ACTIVE"}'

Dostaję:

Seq Scan on k3_allegro_api_offer_prop (cost=0.00..1.04 rows=1 width=57) (actual time=0.018..0.022 rows=3 loops=1)
Filter: jsonb_contains(offer_publication, '{"status": "ACTIVE"}'::jsonb)

Jak widać, szukanie jest sekwencyjne nie po indeksie.

Pytanie: czy w ogóle można zrobić w PostgreSQLu indeks na taką operację @>, ponieważ indeks typu GIN nie działa dla operatorów ? ?& ?| @>, działa tylko na operatorach typu -> czyli liczbowych.

Robienie innego typu indeksu nic nie daje, próbowałem np.:

create index k3_allegro_api_offer_prop_pub_active on k3_allegro_api_offer_prop ( ( JSONB_CONTAINS(offer_publication, '{"status":"ACTIVE"}') ) );
create index k3_allegro_api_offer_prop_pub_active on k3_allegro_api_offer_prop ( ( JSONB_CONTAINS(offer_publication, '{"status":"ACTIVE"}')::boolean ) );

i nie korzysta z tych indeksów.

Oczywiście, mógłbym to zapisywac jakoś liczbowo zamiast tekstowo "ACTIVE", i pewnie tak ostatecznie zrobię, tylko się zastanawiam, czy dałoby się dla operatora @> zrobić indeks czy się nie da.... jestem trochę noobem jeżeli chodzi o jsonb w PostgreSQL...

0

A indeksowanie ścieżek jsonowych?

CREATE INDEX j_foobar ON k3_allegro_api_offer_prop ((offer_publication->'status'));  

I próba w zapytaniu:

select .... WHERE offer_publication->'status' = 'ACTIVE';

Pisane z palca, więc może się wywalić. Nie znam struktury tabel, ani struktury JSONa.

0

Tak oczywiście próbowałem ale to nie działa, operator -> działa na liczbach (integer):

   Schema   | Name |        Left arg type        |       Right arg type        |         Result type         |         Function          |                           Description
------------+------+-----------------------------+-----------------------------+-----------------------------+---------------------------+------------------------------------------------------------------
pg_catalog | ->   | jsonb                       | integer                     | jsonb                       | jsonb_array_element       | get jsonb array element

więc to nie ma prawa zadziałać, bo moja operacja to:

   Schema   | Name |        Left arg type        |       Right arg type        |         Result type         |         Function          |                           Description
------------+------+-----------------------------+-----------------------------+-----------------------------+---------------------------+------------------------------------------------------------------
pg_catalog | @>   | jsonb                       | jsonb                       | boolean                     | jsonb_contains            | contains

poza tym jak już to taki indeks trzeba chyba zrobić z GIN, czyli:

CREATE INDEX j_foobar ON k3_allegro_api_offer_prop USING gin ((offer_publication->'status'));

a GIN właśnie nie działa dla operatora @> i kilku innych....

Wszystkie operatory i odpowiadające im funkcje można zobaczyć w psql, robiąc:

$ \doS+

Edit:

Podobnie indeks

create index idx_test on k3_allegro_api_offer_prop ( (offer_publication @> '{"status":"ACTIVE"}') );

nic nie daje....

0

A jak zrobisz indeks zmieniając domyślny operator jsonb na jsonb_path_ops?
CREATE INDEX j_foobar ON k3_allegro_api_offer_prop USING gin (offer_publication jsonb_path_ops); ?

I w zapytaniu: @> '{"status":"ACTIVE"}')

0

Też nic nie zmienia, może też być tak, że PostgreSQL nie korzysta z tych indeksów bo jest za mało danych, tam są teraz tylko trzy rekordy. na razie nie mam czasu wypełniać tego danymi i się bawić, ale w ciągu najbliższych kilku dni sprawdzę.

PS wersja serwera Postgresql to 10.

1 użytkowników online, w tym zalogowanych: 0, gości: 1