我正在玩PostgreSQL9.3并决定试用JSON类型。所以我编写了一个Query来计算某些JSON数据,并通过user_id对它们进行分组,但这个过程需要很长时间才能完成。有人可以给我一些改善表现的提示吗?
但是,让我先向您展示测试数据和关系:
我下载了一些测试数据,每行包含一个JSON文档。 JSON文档由一个名为“hashtags”的数组,一个名为“urls”的数组和一个名为“user_id”(非唯一)的字段组成。
测试数据:
{"hashtags": ["a", "b", "c"],"user_id": 210824047, "urls": ["http://www.google.com"]}
{"hashtags": ["b"], "user_id": 78149438, "urls": ["http://www.facebook.com"]}
{"hashtags": ["a", "c"], "user_id": 123791448, "urls": ["http://www.twitter.com","http://www.facebook.com"]}
...
然后我使用自动递增主键和包含JSON类型的列创建了一个简单的关系:
CREATE TABLE tweets(id BIGSERIAL PRIMARY KEY, tweet JSON);
我将数据加载到postgresql中,其中一个JSON Document现在等于一行:
id | tweet
---+---------------------------------------------------------------------------------
1 |{"hashtags": ["a", "b", "c"],"user_id": 210824047, "urls": ["http://www.google.com"]}
2 |{"hashtags": ["b"], "user_id": 78149438, "urls": ["http://www.facebook.com"]}
3 |{"hashtags": ["a", "c"], "user_id": 123791448, "urls": ["http://www.twitter.com","http://www.facebook.com"]}
现在我想知道某个user_id使用hastag的频率。要做到这一点,我有 使用使用json_array_elements()函数的子查询。该函数接受指定的JSON数组并将其转换为列。
查询如下所示:
select foo.uid, foo.tag, count(foo.*) from
(select (tweet::json->>'user_id')::int as uid,
json_array_elements(tweet::json->'hashtags')::text as tag from tweets)
as foo group by foo.uid, foo.tag;
我得到了我想要的结果,但查询花了很长时间才完成。例如,我将200.000个JSON文档加载到postgresql中,略小于25MB,并且在得到结果之前大约需要10分钟。我也尝试了各种索引,但性能最多只提高了半分钟。
现在我是一名postgresql初学者,我问自己,如果真的那么慢,或者我做错了什么?如果是后者,我该怎么办呢?
非常感谢您的帮助。
答案 0 :(得分:1)
JSON对PostgreSQL来说还是一个新手,并没有很好的优化,但正在迅速改进。
当9.4在今年晚些时候发布时,看起来这个领域会有很大的改进(我的查询大约需要2秒,有196,608条记录)。
实际上,改进也在9.3.3,这应该在一周内完成。