使用json列的Postgresql偏移行为

时间:2014-12-11 04:22:46

标签: postgresql

使用postgresql 9.4我们有一个简单的联系人表(id文本不为null(作为pk),blob json)来试验移植couchdb crm数据库。我们最终将拆分为更多列等,并为rdbms更自觉地处理数据,但除了目前的要点之外。

大约有100k行。

我知道硬核postgresql性能专家建议不要使用偏移但是我可以接受一个小的性能损失(对100毫秒以下的任何事情感到满意)

SELECT id FROM couchcontacts OFFSET 10000 LIMIT 10 

如预期的那样需要<10ms

SELECT blob->>'firstName' FROM couchcontacts LIMIT 10 

也需要&lt; 10ms(在这里假设10个json解码操作blob列)

SELECT blob->>'firstName' FROM couchcontacts OFFSET 10000 LIMIT 10 

需要10秒钟!忽略偏移的低效率为什么这可能导致10,010个json解码操作?由于投影没有副作用,我不明白这不快的原因?

这是json功能的限制对postgres来说相对较新吗?因此无法确定->>操作员不会产生副作用?

有趣的是将查询重写为10毫秒

SELECT jsonblob->>'firstName' FROM couchdbcontacts WHERE id IN (SELECT id FROM couchcontacts OFFSET 10000 LIMIT 10)

有没有办法确保偏移不对json解码偏移的记录? (即不执行选择投影)

"Limit  (cost=1680.31..1681.99 rows=10 width=32) (actual time=12634.674..12634.842 rows=10 loops=1)"
"  ->  Seq Scan on couchcontacts  (cost=0.00..17186.53 rows=102282 width=32) (actual time=0.088..12629.401 rows=10010 loops=1)"
"Planning time: 0.194 ms"
"Execution time: 12634.895 ms"

1 个答案:

答案 0 :(得分:5)

我跑了几个测试,我看到了类似的行为。其中每一项都在绩效方面存在微不足道的差异:

  • select id ...
  • select indexed_field ...
  • select unindexed_field ...
  • select json_field ...
  • select * ...

然而,这个确实显示出性能上的差异:

  • select json_field->>'key' ...

当json_field为null时,性能影响可以忽略不计。如果它是空的,它会稍微降低一些东西。当它被填满时,它会明显降低。当字段加载更大的数据时,它会大幅降低。

换句话说,Postgres似乎想要为它访问的每一行重新序列化json数据。 (这可能是一个错误,并且会严重影响RoR开发人员如何使用json。)

Fwiw,我注意到重新安排查询以便它使用CTE将解决问题:

with data as (
  select * from table offset 10000 limit 10
)
select json_field->>'key' from data;

(它可能会得到一个比你突出显示的id IN (...)查询更好的计划。)