PostgreSQL:使用JSON时计数数据非常慢

时间:2014-02-13 16:30:51

标签: sql json postgresql ubuntu postgresql-9.3

我正在玩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初学者,我问自己,如果真的那么慢,或者我做错了什么?如果是后者,我该怎么办呢?

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

JSON对PostgreSQL来说还是一个新手,并没有很好的优化,但正在迅速改进。

当9.4在今年晚些时候发布时,看起来这个领域会有很大的改进(我的查询大约需要2秒,有196,608条记录)。

实际上,改进也在9.3.3,这应该在一周内完成。