CHAR vs VARCHAR (Postgres) için dizin performansı


16

Bu cevapta ( /programming/517579/strings-as-primary-keys-in-sql-database ) tek bir yorum dikkatimi çekti:

Ayrıca, dizin karşılaştırmaları yaparken CHAR ve VARCHAR arasında genellikle çok büyük bir fark olduğunu unutmayın.

Bu Postgres için geçerli mi / hala geçerli mi?

Oracle'da CHARaz çok bir takma ad olduğunu iddia eden sayfalar buldum VARCHARve bu nedenle dizin performansı aynı, ancak Postgres'te kesin bir şey bulamadım.

Yanıtlar:


24

CHARve VARCHARPostgres (ve Oracle) için de aynı şekilde uygulanır. Bu veri türlerini kullanırken hız farkı yoktur.

Bununla birlikte, performansta bir fark yaratabilecek bir fark vardır: bir charsütun her zaman tanımlanan uzunluğa doldurulur. Yani bir sütunun tanımlarsak char(100)olarak ve bir varchar(100)yalnızca her 10 karakter depolamak, char(100)kolon ise, her bir değer (saklı 10 karakter, artı 90 boşluk) 100 karakter kullanır varcharsadece depolar sütun 10 karakter.

100 karakteri 100 karakteriyle karşılaştırmak 10 karakteri 10 karakteriyle karşılaştırmaktan daha yavaş olacaktır - ancak bir SQL sorgusunda bu farkı ölçebildiğinizden şüpheleniyorum.

Her ikisini de 10 karakter uzunluğunda beyan ederseniz ve her zaman tam olarak 10 karakter saklarsanız, kesinlikle hiçbir fark yoktur (bu Oracle ve Postgres için geçerlidir)

Yani tek fark, charveri tipi için yapılan dolgulamadır .


Ayrıca, dizin karşılaştırmaları yaparken CHAR ve VARCHAR arasında genellikle çok büyük bir fark olduğunu unutmayın.

Yukarıdaki alıntı yalnızcachar sütun çok geniş olarak tanımlanmışsa (ve yalnızca dolgu nedeniyle boşluk harcıyorsanız ) doğrudur . charSütunun uzunluğu her zaman tamamen kullanılırsa (dolgu olmaz), yukarıdaki alıntı yanlıştır (en azından Postgres ve Oracle için)


Benim bakış açımdan, charveri türünün gerçek anlamda herhangi bir kullanımı yok. Sadece varchar(veya textPostgres'de) kullanın ve charvar olduğunu unutun .


2
100 karakteri 100 karakteriyle karşılaştırmak 10 karakteri 10 karakteriyle karşılaştırmaktan daha yavaş olacaktır - ancak bir SQL sorgusunda bu farkı ölçebildiğinizden şüpheleniyorum. - Sorgunun sıralamaya ek olarak ne yaptığına bağlı olarak, fark çok büyük olabilir. Bu nedenle Postgres 9.5'in yeni bir “kısaltılmış anahtarlar” özelliği var: pgeoghegan.blogspot.de/2015/01/…
chirlu

6

Her şey ile katılıyorum söyledi a_horse_with_no_name tarafından ve genellikle Erwin'ın açıklama tavsiye ile anlaşmak:

Hayır, char daha düşük (ve modası geçmiş). metin ve varchar (neredeyse) aynı şeyi yapar.

Meta veri

Bir küçük istisna olmak üzere, tek sefer kullanım char()ı meta veriler bu demek istediğinizde ise zorunluluk bulunuyorsa hala röntgen karakterleri. Her ne kadar char()sadece giriş sınırın üzerindeyse şikayetçi olduğumu bilsem de, sık sık alt sınırlara karşı bir CHECKkısıtlama ile koruyacağım . Örneğin,

CREATE TABLE foo (
  x char(10) CHECK ( length(x) = 10 )
);
INSERT INTO foo VALUES (repeat('x', 9));

Bunu birkaç nedenden dolayı yapıyorum,

  1. char(x)bazen sabit genişlikli bir sütun olarak şema yükleyicilerle çıkarılır. Bu, sabit genişlikli dizeler için optimize edilmiş bir dilde fark yaratabilir.
  2. Anlamlı ve kolayca uygulanabilen bir sözleşme kurar. Bu kuraldan kod oluşturmak için bir dilde bir şema yükleyici yazabilirim.

Bunu nerede yapabileceğimin bir örneğine ihtiyacım var,

  1. İki harfli eyalet kısaltmaları olsa da, bu liste numaralandırılabildiğinden, genellikle bir ile yapacağım ENUM.
  2. Araç Kimlik Numaraları
  3. Model Numaraları (sabit boyutlu)

Hatalarda

Bazı insanlar sınırın her iki tarafındaki hata mesajlarının tutarsızlığından rahatsız olabilir, ancak beni rahatsız etmiyor

test=# INSERT INTO foo VALUES (repeat('x', 9));
ERROR:  new row for relation "foo" violates check constraint "foo_x_check"
DETAIL:  Failing row contains (xxxxxxxxx ).
test=# INSERT INTO foo VALUES (repeat('x', 11));
ERROR:  value too long for type character(10)

İle kontrast varchar

Dahası, yukarıdaki öneri neredeyse her zaman kullanımtext kuralına gerçekten iyi uyuyor . Sen de soruyorsun varchar(n). Bunu asla kullanmam . En azından son kullandığım zamanı hatırlayamıyorum varchar(n).

  • Bir spesifikasyonun güvendiğim bir statik genişlik alanı varsa char(n),
  • Aksi takdirde, textetkin bir şekilde kullanıyorum varchar(sınır yok)

Anlamlı değişken uzunluklu metin anahtarları olan ve sabit bir maksimum uzunluğa sahip olduğum için güvenilen bir özellik buldum, ben de kullanırdım varchar(n). Ancak, bu kriterlere uyan hiçbir şey düşünemiyorum.

Ek Notlar

  • charburada"char" tek baytlık bir tür olan ve sağlam performans ve yerden tasarruf sağlayan faydaları olan karıştırılmamalıdır.

İlgili Soru-Cevap:


1

postgresql

sales_reporting_db=# create table x (y char(2));
CREATE TABLE
sales_reporting_db=# insert into x values ('Y');
INSERT 0 1
sales_reporting_db=# select '*' || y || '*' from x;
 ?column? 
----------
 *Y*

torpil

SQL> create table x ( y char(2));

Table created.

SQL> insert into x values ('Y');

1 row created.

SQL> select '*' || y || '*' from x;

'*'|
----
*Y *

Postgresql boşluk bırakmadı.


Bu sadece Postgres'te optik bir yanılsama. DeneSELECT pg_column_size(y) FROM x;
dezso

-2

Bunu en yararlı ve hızlı bir 3 satır açıklaması buldum:

Gönderen CHAR (n) Vs VARCHAR (N) Vs Metinden

  • Uzunluğu bilinmeyen bir metin saklamak istiyorsanız, TEXTveri türünü kullanın .
  • Uzunluğu bilinmeyen bir metin saklamak istiyor ancak maksimum uzunluğu biliyorsanız, kullanın VARCHAR(n).
  • Tam uzunluğu bilinen bir metin saklamak istiyorsanız, kullanın CHAR(N).
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.