Just for fun, sample data..
CREATE TABLE datasets
AS
SELECT
gs.rowid,
jsonb_agg(
jsonb_build_object('PARAM'||keys.id, md5(gs.rowid::text))
) AS jsondata,
md5(gs.rowid::text) AS myparam
FROM generate_series(1,53696) AS gs(rowid)
CROSS JOIN LATERAL (
SELECT gs.rowid, trunc(random()*3)::int+1 AS elemcnt
) AS r1
CROSS JOIN LATERAL (
SELECT gs.rowid, elemcnt, trunc(random()*290)::int+10 AS keycnt
) AS r2
CROSS JOIN LATERAL generate_series(1,r1.elemcnt) AS elems(id)
CROSS JOIN LATERAL generate_series(1,r2.keycnt) AS keys(id)
GROUP BY gs.rowid;
Then we do...
SELECT rowid FROM datasets WHERE myparam = '5ecc613150de01b7e6824594426f24f4';
QUERY PLAN
-------------------------------------------------------------------------------------------------------
Seq Scan on datasets (cost=0.00..5975.20 rows=1 width=4) (actual time=18.760..19.527 rows=1 loops=1)
Filter: (myparam = '5ecc613150de01b7e6824594426f24f4'::text)
Rows Removed by Filter: 53695
Planning time: 0.089 ms
Execution time: 19.557 ms
(5 rows)
SELECT rowid, jsondata->0->'PARAM1' FROM datasets WHERE jsondata->0->>'PARAM1' = '5ecc613150de01b7e6824594426f24f4';
QUERY PLAN
-------------------------------------------------------------------------------------------------------------
Seq Scan on datasets (cost=0.00..6245.02 rows=268 width=684) (actual time=761.555..809.514 rows=1 loops=1)
Filter: (((jsondata -> 0) ->> 'PARAM1'::text) = '5ecc613150de01b7e6824594426f24f4'::text)
Rows Removed by Filter: 53695
Planning time: 0.078 ms
Execution time: 809.545 ms
(5 rows)
So the overhead on the whole operation is 41.3x Now just add a gist index.
Adding an index
CREATE INDEX ON datasets USING gin(jsondata jsonb_path_ops);
SELECT rowid, jsondata->0->'PARAM1' FROM datasets WHERE jsondata @> '[{"PARAM1":"5ecc613150de01b7e6824594426f24f4"}]'::jsonb;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on datasets (cost=24.42..225.02 rows=54 width=684) (actual time=0.405..0.408 rows=1 loops=1)
Recheck Cond: (jsondata @> '[{"PARAM1": "5ecc613150de01b7e6824594426f24f4"}]'::jsonb)
Heap Blocks: exact=1
-> Bitmap Index Scan on datasets_jsondata_idx (cost=0.00..24.40 rows=54 width=0) (actual time=0.082..0.082 rows=1 loops=1)
Index Cond: (jsondata @> '[{"PARAM1": "5ecc613150de01b7e6824594426f24f4"}]'::jsonb)
Planning time: 0.184 ms
Execution time: 0.460 ms
(7 rows)
And, now we're 42x faster than with the seq scan on the "plain column".
I'm not sure where your question is though. TOAST adds over head. So does indexing into binary JSON and converting from the JSONB type to text.