Berapa overhead untuk varchar (n)?

15

Saya ingin menanyakan arti fragmen ini dari postgres doc mengenai varchar(n)tipe:

Persyaratan penyimpanan untuk string pendek (hingga 126 byte) adalah 1 byte plus string yang sebenarnya, yang mencakup ruang bantalan dalam kasus karakter. String yang lebih panjang memiliki 4 byte overhead daripada 1.

Mari kita asumsikan bahwa saya memiliki varchar(255)lapangan. Dan sekarang, pernyataan berikut:

  • Jika bidang ini memiliki string 10 byte, maka biaya overhead adalah 1 byte. Jadi string akan menggunakan 11 byte.
  • Jika bidang menyimpan string menggunakan 140 byte, maka overhead adalah 4 byte. Jadi string akan menggunakan 144 byte.

Apakah pernyataan di atas benar? Di sini seseorang memahami doc dengan cara yang sama seperti saya, tetapi di sini seseorang menyatakan overhead selalu 4 byte di sini ?

penekanan tombol
sumber

Jawaban:

19

Tidak mengejutkan, manualnya benar. Tapi ada lebih banyak lagi mengenai hal tersebut.

Untuk satu ukuran pada disk (dalam tabel apa pun , bahkan ketika tidak benar-benar disimpan pada disk) dapat berbeda dari ukuran dalam memori . Pada disk, overhead untuk varcharnilai pendek hingga 126 byte dikurangi menjadi 1 byte seperti yang dinyatakan dalam manual. Tetapi overhead dalam memori selalu 4 byte (setelah nilai individu diekstraksi).

Hal yang sama berlaku untuk text, varchar, varchar(n)atauchar(n) - kecuali bahwa char(n)kosong-empuk untuk nkarakter dan Anda biasanya tidak ingin menggunakannya. Ukuran efektifnya masih dapat bervariasi dalam pengkodean multi-byte karena nmenunjukkan karakter maksimum, bukan byte:

panjang nkarakter hingga (bukan byte).

Semuanya digunakan secara varlenainternal.
"char"(dengan tanda kutip ganda) adalah makhluk yang berbeda dan selalu menempati satu byte tunggal.
Literal string yang tidak diketik ( 'foo') memiliki overhead byte tunggal. Jangan bingung dengan nilai yang diketik!

Tes dengan pg_column_size().

CREATE TEMP TABLE t (id int, v_small varchar, v_big varchar);
INSERT INTO t VALUES (1, 'foo', '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890');

SELECT pg_column_size(id)        AS id
     , pg_column_size(v_small)   AS v_small
     , pg_column_size(v_big)     AS v_big
     , pg_column_size(t)         AS t
FROM   t
UNION ALL  -- 2nd row measuring values in RAM
SELECT pg_column_size(1)
     , pg_column_size('foo'::varchar)
     , pg_column_size('12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890'::varchar)
     , pg_column_size(ROW(1, 'foo'::varchar, '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890'::varchar));

 id | v_small | v_big |  t
----+---------+-------+-----
  4 |       4 |   144 | 176
  4 |       7 |   144 | 176

Seperti yang dapat Anda lihat:

  • String 3-byte 'foo' menempati 4 byte pada disk dan 7 byte dalam RAM (jadi 1 byte vs 4 byte overhead).
  • String 140 byte '123 ...' menempati 144 byte baik pada disk maupun dalam RAM (jadi selalu 4 byte overhead).
  • Penyimpanan integertidak memiliki overhead (tetapi memiliki persyaratan pelurusan yang dapat mengenakan bantalan).
  • Baris memiliki overhead tambahan 24 byte untuk tuple header (ditambah 4 byte tambahan per tuple untuk pointer item di header halaman).
  • Dan last but not least: Overhead kecil varcharmasih hanya 1 byte sementara itu belum diekstraksi dari baris - seperti yang dapat dilihat dari ukuran baris. (Itu sebabnya kadang-kadang sedikit lebih cepat untuk memilih seluruh baris.)

Terkait:

Erwin Brandstetter
sumber
1
Apakah itu 1 byte overhead masih 1 byte dalam indeks?
dvtan
1
@ dtgq: Indeks menyimpan data seperti tabel, jadi ya.
Erwin Brandstetter