2017-05-23 33 views
1

私はpg_column_sizeが非常に異なる値を報告している簡単な例があります。 TOASTされた値を検討しているかどうかは関係ありませんが、わかりません。pg_column_sizeは、特定の列よりもテーブル。*のサイズが大きく異なることを報告します

CREATE TABLE foo (bar TEXT); 
INSERT INTO foo (bar) VALUES (repeat('foo', 100000)); 
SELECT pg_column_size(bar) as col, pg_column_size(foo.*) as table FROM foo; 

私はPostgresの9.6に見ていることは、

col  table 
3442 300028 

あり、ここで大きさの差の順序があります:ここでセットアップがあります。思考?行のサイズを計算する正しい方法は何ですか?私が持っている一つのアイデアは、ポストTOASTサイズを減算し、TOASTサイズに追加する必要があります

SELECT pg_column_size(bar), pg_column_size(foo.*) - octet_length(bar) + pg_column_size(bar) FROM foo; 

です。

編集:私の提案されている回避策は、文字列にのみ有効です。 JSONBでは動作しません。

答えて

1

最初の値はTOASTed値の圧縮サイズで、2番目の値は行全体の圧縮されていないサイズです。

SELECT 'foo'::regclass::oid; 
┌───────┐ 
│ oid │ 
├───────┤ 
│ 36344 │ 
└───────┘ 
(1 row) 

SELECT sum(length(chunk_data)) FROM pg_toast.pg_toast_36344; 
┌──────┐ 
│ sum │ 
├──────┤ 
│ 3442 │ 
└──────┘ 
(1 row) 

foo.*(またはそのことについてfoo)はPostgreSQLの”を参照wholerow “ている場合、そのデータ型は、(テーブルが作成されるときに作成される)fooあります。

PostgreSQLはfoo.barが外部に格納されていることを知っているので、TOASTテーブルのサイズをそのまま返しますが、foo(複合型)はないので、合計サイズを取得します。

src/backend/access/heap/tuptoaster.cからコードの関連部分を参照してください:

Size 
toast_datum_size(Datum value) 
{ 
    struct varlena *attr = (struct varlena *) DatumGetPointer(value); 
    Size  result; 

    if (VARATT_IS_EXTERNAL_ONDISK(attr)) 
    { 
     /* 
     * Attribute is stored externally - return the extsize whether 
     * compressed or not. We do not count the size of the toast pointer 
     * ... should we? 
     */ 
     struct varatt_external toast_pointer; 

     VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr); 
     result = toast_pointer.va_extsize; 
    } 
    [...] 
    else 
    { 
     /* 
     * Attribute is stored inline either compressed or not, just calculate 
     * the size of the datum in either case. 
     */ 
     result = VARSIZE(attr); 
    } 
    return result; 
} 
関連する問題