我有一个相对较小的表(约5万行)。当我选择所有记录时,大约需要40秒。该表具有3个JSONB列。当我选择除JSONB之外的所有列时,查询大约需要700毫秒。
如果我仅添加JSONB字段之一,则查询时间将跳到近10s。
我从不使用引用JSONB内部内容的where子句,而只是选择*。即便如此,我还是尝试添加GIN索引,因为我经常看到它们被认为是JSONB的性能提升器。
我已经完全抽真空了。
Postgres 9.6版
explain (analyze, buffers) select * from message;
Seq Scan on message (cost=0.00..5541.69 rows=52969 width=834) (actual
time=1.736..116.183 rows=52969 loops=1)
Buffers: shared hit=64 read=4948
Planning time: 0.151 ms
Execution time: 133.555 ms
答案 0 :(得分:2)
Jsonb是PostgreSQL的varlena数据类型-这意味着当值大于2KB时,它将存储在辅助表(名为TOAST表)中。指向TOAST表的指针存储在主表中。因此,当您不触摸Jsonb列时,则不会读取此值。
GIN索引在这种情况下无济于事。它仅对搜索有用。
50K值需要10秒的时间很长-也许您的Jsonb值很长,或者您的IO系统性能不佳。请检查表的大小,并检查IO的性能。廉价的云机器通常具有糟糕的IO。
变慢的另一个可能原因是Jsonb数据类型的复杂性。 Jsonb是json子对象的序列化树。如果您不需要Jsonb数据类型的某些特殊功能,请使用JSON数据类型。这只是测试(仅在输入中检查JSON格式)。 JSONB的输出比Jsonb更快,因为JSON在内部是文本,因此不需要任何操作。 Jsonb的输出应该序列化,这会更昂贵。