답변:
비슷한 질문을하기 전에
여기 내 대답의 발췌가 있습니다.
CHAR 대 VARCHAR 사용의 장단점을 인식해야합니다
CHAR 필드를 사용하면 할당하는 것이 정확히 얻는 것입니다. 예를 들어, CHAR (15)는 필드에 문자를 배치하는 방법에 관계없이 15 바이트를 할당하고 저장합니다. 데이터 필드의 크기를 완전히 예측할 수 있으므로 문자열 조작이 간단하고 간단합니다.
VARCHAR 필드를 사용하면 완전히 다른 이야기를 얻을 수 있습니다. 예를 들어 VARCHAR (15)는 실제로는 최대 16 바이트, 데이터의 경우 최대 15 바이트, 데이터의 길이를 저장하기 위해 최소 1 개의 추가 바이트를 동적으로 할당합니다. 저장할 문자열 'hello'가 6 바이트가 아닌 경우 5가 아닙니다. 문자열 조작은 항상 모든 형태의 길이 검사를 수행해야합니다.
다음 두 가지 작업을 수행하면 절충이 더 분명해집니다. 1. 수백만 또는 수십억 개의 행 저장 2. CHAR 또는 VARCHAR 인 색인화 열
TRADEOFF # 1 가변 길이 데이터는 더 작은 행을 생성하므로 더 작은 실제 파일을 생성하므로 VARCHAR은 이점을 갖습니다.
TRADEOFF # 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)입니다. CHAR(15)
IP 주소의 길이는 그다지 다르지 않으며 추가 바이트로 제어되는 문자열 조작의 복잡성이 증가하기 때문에 하트 비트에서 바로 뛰어 넘을 것입니다. 당신은 여전히 그런 PROCEDURE ANALYSE()
열에 대해 반대 할 수 있습니다 . VARCHAR을 권장 할 수도 있습니다. 이 경우 내 돈은 여전히 VARCHAR보다 CHAR에 있습니다.
CHAR 대 VARCHAR 문제는 적절한 계획을 통해서만 해결할 수 있습니다. 큰 힘으로 큰 책임이 따릅니다 (진실이지만 사실).
최신 정보
MD5에 관해서 strlen
는 전체 행 형식을 전환 할 때 내부 계산을 제거해야합니다. 필드 정의를 변경할 필요가 없습니다.
MD5 키가 유일한 VARCHAR이면, 키 행을 사용하여 테이블 행 형식을 fixed로 변환합니다 . 많은 수의 다른 VARCHAR 필드가있는 경우에도 도움이됩니다. 그 대가로 테이블의 크기가 약 두 배로 확장되었습니다. 그러나 추가 조정 없이도 쿼리 속도가 약 20 % 증가합니다.
bit
와 binary
?
로 변환하여 값당 1 바이트 또는 약 3 %를 절약하는 것처럼 보입니다 char
. 어쨌든 MD5 를 16 진수 로 저장하면 그만한 가치가 없습니다 binary
. 대신에 50 %를 절약 할 수 있습니다.
멀티 바이트 문자 집합을 사용하는 경우 32 바이트 이상을 사용할char(32)
수 있다고 지적한 Ovais (주석 참조)에게 감사합니다 .
unhex
16 진수 문자열을 이진수로 변환하는 함수를 사용해야 함을 지적한 Rick James에게 감사합니다 .
create table foo(bar varbinary(100)); insert into foo(bar) values(md5('a')); insert into foo(bar) values(unhex(md5('a')));
select length(bar) from foo;
| 길이 (bar) | | ---------- : | | 32 | | 16 |
db <> 바이올린 여기
binary
오해 되었습니까?
BINARY
하지 않으면로 변경하는 것이 거의 없습니다 UNHEX()
. 즉 당신이 저장할 수있다 UNHEX(MD5(x))
16 바이트로 BINARY(16)
저장 비해 상당한 공간을 절약하기 MD5(x)
로 CHAR(32) CHARACTER SET ascii
.
내 의견으로는 바꿀 가치가 없습니다. 여기에서 문서를 살펴보면 두 문서의 차이점을 설명해야합니다. 사용 시나리오에서 행 크기와 관련된 추가 오버 헤드에 대해 염려하지 않는 한 실제로 다른 것에 비해 큰 이점을 제공하지 않습니다.
http://dev.mysql.com/doc/refman/5.0/en/char.html
또한 위에 링크 된 문서에 대한 첫 번째 주석을 참고하십시오 ... "CHAR은 전체 레코드의 크기가 고정 된 경우에만 액세스 속도를 높입니다. 즉, 가변 크기 개체를 사용하는 경우 모든 개체를 만들 수도 있습니다. VARCHAR도 포함하는 테이블에서 CHAR을 사용하면 속도가 나지 않습니다. "