CHAR vs VARCHAR (Postgres)의 인덱스 성능


16

이 답변 ( /programming/517579/strings-as-primary-keys-in-sql-database )에서 한 발언이 내 눈을 사로 잡았습니다.

또한 인덱스 비교를 수행 할 때 CHAR과 VARCHAR간에 매우 큰 차이가 있음을 명심하십시오.

이것이 Postgres에도 적용됩니까?

Oracle CHAR에서 별명 이라고 주장하는 페이지를 찾았 VARCHAR으므로 색인 성능이 동일하지만 Postgres에서 결정적인 것은 없습니다.

답변:


24

CHAR그리고 VARCHAR포스트 그레스 (오라클)에서 동일한 정확하게 구현됩니다. 이러한 데이터 유형을 사용할 때 속도에는 차이가 없습니다.

그러나 성능에 차이를 줄 있는 한 가지 차이점이 있습니다 . char열은 항상 정의 된 길이로 채워집니다. 따라서 열을 char(100)하나만 정의하고 varchar(100)char(100)열에 10자를 저장하는 경우 열은 각 값에 100 자 (저장 한 10 자 + 90 자)를 사용하지만 varchar열은 10 자만 저장합니다.

100 문자와 100 문자를 비교하는 것은 10 문자와 10 문자를 비교하는 것보다 느릴 것입니다.하지만 실제로 SQL 쿼리 에서이 차이를 측정 할 수는 없습니다.

10 자 길이로 선언하고 항상 정확히 10자를 저장 하면 아무런 차이가 없습니다 (Oracle과 Postgres의 경우)

따라서 유일한 차이점은 char데이터 유형에 대해 수행되는 패딩입니다 .


또한 인덱스 비교를 수행 할 때 CHAR과 VARCHAR간에 매우 큰 차이가 있음을 명심하십시오.

위 인용문은 열이 너무 넓게 정의 된 경우 에만 적용됩니다 char(즉, 패딩으로 인해 공간이 낭비되는 경우). char열의 길이 가 항상 완전히 사용되면 (패딩이 발생하지 않음) 위의 인용은 잘못되었습니다 (적어도 Postgres 및 Oracle의 경우)


필자의 관점에서 볼 때 char데이터 유형에는 실제로 실제 단어가 사용되지 않습니다. 그냥 varchar(또는 textPostgres에서) 사용하고 잊어 버려요 char.


2
100 문자와 100 문자를 비교하는 것은 10 문자와 10 문자를 비교하는 것보다 느릴 것입니다.하지만 실제로 SQL 쿼리 에서이 차이를 측정 할 수는 없습니다. – 정렬 외에 쿼리가 수행하는 작업에 따라 차이가 클 수 있습니다. 그렇기 때문에 Postgres 9.5에 새로운“약어 키”기능이 추가되었습니다 : pgeoghegan.blogspot.de/2015/01/…
chirlu

6

나는 a_horse_with_no_name이 말한 모든 것에 동의하며 일반적으로 Erwin의 의견 조언에 동의합니다.

아니요, char는 열등합니다 (구식입니다). text와 varchar는 (거의) 동일하게 수행합니다.

메타 데이터

하나 개의 작은 예외로, 단지 시간 I 사용은 char()내가 메타 데이터가이 말을 할 때입니다 MUST가 되세요 되세요 X-문자. char()입력이 한도를 초과하는 경우에만 불만 이 있음을 알고 있지만 CHECK제약 조건의 언더런을 자주 방지 합니다. 예를 들어

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

몇 가지 이유로이 작업을 수행합니다.

  1. char(x)때로는 스키마 로더가 고정 너비 열인 것으로 추론됩니다. 이는 고정 폭 문자열에 최적화 된 언어에서 차이를 만들 수 있습니다.
  2. 이해하기 쉽고 쉽게 적용 할 수있는 규칙을 설정합니다. 이 컨벤션에서 코드를 생성하는 언어로 스키마 로더를 작성할 수 있습니다.

내가 이것을 할 수있는 곳의 예가 필요합니다.

  1. 두 글자 상태 약어는이 목록을 열거 할 수 있기 때문에 일반적으로 ENUM.
  2. 차량 식별 번호
  3. 모델 번호 (고정 크기)

오류

일부 사람들은 한도의 양쪽에 오류 메시지가 일치하지 않아 불편할 수 있지만 나를 귀찮게하지는 않습니다.

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)

대조 varchar

또한 위의 제안은 거의 항상 사용text 되는 규칙과 잘 맞습니다 . 당신 varchar(n)도 역시 묻습니다 . 나는 그것을 사용하지 않습니다 . 적어도 마지막으로 사용한 시간을 기억할 수 없습니다 varchar(n).

  • 사양에 내가 신뢰할 수있는 정적 너비 필드가있는 경우 char(n),
  • 그렇지 않으면 text효과적으로 사용합니다 varchar(제한 없음)

의미있는 가변 길이 텍스트 키가 있고 최대 길이가 일정하다고 신뢰하는 사양을 발견하면 사용 varchar(n)합니다. 그러나 그 기준에 맞는 것을 생각할 수 없습니다.

추가 사항

  • char여기서는"char" 1 바이트 유형이며 성능과 공간 절약 측면에서 확실한 이점이 있습니다.

관련 Q & A :


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*

신탁

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은 공백으로 채워지지 않았습니다.


그것은 Postgres의 착시 일뿐입니다. 시도SELECT pg_column_size(y) FROM x;
dezso

-2

나는 이것이 가장 유용하고 빠른 3 줄 설명을 발견했다.

에서 포스트 그레스에서 CHAR (n)에 대 VARCHAR (N) 대 텍스트

  • 길이를 알 수없는 텍스트를 저장하려면 TEXT데이터 유형을 사용하십시오 .
  • 길이를 알 수없는 텍스트를 저장하려고하지만 최대 길이는 알고있는 경우을 사용하십시오 VARCHAR(n).
  • 정확한 길이로 알려진 텍스트를 저장하려면을 사용하십시오 CHAR(N).
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.