MySQL VARCHAR 크기의 성능 영향


45

varchar 크기간에 MySQL의 성능 차이가 있습니까? 예를 들어, varchar(25)varchar(64000). 그렇지 않은 경우 공간이 부족하지 않도록 최대 크기의 모든 varchar를 선언하지 않는 이유가 있습니까?


3
+1이 질문은 모든 DBMS와 유사하게 적용됩니다. 내 관찰에 따르면 많은 varchar 크기가 커지는 경향이 있습니다.
bernd_k

5
MySQL은 아니지만 Depesz의이 블로그 게시물이 PostgreSQL에 대한 질문에 답변 할 수 있습니다 .
xenoterracide

답변:


29

CHAR 대 VARCHAR 사용의 장단점을 인식해야합니다

CHAR 필드를 사용하면 할당하는 것이 정확히 얻는 것입니다. 예를 들어, CHAR (15)는 필드에 문자를 배치하는 방법에 관계없이 15 바이트를 할당하고 저장합니다. 데이터 필드의 크기를 완전히 예측할 수 있으므로 문자열 조작이 간단하고 간단합니다.

VARCHAR 필드를 사용하면 완전히 다른 이야기를 얻을 수 있습니다. 예를 들어, VARCHAR (15)는 실제로는 최대 16 바이트, 데이터의 경우 최대 15 바이트, 데이터의 길이를 저장하기 위해 최소 1 개의 추가 바이트를 동적으로 할당합니다. 저장할 문자열 'hello'가 6 바이트가 아닌 경우 5가 아닙니다. 문자열 조작은 항상 모든 형태의 길이 검사를 수행해야합니다.

두 가지 작업을 수행 할 때 절충이보다 분명해집니다.
1. 수백만 또는 수십억 개의 행 저장
2. CHAR 또는 VARCHAR 인 색인화 열

무역 # 1

가변 길이 데이터가 더 작은 행을 생성하여 더 작은 실제 파일을 생성하므로 VARCHAR은 이점을 가지고 있습니다.

무역 # 2

CHAR 필드는 고정 필드 너비로 인해 문자열 조작이 덜 필요하므로 CHAR 필드에 대한 인덱스 조회는 VARCHAR 필드보다 평균 20 % 빠릅니다. 이것은 내 추측에 해당되지 않습니다. MySQL Database Design and Tuning 책 은 이것을 증명하기 위해 MyISAM 테이블에서 놀라운 것을 수행했습니다. 이 책의 예제는 다음과 같은 작업을 수행했습니다.

ALTER TABLE tblname ROW_FORMAT=FIXED;

이 지시문은 VARCHAR이 CHAR로 작동하도록합니다. 나는 2007 년 이전 직장에서이 작업을 수행했으며 300GB 테이블을 가져 와서 다른 것을 변경하지 않고 인덱스 조회를 20 % 늘 렸습니다. 출판 된대로 작동했습니다. 그러나 거의 두 배 크기의 테이블을 만들었지 만 단순히 트레이드 오프 # 1로 돌아갑니다.

저장된 데이터를 분석하여 MySQL이 열 정의에 권장하는 것을 확인할 수 있습니다. 테이블에 대해 다음을 실행하십시오.

SELECT * FROM tblname PROCEDURE ANALYSE();

그러면 전체 테이블을 순회하며 포함 된 데이터, 최소 필드 값, 최대 필드 값 등을 기준으로 모든 열에 대한 열 정의를 권장합니다. 때로는 CHAR 대 VARCHAR을 계획 할 때 상식을 사용해야합니다. 다음은 좋은 예입니다.

IP 주소를 저장하는 경우 해당 열의 마스크는 최대 15 자 (xxx.xxx.xxx.xxx)입니다. IP 주소의 길이가 그다지 다르지 않으며 추가 바이트로 제어되는 문자열 조작의 복잡성이 증가하기 때문에 CHAR (15)에서 하트 비트로 바로 뛰어 올 것입니다. 이러한 열에 대해 여전히 PROCEDURE ANALYSE ()를 수행 할 수 있습니다. VARCHAR을 권장 할 수도 있습니다. 이 경우 내 돈은 여전히 ​​VARCHAR보다 CHAR에 있습니다.

CHAR 대 VARCHAR 문제는 적절한 계획을 통해서만 해결할 수 있습니다. 큰 힘으로 큰 책임이 따릅니다 (진실이지만 진실)


4
IP 주소를 저장하면 int 이외의 다른 주소로 저장할 이유가 없습니다. 그게 전부 IP 주소입니다. 많은 언어에는 일종의 ip2int 기능이 있습니다. 당신이 명령 줄 호출의 편리함을 원하는 경우가 ABCD를 변환하는 저장 프로 시저를 만들 어렵지 않다 :의 펑 (256,3) + (B)의 펑 (256,2) + C * 256 + D
atxdba

1
mysql에 자체 ip2int 함수가 있다고 생각합니다. INET_ATON
atxdba

3
@atxdba : 내 대답의 요점은 CHAR 대 VARCHAR을 사용하는 것입니다. 문자열 문자 크기가 15에 가까우므로 IP를 예로 사용합니다. 따라서 VARCHAR을 위해 안정적인 CHAR 크기를 반올림하는 것은 질문 자체를위한 예일뿐입니다. IP 주소를 표현하는 더 나은 방법에 대한 귀하의 의견은 매우 유효하며 가장 합리적입니다.
RolandoMySQLDBA

CHAR (15)는 바이트가 아닌 15 자를 할당 합니다 . utf8의 경우 45 바이트 입니다.
Rick James

2
이것은 CHAR / VARCHAR 비교에 대한 좋은 대답이지만 다른 VARCHAR 크기에 대한 질문이었습니다.
수집기

13

이에 대한 대답은 실제로 다소 복잡합니다. 짧은 버전 : 차이가 있습니다.

  1. 결과 (예 : GROUP BY명령문) 를 필터링하기 위해 임시 테이블을 작성할 때 전체 길이가 할당됩니다.

  2. 유선 프로토콜 (행을 클라이언트에 전송)은 더 큰 길이를 할당 할 것입니다.

  3. 스토리지 엔진이 적절한 varchar를 구현하지 않을 수도 있습니다.

(2) 나는 유선 프로토콜이 친숙한 것이 아니라는 것을 인정하지만, 일반적인 조언은 길이를 추측하기 위해 최소한의 노력을 기울이는 것입니다.


지적 할 가치가 있습니다. MySQL 5.7은 정렬 버퍼 (가변 길이)에 값을 압축 할 수 있습니다. mysqlserverteam.com/…
Morgan Tocker

9

이 스레드의 대부분의 답변은 5 세이며 InnoDB와 utf8이 기본값이되기 전에 작성되었습니다. 다시 시작하겠습니다 ...

쿼리에 내부 임시 테이블이 필요한 경우 테이블을 사용하려고 MEMORY합니다. 그러나 MEMORY는

  • TEXT/ BLOB열을 가져올 수 없습니다 TINYTEXT.
  • VARCHAR 현재 버전에서는 512보다 약간 더 큽니다.

또한, 그주의 VARCHARs로 전환된다 CHARs. 따라서 열의 내용에 관계없이 765 바이트 VARCHAR(255)CHARACTER SET utf8확장됩니다. 그런 다음 트리거 될 수 있습니다.

  • 경우 MEMORY테이블 중 하나를보다 더 얻는다 max_heap_table_size 거나 tmp_table_size , 그것은의 MyISAM로 변환하고 잠재적으로 디스크에 유출됩니다.

따라서 VARCHAR(25)더 머무를 가능성이 높 MEMORY으므로 더 빠릅니다. (255)좋은으로하지 않고, (64000)나쁘다.

(미래에 임시 테이블은 아마도 InnoDB이며이 답변의 일부를 수정해야 할 것입니다.)


6

크기가 큰 varchar 열은 전체 테이블에 대한 쿼리가 임시 테이블을 사용하기 쉽습니다. 고성능 MySQL 책에 따르면. 옵티마이 저가 메모리에서이 쿼리를 실행할 수 있는지 확인하거나 임시 테이블이 필요한 경우 테이블 정의를 기반으로 행 크기를 확인합니다. 즉, 속도로 인해 64K 문자를 얼마나 많이 보려고하지는 않습니다. 실제로 사용하고 있습니다. 그렇기 때문에 작가는 열에 들어가는 실제 가능한 값을 넘어서 그 정의 방식을 확장하지 말 것을 권장합니다. 실제로 실제 데이터 크기가 RAM에 적합하더라도 임시 테이블에 대한 추가 쿼리에 대해 스스로를 설정 한 경우 이제 피할 수있는 I / O 페널티가 발생했습니다.


그것은 매우 신선한 관점입니다. 이 책이 당신이 참조하는 책 ( amazon.com/MySQL-High-Availability-Building-Centers/dp/… ) 이라면 책 의 페이지 번호를 답장에 넣으십시오. +1 !!!
RolandoMySQLDBA

바보 나 ... 고성능되지 가용성 : amazon.com/High-Performance-MySQL-Optimization-Replication/dp/...는 ... 페이지 번호가 237분의 236입니다 그것은 VARCHAR 컬럼을 정의 관대함이 현명 할 수있는 방법에 대해 설명합니다. 이 책은 5.1이 나왔을 때 다시 쓰여 졌음을 명심하십시오. 내년에는 5.5의 모든 BIG 변경 사항을 포함하여 다음과 같이 변경 될 것입니다. 변경 될 수 있습니다 :)
TechieGurl

페이지 236은 특정 문자 집합에 속하는 데이터 정렬을 언급합니다. VARCHAR에게는 불쾌한 일일 수 있습니다. 237 페이지의 238 페이지의 그림 5-5와 함께 클라이언트 / 서버 통신 설정에 또 다른 이유가 있습니다. 문자 집합을 번역하는 과정. VARCHAR에 대한 또 다른 불쾌한 모험.
RolandoMySQLDBA

명확히하기 위해이 섹션에서 MySQL이 크기를 만들 것이라고 말할 수는 없지만 작업이 임시 테이블을 필요로 할 때 테이블이 MEMORY Engine에 있고 THAT는 항상 문자열을 수정 청크에 저장하므로 관대합니다. 정의는 필요한 메모리 임시 테이블을 RAM에 머무르는 대신 디스크로
옮길 수 있습니다

@RolandoMySQLDBA. 네 ... 너무 ... 조합은 여기에 (당신이 UTF-8을 사용하고 비 라틴 문자가 할 ESP 경우) 요인이되고 디스크에 더 빠른 여행에 메모리 엔진 테이블과 리드를 처리 할 때 그것은 모든 단지 나중에 사망
TechieGurl

5

더 작은 필드는 인덱스에서 직접 포함 할 수 없지만 더 긴 필드는 직접 계산할 수 없다는 것을 이해합니다. 이러한 제한으로 인해 문자열을 인덱싱 가능하게하려면 더 짧게 유지해야합니다. 그렇지 않으면 아니요, 두 varchar의 정렬 방식이므로 정렬 또는 비교와 같은 ops는 필드가 25이든 MAX이든 관계없이 같은 시간에 작동합니다.


3

공간이 부족하지 않도록하십시오

이 문구는 데이터베이스에 저장할 데이터에 대해 잘 모르기 때문에 질문을한다는 것을 의미합니다. 이것이 사실이라면 용량 계획에 필요하기 때문에 가능한 빨리 알아볼 수 있습니다. 예를 들어, 7000 자로 된 데이터 요소를 얻는 경우 DBMS에 성능 영향을 줄 수 있으므로 알아야합니다.

즉, 예상 내용과 관련된 열 크기를 선호합니다. 예를 들어, 국가 코드와 내선 번호를 포함하더라도 전화 번호는 50자를 초과하지 않을 수 있습니다. 마찬가지로 우편 번호는 20 자 이하 여야합니다.

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