회원가입을 하면 원하는 문장을
저장할 수 있어요!
다음
AWS 이용 중이라면 최대 700만 원 지원받으세요
IT 지식이 무엇보다 중요해진 요즘, 여러분은 어떻게 공부하고 있나요? 가장 먼저 눈길이 가는 건 다양한 IT 강의 영상일 겁니다. 강의를 제공하는 교육 기업들과 함께, 요즘IT에서 ‘IT 강의 시리즈’를 준비했습니다. 엄선한 교육 영상을 TEXT로 읽고 필요한 정보를 빠르게 가져가세요.
회원가입을 하면 원하는 문장을
저장할 수 있어요!
다음
회원가입을 하면
성장에 도움이 되는 콘텐츠를
스크랩할 수 있어요!
확인
IT 지식이 무엇보다 중요해진 요즘, 여러분은 어떻게 공부하고 있나요? 가장 먼저 눈길이 가는 건 다양한 IT 강의 영상일 겁니다. 강의를 제공하는 교육 기업들과 함께, 요즘IT에서 ‘IT 강의 시리즈’를 준비했습니다. 엄선한 교육 영상을 TEXT로 읽고 필요한 정보를 빠르게 가져가세요.
이번 강의는 ‘Real MySQL’입니다. 당근마켓 인프라실 DB팀에서 DBA로 근무하는 이성욱, 백은빈 님이 강의를 맡았습니다. MySQL 8.0 버전을 중심으로 실무에 바로 적용할 수 있는 MySQL 활용법을 다루고 있죠. 전체 영상은 인프런에서 확인할 수 있습니다.
Real MySQL 시리즈
① CHAR vs. VARCHAR, 언제 어떻게 써야 할까?
② VARCHAR vs. TEXT, 뭐가 다를까?
안녕하세요, Real MySQL 강의를 진행할 강사 백은빈입니다. 10년간 밀도 높은 DBA 업무를 수행하며, 전통적인 온프레미스 환경부터 최근 주목받고 있는 클라우드 환경까지 다양한 환경에서 DB를 다뤘습니다. MySQL, 몽고DB, 마리아DB를 운영하며 얻은 배움과 경험을 모아 이번 강의를 준비했습니다. 현재 MySQL 프로젝트를 수행하는 개발자 또는 데이터베이스 관리자분들에게 지금 당장 필요한 지식과 경험이 잘 전달되길 바랍니다.
매일 개발할 때 고민해 왔고 앞으로도 고민할 문제, 지금까지는 고민하지 않고 넘겼지만 이제부터 고민해야 할 문제를 다룰 예정입니다. 함께 공부하고 지금까지와는 다른 시각으로 SQL 쿼리를 작성해 보세요.
이번 글에서는 MySQL의 문자열 속성값을 저장하는 VARCHAR(이하 VARCHAR) 타입과 TEXT(이하 TEXT) 타입에 대해 살펴보려고 합니다. 두 타입 모두 실제로 많이 사용되는 타입이라, 두 타입의 차이점이 무엇인지, 어떻게 사용하면 좋은지 등을 알아보겠습니다.
우선 두 타입의 공통점과 차이점에 대해 알아보겠습니다. 먼저 공통점은 VARCHAR와 TEXT는 둘 다 모두 문자열 값을 저장하는 타입이며, 최대로 저장할 수 있는 사이즈도 64K로 동일합니다.
그럼 차이점은 무엇일까요? 먼저 VARCHAR 타입 컬럼에는 지정된 글자 수만큼만 데이터를 저장할 수 있습니다. 예를 들어, VARCHAR 10은 10글자 이하만 저장이 가능합니다. 여기서 바이트가 아니라 글자 수라는 점 참고해 주시면 좋을 것 같습니다.
그리고 TEXT 타입 컬럼은 인덱스 생성 시 반드시 Prefix 길이를 지정해야 인덱스 생성이 가능하고, 그렇지 않은 경우에는 생성이 불가합니다. 또한 인덱스 키로 지정할 수 있는 최대 사이즈를 넘어가는 크기로 길이를 지정하면, 인덱스 생성이 불가합니다. 이 부분은 VARCHAR 타입도 마찬가지입니다.
마지막으로 TEXT 타입 컬럼은 표현식으로만 디폴트 값 지정이 가능합니다. 위 이미지 속 예시로 나와 있는 첫 번째 쿼리처럼, 디폴트 값을 일반 문자열 값을 주는 형태로 지정하면 에러가 발생합니다.
VARCHAR는 이와 같은 형태로 디폴트 값 지정이 가능한 반면에, TEXT 타입의 경우에는 두 번째 쿼리와 같이 괄호로 감싼 표현식 형태로만 디폴트 값을 지정해야 합니다.
그렇다면 VARCHAR 타입과 TEXT 타입 중 어떤 걸 사용해야 할까요? 이를 결정하려면 일반적인 사용 형태를 먼저 살펴봐야 합니다. 대개 저장되는 길이가 짧으면 VARCHAR 타입을, 길이가 길면 TEXT 타입을 사용하는데요.
여기서 길이가 짧다, 길다는 상대적이라고 볼 수 있고, 명확한 길이 기준이 있는 게 아니라서 어떤 타입을 선택하면 좋을지 고민할 수 있습니다.
예를 들어, 사이즈가 큰 데이터를 저장한다고 할 때, VARCHAR(5000)과 TEXT 타입 중에는 어떤 걸 사용하면 좋을까요?
이를 결정하려면 MySQL에서 두 타입을 어떻게 처리하는지를 먼저 살펴봐야 합니다. MySQL에서는 세션에서 어떤 테이블에 저장된 데이터를 읽는다고 할 때, 메모리에 이를 위한 버퍼 공간을 미리 할당해 두고 그걸 유지하면서 재활용합니다.
이 버퍼 공간은 테이블 레코드의 최대 사이즈로 메모리에 할당되는데요. 이때 VARCHAR타입 컬럼의 경우, 이 버퍼 공간에 포함되어 메모리 공간을 재사용할 수 있습니다. TEXT 타입의 경우 그렇지 않고, 그때그때 필요할 때마다 메모리가 할당되고 해제됩니다.
그래서 만약 컬럼 사용이 빈번하고 서버의 메모리 용량도 충분하다면, VARCHAR 타입을 사용하는 게 오버헤드를 조금이라도 줄일 수 있을 것입니다.
그러나 긴 길이의 VARCHAR 컬럼이 테이블에 많이 존재하는 경우, 로우 사이즈 제한에 손쉽게 도달할 수 있습니다. 그래서 테이블에 이미 많은 컬럼이 존재하는 경우라면, 이러한 제한에 크게 영향받지 않는 TEXT 타입 사용을 권장합니다.
또한 어느 정도 짧은 길이의 데이터를 저장할 때도 있을 텐데요. 예를 들어, 30 이하의 길이를 가지는 데이터를 저장한다고 할 때, VARCHAR(30)과 VARCHAR(255) 중 뭐가 더 나을지 고민할 수 있을 것 같습니다.
특히 서드파티 소프트웨어 등에서 DB의 문자열 값을 저장하는 컬럼을 VARCHAR(255)로 설정하는 경우도 많고, 기본적으로 VARCHAR 타입을 255 길이로 사용하는 분들도 더러 있는데요.
앞서 말한 것처럼 메모리의 버퍼 공간을 할당할 때, VARCHAR 컬럼도 포함해서 컬럼에 지정된 최대 길이만큼 메모리 공간을 할당합니다. 따라서 실제 최대 사용하는 길이만큼만 명시해 두는 게 메모리 사용 효율을 높일 수 있다고 볼 수 있습니다.
그리고 VARCHAR 타입은 내부적으로 컬럼에 저장되는 데이터의 길이 정보를 저장하고 있는데요. 이 정보를 저장하기 위해 지정된 길이에 따라, 디스크 공간을 1바이트 또는 2바이트를 사용하게 됩니다. 그래서 디스크 공간 효율 차이도 미미하게 존재할 수 있다는 점도 참고하면 좋습니다.
다음은 VARCHAR와 TEXT 타입 사용 시 주의 사항입니다.
첫 번째로 VARCHAR와 TEXT 컬럼에 저장되는 값의 사이즈가 크면, 오프페이지 형태로 데이터가 저장될 수 있다는 점입니다.
MySQL의 InnoDB 스토리지 엔진은 하나의 레코드 크기가 데이터 페이지의 절반 크기보다 큰 경우, 레코드에서 외부로 저장할 가변 길이 컬럼을 선택하게 됩니다. 그렇게 선택된 컬럼은 별도 외부 페이지의 데이터가 저장됩니다.
실제 다른 컬럼들이 모두 저장된 본래의 데이터 페이지에는 이 외부 페이지를 가리키는 20바이트 포인터 값만 저장이 되는데요. 이렇게 외부에 저장된 페이지를 ‘External Off Page’ 또는 ‘Overflow Page’라고 하며, 아래 그림과 같은 형태입니다.
그리고 테이블에 설정된 InnoDB 로우 포맷에 따라, 외부 페이지로 컬럼 값을 저장할 때 본래의 데이터 페이지에 저장해 두는 값의 사이즈가 다릅니다.
저는 최신 MySQL에서의 기본값인 ‘DYNAMIC’ 로우 포맷을 기준으로 해서, 20바이트 포인터 값이 저장된다고 했는데요. 다른 로우 포맷의 경우, 이와 같은 부분이 다를 수 있다는 점 참고해 주세요.
두 번째 주의 사항은 데이터가 오프페이지로 저장되는 경우, 쿼리에서 오프페이지로 저장된 컬럼을 참조하고 있는지에 따라 쿼리 처리 성능이 매우 달라질 수 있다는 점입니다. 이는 실제 레코드를 읽을 때 기존 데이터 페이지뿐만 아니라, 해당 컬럼에 대해서는 추가적인 데이터 페이지들을 읽어야 하기 때문인데요.
예시를 한번 살펴보겠습니다.
DB에 user_log라는 테이블이 있고, 그 안에 유저의 고유한 id 값이 저장되는 user_id 컬럼과 기타 다른 컬럼들과 함께 extra_info라는 TEXT 타입의 컬럼이 있다고 가정해 볼게요. 그리고 이 extra_info 컬럼에는 오프 페이지로 저장될 만큼의 큰 값이 저장되어 있다고 보겠습니다.
이때 위 오른쪽 그림과 같이 SELECT 쿼리로 테이블의 데이터를 조회한다고 할 때, 이 TEXT 컬럼이 포함된 쿼리와 그렇지 않은 쿼리의 실행 시간을 보면, 상당히 차이가 나는 것을 알 수 있습니다.
오른쪽 쿼리들을 보면, 4배 정도 실행시간이 차이가 나는 것을 확인할 수 있는데요. 그래서 이처럼 테이블 내에 대형 데이터가 저장되어 있고, 이를 SELECT 절에서 항상 함께 참조하는 경우 쿼리가 예상한 것보다 훨씬 느려질 수 있습니다. 따라서 쿼리 작성 시 이와 같은 부분에 대해 주의가 필요합니다.
보통은 쿼리의 WHERE 절에서 이 같은 대형 컬럼을 조건으로 참조하는 경우는 드물고, 대부분 SELECT 절에서 참조합니다. 또 관성적으로 테이블의 모든 컬럼들을 조회하는 경우가 많은데요.
그런 경우 오프 페이지로 저장된 큰 사이즈의 컬럼 데이터를 조회하면 쿼리 성능이 저하되고, DB 서버 자원도 비효율적으로 사용될 수 있으므로, 필요 없는 경우에 한해서는 SELECT 절에서 해당 컬럼을 제외해 주는 것이 좋습니다.
마지막으로 지금까지의 내용을 간추려서 살펴보겠습니다.
만약 컬럼에 저장되는 데이터 사이즈가 상대적으로 많이 크지 않고, 쿼리에서 컬럼 사용이 빈번하며 DB 서버의 메모리 용량이 충분히 큰 경우라면 VARCHAR 타입 사용을 권장합니다. 조금이라도 더 처리가 빠를 수 있기 때문이죠.
반면 저장되는 데이터 사이즈가 큰 편이고, 컬럼을 자주 사용하지 않으면서 테이블에 이미 문자열 타입의 컬럼들이 많이 존재한다면, TEXT 타입이 좋습니다. 로우 사이즈 제한에 영향을 받지 않기 때문입니다.
그리고 VARCHAR 타입을 사용하는 경우, DB 서버의 효율적인 자원 사용을 위해 실제 사용되는 만큼만 길이를 지정하는 것이 좋습니다.
마지막으로 데이터를 조회할 때 쿼리의 SELECT 절에는 가능하면 필요한 컬럼들만 명시하는 것이 좋습니다. 만약 데이터 조회 시 항상 테이블의 모든 컬럼을 읽는다고 하면, 테이블에서 VARCHAR나 TEXT 타입 컬럼에 대형 데이터가 저장된 경우, 대형 데이터를 읽어 들이고 전송하는 데 많은 자원을 소모하기 때문입니다. 이와 같은 경우 쿼리 처리 성능이 매우 저하되고, DB 서버도 부하가 발생할 수 있으므로 주의해야 합니다.
또 한 가지, 만약 필요한 컬럼들만 조회할 때는 경우에 따라 커버링 인덱스, 즉, 인덱스 데이터만 접근하는 형태로도 처리될 수 있는데요. 이 경우 쿼리 처리 효율을 좀 더 높일 수 있어서, 가능하다면 실제로 필요한 컬럼들만 SELECT 절에 명시하는 것이 좋습니다.
원본 강의 보러가기 https://u.inf.run/4fss3D5
요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.