使用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"
答案 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 (...)
查询更好的计划。)