Varchar (n) için ek yük nedir?


15

Ben bu parçanın anlamını sormak istedim Postgres doc ilişkin varchar(n)tip:

Kısa bir dize (126 bayta kadar) için depolama gereksinimi, 1 bayt artı karakter durumunda boşluk dolgusu içeren gerçek dizedir. Daha uzun dizelerde 1 yerine 4 bayt ek yük vardır.

Bir alanım olduğunu varsayalım varchar(255). Ve şimdi, aşağıdaki ifadeler:

  • Bu alan 10 baytlık bir dize içeriyorsa, ek yük 1 bayttır. Dize 11 bayt kullanır.
  • Alan 140 bayt kullanarak dize tutarsa, ek yük 4 bayttır. Dize 144 bayt kullanır.

Yukarıdaki ifadeler doğru mu? İşte birisi doktor benimle aynı şekilde anlayan ama burada birileri havai daima 4 bayt devletler burada ?

Yanıtlar:


19

Şaşırtıcı olmayan bir şekilde, kılavuz doğru. Ama daha fazlası var.

Birincisi, diskteki boyut (herhangi bir tabloda , gerçekte diskte saklanmamış olsa bile) bellekteki boyuttan farklı olabilir . Diskte, varchar126 bayta kadar kısa değerler için ek yük , kılavuzda belirtildiği gibi 1 bayta indirgenir . Ancak bellekteki ek yük her zaman 4 bayttır (tek tek değerler çıkarıldığında).

Aynı şey , veya için de geçerlidir text,varcharvarchar(n)char(n) ancak bu karakterlere char(n)boş olarak doldurulur nve normalde kullanmak istemezsiniz. Etkili boyutu çok baytlı kodlamalarda değişebilir, çünkü nbayt değil, maksimum karakter anlamına gelir:

nkarakter (bayt değil) uzunluğuna kadar dizeler .

Hepsi varlenadahili olarak kullanır .
"char"(çift tırnak ile) farklı bir yaratıktır ve her zaman tek bir bayt kaplar.
Türlenmemiş dize değişmezlerinin ( 'foo') tek bir bayt ek yükü vardır. Yazılan değerlerle karıştırılmamalıdır!

İle test edin 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

Gördüğün gibi:

  • 3 baytlık 'foo' dizgisinde 4 bayt ve RAM'de 7 bayt yer kaplar (yani 1 bayt ve 4 bayt ek yük).
  • 140 bayt '123 ...' dizesi hem diskte hem de RAM'de 144 bayt kaplar (bu nedenle her zaman 4 bayt ek yük).
  • Depolama integerbiriminin ek yükü yoktur (ancak dolgu uygulayabilecek hizalama gereksinimleri vardır).
  • Satırın, üstbilgi başlığı için ek 24 bayt ek yükü vardır (ayrıca sayfa üstbilgisindeki öğe işaretçisi için her kanal için ek 4 bayt).
  • Ve son fakat en az değil: Küçük varcharboyutun tepesi, satırdan çıkarılmadığı halde hala sadece 1 bayttır - satır boyutundan görülebileceği gibi. (Bu yüzden bazen tüm satırları seçmek biraz daha hızlıdır.)

İlişkili:


1
Bu 1 bayt yükü hala dizinde 1 bayt mı?
dvtan

1
@dtgq: Bir dizin, verileri tıpkı bir tablo gibi depolar, bu nedenle evet.
Erwin Brandstetter
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.