Ytelse og spørringsoptimalisering i PostgreSQL · leksjon

JSONB-operatorer og containment-spørringer

Bruk containment- og path-operatorene som GIN-indekser faktisk kan akselerere.

Leksjon 1 av 413 trinn

JSONB-operatorer og containment-spørringer er en gratis leksjon i Ytelse og spørringsoptimalisering i PostgreSQL på CoddyKit. Dette er leksjon 1 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Ytelse og spørringsoptimalisering i PostgreSQL, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Ytelse og spørringsoptimalisering i PostgreSQL inneholder totalt 4 leksjoner.

Hvorfor valg av operator avgjør om indeksen brukes

I PostgreSQL kan en kolonne av typen jsonb søkes på mange forskjellige måter, men ikke alle operatorer kan bruke en indeks. Ytelsen handler nesten utelukkende om å velge operatorer som en GIN-indeks kan akselerere.

  • En GIN-indeks (Generalized Inverted Index) lagrer nøklene og verdiene i JSON-dokumentene, slik at oppslag kan hoppe over hele tabellen.
  • De to viktigste operatorene er inneslutning (@>) og nøkkeleksistens (?, ?|, ?&).

Denne leksjonen lærer Dem nøyaktig hvilke operatorer dette er, og hvordan De skriver spørringer som er indeksvennlige.

Inneslutningsoperatoren @>

Inneslutningsoperatoren @> spør: inneholder venstre JSONB høyre JSONB? Høyresiden er et fragment, og Postgres kontrollerer at hver nøkkel/verdi i fragmentet finnes i dokumentet til venstre.

  • '{"a":1,"b":2}' @> '{"a":1}' er true.
  • '{"a":1}' @> '{"a":1,"b":2}' er false (høyresiden inneholder mer).

Dette er arbeidshesten for filtrering av rader: WHERE data @> '{"status":"active"}' finner alle rader der JSON-en inneholder dette paret.

SELECT '{"a":1,"b":2}'::jsonb @> '{"a":1}'::jsonb AS contains_a,
       '{"a":1}'::jsonb @> '{"a":1,"b":2}'::jsonb AS contains_both;

Opprette en GIN-indeks for inneslutning

En vanlig GIN-indeks på en jsonb-kolonne støtter både inneslutningsoperatorer og operatorer for nøkkeleksistens. Dette er indeksen De bør prøve først.

  • Den standardiserte operator-klassen jsonb_ops indekserer hver nøkkel og verdi.
  • Den akselererer @>, ?, ?| og ?&.

Opprett den én gang, så blir inneslutningsfiltre som tidligere skannet hele tabellen, til punktgrafikkindeksskanninger.

CREATE INDEX idx_events_data
  ON events
  USING GIN (data);

Inneslutningsfiltre i WHERE

Når GIN-indeksen finnes, skriver De filteret som en inneslutningskontroll slik at planleggeren kan bruke den. Det fungerer også å matche et nøstet fragment, fordi inneslutning er rekursiv.

  • Treff på øverste nivå: data @> '{"status":"active"}'.
  • Nøstet treff: data @> '{"user":{"plan":"pro"}}'.

Legg merke til at De sender et JSON-objektliteral på høyresiden, ikke en kolonnereferanse eller et funksjonskall. Det er denne literalformen som gjør spørringen egnet for indeksbruk.

SELECT id, created_at
FROM events
WHERE data @> '{"user":{"plan":"pro"}}'
ORDER BY created_at DESC
LIMIT 50;

Operatorer for nøkkeleksistens ? ?| ?&

Noen ganger er De bare opptatt av om en nøkkel finnes, uavhengig av verdien. Eksistensoperatorene håndterer dette og akselereres også av GIN.

  • data ? 'email' – true hvis nøkkelen email finnes på øverste nivå.
  • data ?| array['phone','email'] – true hvis minst én av disse nøklene finnes.
  • data ?& array['phone','email'] – true hvis alle disse nøklene finnes.

Viktig: ? kontrollerer bare nøkler på øverste nivå, og for tabeller kontrollerer den om strengen er et element.

SELECT '{"email":"x@y.z","phone":"123"}'::jsonb ? 'email'        AS has_email,
       '{"email":"x@y.z"}'::jsonb ?| array['phone','email']      AS has_any,
       '{"email":"x@y.z"}'::jsonb ?& array['phone','email']      AS has_all;

Fellen: baneuttrekksoperatorene -> og ->>

Uttrekksoperatorene ser praktiske ut, men akselereres ikke av en standard GIN-indeks:

  • data -> 'status' returnerer verdien som jsonb.
  • data ->> 'status' returnerer verdien som text.

En spørring som WHERE data ->> 'status' = 'active' tvinger frem en sekvensiell skanning med en vanlig GIN-indeks, fordi indeksen ikke indekserer sammenligninger av uttrukne skalarer. Foretrekk i stedet inneslutningsformen data @> '{"status":"active"}'.

-- Slow on a plain GIN index (seq scan):
SELECT * FROM events WHERE data ->> 'status' = 'active';

-- Fast equivalent (uses GIN):
SELECT * FROM events WHERE data @> '{"status":"active"}';

Redde ->> med en uttrykksindeks

Hvis De faktisk trenger område- eller mønstersammenligninger på ett felt, er en B-tre-uttrykksindeks på den uttrukne teksten det riktige verktøyet – ikke GIN.

  • Indekser nøyaktig uttrykket De spør etter.
  • Da kan sammenligninger som =, <, > og BETWEEN bruke den.

Spørringens uttrykk må samsvare med det indekserte uttrykket tegn for tegn, ellers ignorerer planleggeren indeksen.

CREATE INDEX idx_events_status
  ON events ((data ->> 'status'));

-- Now this can use the B-tree index:
SELECT * FROM events WHERE (data ->> 'status') = 'active';

jsonb_path_ops: mindre, raskere, bare for inneslutning

Den alternative operator-klassen jsonb_path_ops indekserer hashede baner fra rot til blad i stedet for hver enkelt nøkkel.

  • Den gir en mindre indeks og er vanligvis raskere for @>-spørringer.
  • Avveiningen er at den støtter bare inneslutning (@>), ikke eksistensoperatorene ?, ?| og ?&.

Velg jsonb_path_ops når arbeidsmengden Deres hovedsakelig består av inneslutningsfiltrering, og De aldri trenger søk etter nøkkeleksistens.

CREATE INDEX idx_events_data_path
  ON events
  USING GIN (data jsonb_path_ops);

Inneslutning mot tabeller

Inneslutning fungerer også inne i JSON-tabeller, noe som gjør den ideell for data med tagger. For å spørre «inneholder denne tabellen en verdi?» pakker De verdien inn i en tabell på høyresiden.

  • '["a","b","c"]' @> '["b"]' er true.
  • For et dokument med tagger: data @> '{"tags":["urgent"]}' finner rader der tags-tabellen inneholder urgent.

Dette er fullt ut egnet for indeksbruk med en GIN-indeks, slik at filtrering på tagger skalerer godt.

SELECT '["a","b","c"]'::jsonb @> '["b"]'::jsonb   AS has_b,
       '{"tags":["urgent","billing"]}'::jsonb
         @> '{"tags":["urgent"]}'::jsonb            AS is_urgent;

Bekrefte med EXPLAIN

Ikke anta at indeksen brukes – bekreft det. Kjør EXPLAIN og se etter en Bitmap Index Scan på GIN-indeksen. En Seq Scan betyr at operatoren eller uttrykket hindret indeksbruk.

  • Godt tegn: Bitmap Index Scan on idx_events_data.
  • Dårlig tegn: Seq Scan on events med et JSON-filter.

Bruk EXPLAIN (ANALYZE, BUFFERS) for også å se faktisk tidsbruk og hvor mange sider som ble lest.

EXPLAIN (ANALYZE, BUFFERS)
SELECT id FROM events
WHERE data @> '{"status":"active"}';

Slik henger det sammen: en beslutningsregel

Bruk denne enkle regelen når De skriver et JSONB-filter:

  • Treff på nøkkel/verdi eller et nøstet fragment? Bruk @> med en GIN-indeks.
  • Kontrollerer De bare om en nøkkel finnes? Bruk ?/?|/?& med standardklassen jsonb_ops i GIN.
  • Arbeidsmengde som bare bruker inneslutning, og ønske om minst mulig indeks? Bruk jsonb_path_ops i GIN.
  • Område eller mønster på ett skalarfelt? Bruk en B-tre-uttrykksindeks på ->>.

Unngå likhetsfiltre med ->> uten en tilsvarende uttrykksindeks – de utløser sekvensielle skanninger.

Hurtigsjekk

De har en standard GIN-indeks med jsonb_ops på events.data. Hvilken WHERE-betingelse kan bruke denne indeksen?

Oppsummering

De har lært hvilke JSONB-operatorer som faktisk drar nytte av indeksering:

  • @> (inneslutning) er det primære GIN-akselererte filteret, også for nøstede objekter og tabeller.
  • ?, ?| og ?& (nøkkeleksistens) akselereres av GIN, men bare med standardklassen jsonb_ops, og de kontrollerer nøkler på øverste nivå.
  • jsonb_path_ops gir en mindre og raskere indeks som bare støtter inneslutning.
  • -> og ->>-filtre for uttrekking bruker IKKE en vanlig GIN-indeks; skriv dem om til @>, eller legg til en B-tre-uttrykksindeks.
  • Bekreft alltid med EXPLAIN at De får en Bitmap Index Scan, ikke en Seq Scan.
Gratis å komme i gang

Lær deg SQL med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
22
Leksjoner
88

Ofte stilte spørsmål

Er leksjonen «JSONB-operatorer og containment-spørringer» gratis?

Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Ytelse og spørringsoptimalisering i PostgreSQL, inkludert «JSONB-operatorer og containment-spørringer», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i Ytelse og spørringsoptimalisering i PostgreSQL inneholder totalt 4 leksjoner.

Hva lærer jeg i «JSONB-operatorer og containment-spørringer»?

Bruk containment- og path-operatorene som GIN-indekser faktisk kan akselerere. Du øver på Ytelse og spørringsoptimalisering i PostgreSQL med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med Ytelse og spørringsoptimalisering i PostgreSQL?

Ingen tidligere erfaring er nødvendig. Ytelse og spørringsoptimalisering i PostgreSQL på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 1 av 4.

Hvor lang tid tar leksjonen «JSONB-operatorer og containment-spørringer»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne Ytelse og spørringsoptimalisering i PostgreSQL-leksjonen?

Ja. Alle Ytelse og spørringsoptimalisering i PostgreSQL-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. JSONB-operatorer og containment-spørringer
  2. GIN- kontra uttrykksindekser på JSONB
  3. Spørre JSONB med JSONPath
  4. Når JSONB bør normaliseres ut
← Tilbake til Ytelse og spørringsoptimalisering i PostgreSQL