Tindakan langsung pertama adalah membuat kueri yang Anda miliki sedikit lebih cepat:
SELECT *
FROM parents p
WHERE EXISTS (
SELECT FROM jsonb_array_elements(p.children) c
WHERE (c->>'age')::int BETWEEN 10 AND 12
);
EXISTS
semi-join menghindari duplikasi baris dalam tabel perantara ketika beberapa objek array cocok - dan kebutuhan untuk DISTINCT ON
dalam kueri luar. Tapi itu hanya sedikit lebih cepat.
Masalah intinya adalah Anda ingin menguji rentang nilai integer , sedangkan jsonb
operator
tidak menyediakan fungsi tersebut.
Ada berbagai cara di sekitar ini. Tidak mengetahui semua ini, berikut adalah solusi "pintar" yang menyelesaikan contoh yang diberikan. Triknya adalah membagi rentang ke nilai yang berbeda dan menggunakan jsonb
operator penahanan @>
:
SELECT *
FROM parents p
WHERE (p.children @> '[{"age": 10}]'
OR p.children @> '[{"age": 11}]'
OR p.children @> '[{"age": 12}]');
Didukung oleh jsonb_path_ops
Indeks GIN:
CREATE INDEX parents_children_gin_idx ON parents USING gin (children jsonb_path_ops);
Tetapi jika rentang Anda mencakup lebih dari satu tangan penuh nilai integer, Anda memerlukan sesuatu yang lebih umum. Seperti selalu , solusi terbaik tergantung pada situasi lengkap:Distribusi data, frekuensi nilai, rentang tipikal dalam kueri, kemungkinan nilai NULL?, ukuran baris, pola baca/tulis, apakah setiap jsonb
nilai memiliki satu atau lebih age
matching yang cocok kunci? ...
Jawaban terkait dengan indeks khusus dan sangat cepat:
Terkait: