모든 텍스트 기반 필드에 일반 varchar (255)를 사용하는 데 단점이 있습니까?


100

나는이 contacts같은 필드가 포함 테이블을 postcode, first name, last name, town, country, phone number등으로 정의되어 모두 VARCHAR(255)도이 분야의 누구도 가까운 255 자있는에 올 것이다하지만. (궁금하신다면 Ruby on Rails 마이그레이션 VARCHAR(255)이 기본적으로 String 필드를 에 매핑 하고 재정의 할 필요가 없기 때문에 이런 식 입니다.)

VARCHAR은 (필드 길이와 함께) 분야의 실제 문자의 수를 저장하는 것이기 때문에, 말하자면, 사용에 대한 뚜렷한 장점 (그렇지 않으면 성능)이 VARCHAR(16)이상은 VARCHAR(255)?

또한 이러한 필드의 대부분에는 인덱스가 있습니다. 필드에서 더 큰 VARCHAR 크기가 인덱스의 크기 나 성능에 전혀 영향을 줍니까?

참고로 MySQL 5를 사용하고 있습니다.


2
@ceejayoz, 왜 실제로 도움이되지 않는지 설명하지 않고 받아 들여진 대답이 틀렸다고 말했습니다. 더 나쁜 것은 수용된 답변이 시간이 지남에 따라 변경 될 수 있으며 귀하의 의견은 사람들이 새로운 수용된 답변이 틀렸다고 생각하도록 혼동 할 수 있다는 것 입니다.
Gili

1
@Gili OP가 수락을 변경함에 따라 내 의견을 삭제했습니다. 좋은 점은 앞으로 어떤 대답에 대해 왜 그 이유를 말씀 드릴까요?
ceejayoz

이 중복 질문에서 일부 다른 답변은 stackoverflow.com/questions/1262174/...
제임스 맥마흔에게

답변:


129

저장소에서는 항상 255자를 저장하는 VARCHAR(255)것과 달리 주어진 행에 필요한 길이 만 저장할 수있을만큼 똑똑 CHAR(255)합니다.

그러나이 질문에 MySQL에 태그를 지정 했으므로 MySQL 관련 팁을 언급하겠습니다. 행이 스토리지 엔진 계층에서 SQL 계층으로 복사되면 VARCHAR필드가로 변환 CHAR되어 고정 너비 행으로 작업하는 이점을 얻습니다. 따라서 메모리의 문자열은 선언 된 열의 최대 길이까지 채워집니다VARCHAR .

예를 들어 또는 정렬하는 동안 쿼리가 암시 적으로 임시 테이블을 생성하는 GROUP BY경우 많은 메모리를 사용할 수 있습니다. VARCHAR(255)그렇게 길지 않아도되는 데이터에 대해 많은 필드를 사용하면 임시 테이블이 매우 커질 수 있습니다.

또한이 "패딩 아웃"동작은 utf8 문자 세트로 선언 된 문자열이 단일 바이트 콘텐츠 (예 : ascii 또는 latin1 문자)로 저장 한 문자열에 대해서도 문자 당 3 바이트로 채워짐을 의미합니다. 마찬가지로 utf8mb4 문자 세트는 문자열이 메모리에서 문자 당 4 바이트까지 채워지도록합니다.

따라서 VARCHAR(255)utf8에서 "No 의견"과 같은 짧은 문자열을 저장하는 것은 디스크에서 11 바이트 (낮은 문자 집합 문자 10 개와 길이 1 바이트)를 사용하지만 메모리에서는 765 바이트를 사용하므로 임시 테이블 또는 정렬 된 결과가됩니다.

나는 무의식적으로 1.5GB 임시 테이블을 자주 생성하고 디스크 공간을 채우는 MySQL 사용자를 도왔습니다. VARCHAR(255)실제로는 매우 짧은 문자열을 저장하는 많은 열이 있습니다.

저장하려는 데이터 유형에 따라 열을 정의하는 것이 가장 좋습니다. 다른 사람들이 언급했듯이 응용 프로그램 관련 제약 조건을 적용하면 이점이 있습니다. 그러나 위에서 설명한 메모리 낭비를 피할 수있는 물리적 이점이 있습니다.

물론 가장 긴 우편 주소가 무엇인지 알기는 어렵 기 때문에 많은 사람들 VARCHAR이 어떤 주소보다 확실히 긴 긴 주소를 선택합니다. 그리고 255는 VARCHAR길이를 1 바이트로 인코딩 할 수있는 a의 최대 길이이기 때문에 일반적 입니다. 또한 VARCHAR5.0 이전 MySQL 의 최대 길이였습니다.


6
나는 항상 255문자열의 길이가 단일 바이트에 맞도록 사용 되었다고 생각했습니다.
BlueRaja-Danny Pflughoeft

3
@BlueRaja : 내부 파일 구조가 문자열 길이를 단일 바이트로 인코딩 한 데이터베이스 또는 짧은 문자열을 단일 바이트로 인코딩 한 데이터베이스의 경우 아마도 사실 일 것입니다. 그러나 대부분의 데이터베이스에는 더 이상 사실이 아닙니다.
Bill Karwin

7
@BlueRaja : InnoDB는 다음 varchar의 길이를 저장하지 않고 행의 모든 ​​필드에 대한 일련의 필드 오프셋을 저장합니다. 이러한 필드 오프셋은 총 행 크기가 127 바이트 미만인 경우 1 바이트이거나 그렇지 않은 경우 2 바이트 일 수 있습니다. forge.mysql.com/wiki/MySQL_Internals_InnoDB
Bill Karwin

6
@BlueRaja : MyISAM (아직 사용하는 사람들을 위해)은 varchar 길이를 저장하며 1 바이트 또는 2 바이트로 저장할 수 있습니다. 그러나 : "index_read () 또는 records_in_range의 핸들러에 키를 보낼 때, 우리는 항상 VARCHAR에 대해 2 바이트 길이를 사용하여 작업을 더 간단하게 만듭니다." forge.mysql.com/wiki/MySQL_Internals_MyISAM
Bill Karwin

1
한 가지 질문-모든 필드 또는 varchar 필드 자체에서 정렬 및 그룹화?
Rohit Banga

24

varchar의 크기 설정에 대한 크기 및 성능 고려 사항 외에도 (저장 및 처리 비용이 매초마다 저렴 해짐에 따라 더 중요 할 수 있음) varchar (255) 사용의 단점은 데이터 무결성 이 감소하기 때문 입니다.

문자열에 대한 최대 제한을 정의하는 것은 예상보다 긴 (더 많은 바이트) 값을 데이터베이스에서 검색하고 구문 분석 할 때 예상보다 긴 문자열이 RDBMS에 들어가고 나중에 버퍼 오버런이나 예외 / 오류가 발생 하지 않도록 방지 하는 좋은 방법 입니다.

예를 들어 국가 약어에 대해 2 자 문자열을 허용하는 필드가있는 경우 사용자 (이 컨텍스트에서 프로그래머)가 전체 국가 이름을 입력 할 것이라고 예상 할 수있는 이유가 없습니다. "Antigua and Barbuda"(AG) 또는 "Heard Island and McDonald Islands"(HM)를 입력하는 것을 원하지 않기 때문에 데이터베이스 계층에서 허용하지 않습니다. 또한 일부 프로그래머는 설계 문서 ( 확실히 존재 함 )를 RTFM 하지 않아이를 수행하지 않는 것을 알 수 있습니다.

두 문자를 허용하도록 필드를 설정하고 RDBMS가 처리하도록합니다 (잘림으로써 정상적으로 또는 오류와 함께 SQL을 거부하여 비정상적으로).

특정 길이를 초과 할 이유가없는 실제 데이터의 예 :

  • 캐나다 우편 번호 는 A1A1A1 형식이며 산타 클로스의 경우에도 항상 길이가 6 자입니다 (6 자에서는 가독성을 위해 지정할 수있는 공백이 제외됨).
  • 이메일 주소 -@ 앞에 최대 64 바이트, 뒤에 최대 255 바이트. 더 이상 인터넷을 끊지 않도록하십시오.
  • 북미 전화 번호는 10 자리를 초과 할 수 없습니다 (국가 코드 제외).
  • Windows를 실행하는 컴퓨터 (최신 버전) 는 63 바이트보다 긴 컴퓨터 이름을 가질 수 없지만 15 개 이상은 권장되지 않으며 Windows NT 서버 팜을 손상시킵니다.
  • 주 약자는 2 자입니다 (위의 국가 코드 예와 같음).
  • UPS 조회 번호 는 18 자, 12 자, 11 자 또는 9 자입니다. 18 자리 숫자는 "1Z"로 시작하고 11 자리 숫자는 "T"로 시작합니다. 문자와 숫자의 차이를 모르는 경우 모든 패키지를 배송하는 방법이 궁금합니다.

등등...

시간을내어 데이터와 그 한계에 대해 생각하십시오. 당신이 건축가, 개발자, 프로그래머라면 그것은 결국 당신의 입니다.

varchar (255) 대신 varchar (n)을 사용하면 사용자 (최종 사용자, 프로그래머, 기타 프로그램)가 예기치 않게 긴 데이터 입력 하여 나중에 코드를 괴롭히는 문제를 제거 할 수 있습니다.

그리고 응용 프로그램에서 사용하는 비즈니스 논리 코드에서도이 제한을 구현해서는 안된다고 말하지 않았습니다.


5
캐나다 우편 번호에는 실제로 7 자리 숫자가 있으며 가운데 공백이 중요하며 우편 라벨에 표시되어야합니다. 확장명이있는 경우 북미 전화 번호는 10 자리 이상일 수 있습니다. 내선 전화 번호를 저장할 수없는 경우 10 자리 숫자는 괜찮지 만 후회할 것입니다.
Kibbee

3
데이터 무결성을 제한하는 경우가 있습니다. 하지만 너무 제한적이기는 쉽습니다. 제어하는 데이터에 대해 제한을 적용하고 제어 할 수없는 데이터 요구 사항에 대해 적절한 제한을 적용합니다. 귀하의 전화 번호 및 이메일 제한은 정상입니다 (국제화하지 않는다고 가정). 2 자 국가 코드를 자르는 것이 "우아한"일이라는 요구 사항은 미쳤습니다. 오류가 있음을 알고 있으므로 자르지 말고 수락하십시오. 자르면 잘못된 국가 코드로 끝날 가능성이 매우 높습니다.
coderjoe

대부분의 응용 프로그램은 ... 데이터 유효성 검사가 데이터베이스로 전송하기 전에 수행해야합니다
코비 (cobby) 타입

2
확실한. 대부분. 하지만 여기에서는 기존 데이터베이스 용 새 애플리케이션을 개발하는 개발자가 데이터에 대한 제한 사항을 알고 있다고 가정하고 있다고 생각합니다 (모든 데이터 유형에 대한 전문가는 아니며 모든 데이터베이스에서 구현되는 방법 ). 애플리케이션에서 데이터의 유효성을 검사 할 수 있다고해서 그랬다는 의미는 아닙니다.
shufler

3
the design documentation (which surely exists)하. : D
Camilo Martin

14

난 너와 함께있어. 세부 사항에 대한 까다로운 관심은 목의 통증이며 가치가 제한적입니다.

옛날 옛적에 디스크는 귀중한 상품이었고 우리는이를 최적화하기 위해 총알을 땀을 흘리 곤했습니다. 스토리지 가격이 1,000 배 하락하여 모든 바이트를 압축하는 데 소요되는 시간의 가치가 떨어졌습니다.

CHAR 필드 만 사용하는 경우 고정 길이 행을 얻을 수 있습니다. 필드에 대해 정확한 크기를 선택한 경우 일부 디스크 실제 복원을 절약 할 수 있습니다. 더 조밀하게 압축 된 데이터 (테이블 스캔을위한 I / O 감소)와 더 빠른 업데이트 (업데이트 및 삽입을 위해 블록에서 열린 공간을 더 쉽게 찾을 수 있음)를 얻을 수 있습니다.

그러나 크기를 과대 평가하거나 실제 데이터 크기가 가변적이면 CHAR 필드로 공간을 낭비하게됩니다. 데이터는 압축률이 낮아집니다 (대규모 검색을 위해 더 많은 I / O로 이어짐).

일반적으로 변수 필드에 크기를 입력하면 성능상의 이점은 미미합니다. CHAR (x)와 비교하여 VARCHAR (255)를 사용하여 쉽게 벤치마킹하여 차이를 측정 할 수 있는지 확인할 수 있습니다.

그러나 때때로 "작은", "중간", "대형"힌트를 제공해야합니다. 그래서 저는 크기로 16, 64, 255를 사용합니다.


13

요즘에는이게 더 이상 중요하다는 것을 상상할 수 없습니다.

가변 길이 필드를 사용하는 데는 계산 오버 헤드가 있지만 오늘날 CPU가 너무 많아서 고려할 가치가 없습니다. I / O 시스템이 너무 느려서 varchar를 효과적으로 처리하기위한 계산 비용이 존재하지 않습니다. 사실, 계산적으로 varchar의 가격은 고정 길이 필드에 대해 가변 길이 필드를 사용하여 절약 된 디스크 공간의 양에 대한 순이익 일 것입니다. 행 밀도가 더 높을 가능성이 높습니다.

이제 varchar 필드의 복잡성은 레코드 번호를 통해 레코드를 쉽게 찾을 수 없다는 것입니다. 고정 길이 행 크기 (고정 길이 필드 포함)가있는 경우 행 ID가 가리키는 디스크 블록을 계산하는 것은 간단합니다. 가변 길이 행화를 사용하면 그러한 종류가 창 밖으로 나갑니다.

따라서 이제는 다른 기본 키와 마찬가지로 일종의 레코드 번호 인덱스를 유지해야합니다. 또는 식별자에 세부 정보 (예 : 블록 등)를 인코딩하는 강력한 행 식별자를 만들어야합니다. 하지만 그렇게하면 행이 영구 저장소로 이동 될 경우 ID를 다시 계산해야합니다. 큰 문제는 아닙니다. 모든 인덱스 항목을 다시 작성하고 a) 소비자에게 절대 노출하지 않거나 b) 숫자가 신뢰할 수 있다고 주장하지 않도록해야합니다.

그러나 오늘날 varchar 필드가 있으므로 varchar (255)보다 varchar (16)의 유일한 값은 DB가 varchar (16)에 16 자 제한을 적용한다는 것입니다. DB 모델이 실제로 실제 데이터 모델을 대표해야하는 경우 필드 길이를 갖는 것이 가치가있을 수 있습니다. 그러나 "모델 및 스토리지"가 아니라 단순히 "스토리지"인 경우에는 전혀 필요하지 않습니다.

그런 다음 인덱싱 할 수있는 텍스트 필드 (예 : varchar)와 그렇지 않은 항목 (예 : 텍스트 또는 CLOB 필드)을 구분하기 만하면됩니다. 인덱싱 가능한 필드는 인덱스를 용이하게하기 위해 크기에 제한이있는 경향이 있지만 CLOB 필드는 그렇지 않습니다 (이유 내에서).


5

내 경험상 255 자의 데이터 유형을 허용하면 어리석은 사용자 (또는 숙련 된 테스터)가 실제로이를 채울 것입니다.

그러면 보고서의 해당 필드와 응용 프로그램의 화면 표시에 허용되는 공간을 포함하여 모든 종류의 문제가 발생합니다. 데이터베이스의 데이터에 대한 행당 제한을 초과 할 가능성은 말할 것도 없습니다 (이러한 255 자 필드가 몇 개 이상있는 경우).

처음에 합리적인 제한을 선택하고 애플리케이션과 데이터베이스를 통해 적용하는 것이 훨씬 쉽습니다.


0

필요한 것보다 약간만 할당하는 것이 좋습니다. 전화 번호는 이렇게 커지지 않을 것입니다.

한 가지 이유는 큰 항목에 대해 유효성을 검사하지 않는 한 누군가가있는 모든 항목을 사용한다는 것입니다. 그러면 행의 공간이 부족할 수 있습니다. MySQL 제한에 대해 잘 모르겠지만 8060은 MS SQL의 최대 행 수입니다.

더 일반적인 기본값은 50 imho이며 필요한 경우 증가합니다.


감사. 나는 그것이 좋은 습관이라는 것에 확실히 동의합니다. 내가 정말로 명확히하고 싶은 성능 측면
Olly

0

mysql 컨텍스트에서는 mysql이 최대 값을 가지고 있기 때문에 언급 된 varchar 열의 인덱스로 작업 할 때 중요해질 수 있습니다. 인덱스 행당 767 바이트로 제한됩니다.

즉, 여러 varchar 255 열에 인덱스를 추가 할 때 위의 답변에서 지적한대로 utf8 또는 utf8mb4 열에서이 제한에 다소 빠르게 / 더 빨리 도달 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.