jsonb
在Postgres 9.4+
使用新的二进制JSON数据类型jsonb
,Postgres 9.4引入了大大改进的索引选项。现在,您可以jsonb
直接在数组上具有GIN索引:
CREATE TABLE tracks (id serial, artists jsonb);
CREATE INDEX tracks_artists_gin_idx ON tracks USING gin (artists);
无需函数即可转换数组。这将支持查询:
SELECT * FROM tracks WHERE artists @> '[{"name": "The Dirty Heads"}]';
@>
是jsonb
可以使用GIN索引的新“包含”运算符。(json
仅适用于类型jsonb
!)
或者,您可以使用更专门的非默认GIN运算符类jsonb_path_ops
作为索引:
CREATE INDEX tracks_artists_gin_idx ON tracks
USING gin (artists jsonb_path_ops);
相同的查询。
当前jsonb_path_ops
仅支持@>
运营商。但是它通常更小,更快。手册中还有更多索引选项和详细信息。
如果 artists
所显示的例子仅持有的名字,这将是更有效地存储较小冗余JSON值开始:刚刚值作为文本基元和冗余键可以在列名。
注意JSON对象和原始类型之间的区别:
CREATE TABLE tracks (id serial, artistnames jsonb);
INSERT INTO tracks VALUES (2, '["The Dirty Heads", "Louis Richards"]');
CREATE INDEX tracks_artistnames_gin_idx ON tracks USING gin (artistnames);
查询:
SELECT * FROM tracks WHERE artistnames ? 'The Dirty Heads';
?
不适用于对象值,仅适用于键和数组元素。
或(如果经常重复使用名称,效率更高):
CREATE INDEX tracks_artistnames_gin_idx ON tracks
USING gin (artistnames jsonb_path_ops);
查询:
SELECT * FROM tracks WHERE artistnames @> '"The Dirty Heads"'::jsonb;
json
在Postgres 9.3+中
这应该与一个IMMUTABLE
功能一起工作:
CREATE OR REPLACE FUNCTION json2arr(_j json, _key text)
RETURNS text[] LANGUAGE sql IMMUTABLE AS
'SELECT ARRAY(SELECT elem->>_key FROM json_array_elements(_j) elem)';
创建此功能索引:
CREATE INDEX tracks_artists_gin_idx ON tracks
USING gin (json2arr(artists, 'name'));
并使用这样的查询。WHERE
子句中的表达式必须与索引中的表达式匹配:
SELECT * FROM tracks
WHERE '{"The Dirty Heads"}'::text[] <@ (json2arr(artists, 'name'));
更新了评论反馈。我们需要使用数组运算符来支持GIN索引。
该“包含由”运营商<@
在这种情况下。
功能波动注意事项
IMMUTABLE
即使json_array_elements()
不是,也可以声明函数。
大多数JSON
功能过去只是STABLE
,而没有IMMUTABLE
。黑客名单上进行了讨论,以改变这一点。IMMUTABLE
现在大多数。检查:
SELECT p.proname, p.provolatile
FROM pg_proc p
JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE n.nspname = 'pg_catalog'
AND p.proname ~~* '%json%';
功能索引仅与IMMUTABLE
功能一起使用。