我对这个没有任何经验,但它引起了我的好奇心,所以我做了一些阅读。
仅限JSON
以下是一个类似的东西(未经测试)。它并没有解决你关于存储JSON二进制表示的问题,而是尝试一次性解析你正在检查的所有行的所有JSON,希望通过减少为每一行单独处理的处理开销来提高性能。如果成功了,我认为它可能会导致更高的内存消耗。
CREATE TYPE...set_of_records()
的内容是从wiki上的示例中改编而来,其中提到“您还可以返回具有JSON数组的记录。” 我想它真正意味着“对象数组”。
DB记录中的id
值是否嵌入在JSON中?
版本#1
CREATE TYPE rec AS (id integer, data text, name text);
CREATE FUNCTION set_of_records() RETURNS SETOF rec AS
$$
var records = plv8.execute( "SELECT id, data FROM things" );
var data = [];
// Use for loop instead if better performance
records.forEach( function ( rec, i, arr ) {
data.push( rec.data );
} );
data = "[" + data.join( "," ) + "]";
data = JSON.parse( data );
records.forEach( function ( rec, i, arr ) {
rec.name = data[ i ].name;
} );
return records;
$$
LANGUAGE plv8;
SELECT id, data FROM set_of_records() WHERE name LIKE 'Z%'
版本 #2
这个版本使用Postgres来聚合/连接一些值,以减少在JS中进行的处理。
CREATE TYPE rec AS (id integer, data text, name text);
CREATE FUNCTION set_of_records() RETURNS SETOF rec AS
$$
var cols = plv8.execute(
"SELECT" +
"array_agg( id ORDER BY id ) AS id," +
"string_agg( data, ',' ORDER BY id ) AS data" +
"FROM things"
)[0];
cols.data = JSON.parse( "[" + cols.data + "]" );
var records = cols.id;
records.forEach( function ( id, i, arr ) {
arr[ i ] = {
id : id,
data : cols.data[ i ],
name : cols.data[ i ].name
};
} );
return records;
$$
LANGUAGE plv8;
SELECT id, data FROM set_of_records() WHERE name LIKE 'Z%'
hstore
如果将JSON数据在写入时复制到hstore列(或者如果性能足够好,将JSON转换为hstore在选择时),并在WHERE
中使用hstore,那么它的性能如何比较?例如:
SELECT id, data FROM things WHERE hstore_data -> name LIKE 'Z%'
我从这里听说了hstore: http://lwn.net/Articles/497069/
文章提到了一些其他有趣的事情:
PL/v8让您...在特定的JSON元素上创建表达式索引并保存它们,为您提供存储搜索索引,就像CouchDB的“视图”一样。
它没有详细说明,我不太清楚它指的是什么。
有一个归属于“jberkus”的评论说:
我们讨论过也要有二进制JSON类型,但是没有协议来传输二进制值(BSON根本不是标准,并且存在一些严重的缺陷),似乎没有任何意义。
如果您有兴趣为PostgreSQL开发二进制JSON支持,我们很乐意提供帮助...
return data[key];
,对吧? - JMMjson
字段,而不需要解析。目前,Pg并不支持使用最新的json
字段实现这一点。如果这就是你想要的,那么你需要做的第一件事就是研究v8,看看是否可以找到对json进行高性能二进制序列化和反序列化的支持,因为如果没有这个功能,你将无法实现你的需求。 - Craig Ringer