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

[pg-sql] Indeksy jsonb na operacje @> / jsonb_contains
TR
  • Rejestracja:prawie 8 lat
  • Ostatnio:12 dni
  • Lokalizacja:700m n.p.m.
  • Postów:677
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...


DRY > SOLID (nie bierz tego zbyt poważnie)
edytowany 5x, ostatnio: TomRZ
Tasmanian Devil
Hej! Twój post prawdopodobnie zawiera niesformatowany kod. Użyj znaczników ``` aby oznaczyć, co jest kodem, będzie łatwiej czytać. (jestem botem, ta akcja została wykonana automatycznie, prawdopodobieństwo 0.99303)
YA
  • Rejestracja:około 10 lat
  • Ostatnio:około godziny
  • Postów:2372
0

A indeksowanie ścieżek jsonowych?

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

I próba w zapytaniu:

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

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

TR
  • Rejestracja:prawie 8 lat
  • Ostatnio:12 dni
  • Lokalizacja:700m n.p.m.
  • Postów:677
0

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

Kopiuj
   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:

Kopiuj
   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

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

nic nie daje....


DRY > SOLID (nie bierz tego zbyt poważnie)
edytowany 4x, ostatnio: TomRZ
YA
  • Rejestracja:około 10 lat
  • Ostatnio:około godziny
  • Postów:2372
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"}')

TR
  • Rejestracja:prawie 8 lat
  • Ostatnio:12 dni
  • Lokalizacja:700m n.p.m.
  • Postów:677
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.


DRY > SOLID (nie bierz tego zbyt poważnie)
edytowany 1x, ostatnio: TomRZ
Marcin.Miga
Dokładnie, jak jest mało danych to psql zawsze leci po PK

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.