Postgresql

為什麼 jsonb 使用更多的空間來儲存整數?

  • January 22, 2017

我做了一些小測試來嘗試這些數據類型,發現了一些令人費解的結果。

概括:

jsonb 為整數使用的空間比字元串多:

select pg_column_size('{"a":"1"}'::jsonb) as json_size

18

select pg_column_size('{"a":1}'::jsonb) as json_size

28

為什麼使用整數時 jsonb 的大小會膨脹?


長版:

我最初對使用整數數組感興趣,這裡是那些測試。在每對逗號分隔的數字中,第一個對應的是json_size(bytes),第二個數字是array_size(bytes)。

select pg_column_size('[]'::jsonb) as json_size, 
      pg_column_size(array[]::smallint[]) as array_size

8,16

select pg_column_size('[1]'::jsonb) as json_size, 
      pg_column_size(array[1]::smallint[]) as array_size

20,26

檢查 jsonb 是否真的將整數儲存為純文字;如果是這樣,那麼下一個應該為 jsonb 多使用 4 個字節:

select pg_column_size('[12345]'::jsonb) as json_size, 
      pg_column_size(array[12345]::smallint[]) as array_size

22,26

奇怪,它多用了 2 個字節,不知道這意味著什麼。現在嘗試一些更實際和現實的數據:

select pg_column_size('[123,234,345,456,567,678,789,890]'::jsonb) as json_size, 
      pg_column_size(array[123,234,345,456,567,678,789,890]::smallint[]) as array_size

104,40

這裡的jsonb怎麼了?是什麼導致它膨脹?也許如果我使用具有較少字元的較小數字……

select pg_column_size('[1,2,3,4,5,6,7,8]'::jsonb) as json_size, 
      pg_column_size(array[1,2,3,4,5,6,7,8]::smallint[]) as array_size

104,40

沒有。字元串呢?

select pg_column_size('["1","2","3","4","5","6","7","8"]'::jsonb) as json_size, 
      pg_column_size(array[1,2,3,4,5,6,7,8]::smallint[]) as array_size

48,40

似乎 jsonb 喜歡字元串而不是整數。

我很快就制定了一個經驗法則,即我應該只在 jsonb 中使用字元串,而對數字數據使用原生整數或數組,但我不知道這個規則是否被誤導或為什麼會發生這種異常。

這很簡單。JSON 沒有整數的概念,只有“數字”。從文件

在將文本 JSON 輸入轉換為 jsonb 時,RFC 7159 描述的原始類型有效地映射到原生 PostgreSQL 類型,如表 8-23 所示。

該表顯示一個 JSON“數字”被映射到一個數字。數字的最大精度是

小數點前最多 131072 位;小數點後最多 16383 位

但是,我認為它實際上並沒有儲存它。它確實儲存了某種數字。坦率地說,數字來源很難理解。

如果它適合您的工作負載,則使用 smallint 數組顯然會更好。它減少了用於打包的浪費空間,也減少了數據本身浪費的空間。smallint[]然而

  • 不支持相同範圍的數字。
  • 不支持嵌入不同類型。
  • 根本不支持任何精度。
  • 與網路客戶端不能很好地交流。

引用自:https://dba.stackexchange.com/questions/161866