2016-04-27 25 views
7

Diciamo che è necessario verificare se una colonna jsonb contiene un valore specifico corrispondente da una sottostringa in uno qualsiasi dei valori (non annidato, solo primo livello).Effettivamente la ricerca attraverso l'intero JSONB nidificato a 1 livello in Postgres

Come si ottimizza efficacemente una query per cercare l'intera colonna JSONB (ovvero ogni chiave) per un valore?

C'è qualche buona alternativa a fare ILIKE %val% su jsonb datatype casted to text?

jsonb_each_text(jsonb_column) ILIKE '%val%' 

A titolo di esempio si consideri questi dati:

SELECT '{"col1": "somevalue", "col2": 5.5, "col3": 2016-01-01, "col4": "othervalue", "col5": "yet_another_value"}'::JSONB 

Come si va su come ottimizzare una query come che quando hanno bisogno per cercare modello %val% nel record contenenti configurazione chiavi diverse per diverse righe in un colonna jsonb?

Sono consapevole del fatto che la ricerca con il segno % precedente e successivo è inefficiente, in modo da cercare un modo migliore, ma avendo difficoltà a trovarne uno. Inoltre, l'indicizzazione di tutti i campi in modo esplicito non è un'opzione in quanto variano per ogni tipo di record e creerebbe un enorme insieme di indici.

Esiste un'alternativa migliore per l'estrazione di ciascuna coppia di valori-chiave in testo e l'esecuzione di una ricerca ILIKE/POSIX?

+0

Questa potrebbe essere una soluzione migliore per dba.stackexchange.com, volevo solo ottenere vasto pubblico per questa materia. –

+2

['pg_trgm'] (http://www.postgresql.org/docs/current/static/pgtrgm.html) potrebbe essere l'opzione migliore (tipo ilike/posix) per questo dato che si sta ancora utilizzando il tipo di criteri di corrispondenza del modello nella colonna jsonb –

+0

@DmitrySavinkov potresti per favore elaborare? Credo che avrei ancora bisogno di decomprimere i dati JSON in righe separate. –

risposta

0

Se si sa che è necessario interrogare solo alcune chiavi conosciute, è possibile indicizzare semplicemente tali espressioni.

Questa è una troppo semplice, ma di sé esempio spiegando:

create table foo as SELECT '{"col1": "somevalue", "col2": 5.5, "col3": "2016-01-01", "col4": "othervalue", "col5": "yet_another_value"}'::JSONB as bar; 

create index pickfoo1 on foo ((bar #>> '{col1}')); 
create index pickfoo2 on foo ((bar #>> '{col2}')); 

Questa è l'idea di base, anche se non è utile per ILIKE querys, ma si può fare più cose (a seconda delle esigenze).

Per esempio: se è necessario solo caso di corrispondenza insensibile, sarebbe sufficiente a fare:

-- Create index over lowered value: 
create index pickfoo1 on foo (lower(bar #>> '{col1}')); 
create index pickfoo2 on foo (lower(bar #>> '{col2}')); 

-- Check that it matches: 
select * from foo where lower(bar #>> '{col1}') = lower('soMEvaLUe'); 

NOTA: Questo è solo un esempio: Se si esegue un spiegare al select precedente , vedrai che postgres esegue effettivamente una scansione sequenziale invece di utilizzare l'indice. Ma questo perché siamo test su una tabella con una singola riga, che non è il solito. Ma sono sicuro che si potrebbe provare con un tavolo più grande ;-)

Whith tavoli enormi, anche come query dovrebbero beneficiare dell'indice se la wildcard firt non appare all'inizio del stringa (ma non è una questione di jsonb ma una questione di indici btree).

Se è necessario ottimizzare le query come:

select * from foo where bar #>> '{col1}' ilike '%MEvaL%'; 

... allora si dovrebbe considerare l'utilizzo di GIN o GIST indici invece.

+0

Grazie per la risposta . Sfortunatamente, temo abbiate frainteso il punto di questa domanda. Sto chiedendo un modo più efficiente per cercare attraverso ENTIRE jsonb al primo livello piuttosto che disimballarlo. Per intero intendo ogni tasto. Questo è per un motore di ricerca. Non riesco a dire quali tasti abbia anche una particolare colonna. –

+0

Ecco perché ho iniziato a dire "Se lo sai ...". Se è necessario essere in grado di cercare con qualsiasi chiave (non prestabilita), sarebbe molto più difficile da ottimizzare. – bitifet

+0

Inoltre, oserei dire che cercare di analizzare JSON "in modo più efficiente" non risolverà il tuo problema. Prima di tutto perché in realtà jsonb non è internamente memorizzato come JSON PRECISAMENTE per essere più facilmente accessibile (non penso che tu possa farlo più velocemente delle funzioni di accesso nativo). – bitifet

Problemi correlati