인프런 커뮤니티 질문&답변

hoon님의 프로필 이미지

작성한 질문수

Real MySQL 시즌 1 - Part 1

Ep.02 VARCHAR vs TEXT

(1,2강) char, varchar, text 관련 질문

해결된 질문

24.07.06 15:08 작성

·

207

0

  1. utf8mb4 char에서도 varchar와 마찬가지로 변경되는 문자열이 할당된 길이를 넘어버리면 레코드를 다른 공간으로 옮겨야하는 것이겠죠?

    1. 그렇다면 varchar와 마찬가지로 길이가 자주 변경되는 경우 사용하면 안되겠네요. 맞나요?

  2. varchar가 char과 달리 공간을 미리 예약하지 않는다면, varchar(50)에서 50은 무슨 의미인가요?

    1. 2강에 나오는 메모리 버퍼 크기에만 영향을 주는 것인가요?

  3. varchar 타입의 메모리 버퍼 공간은 어떤식으로 사용되는 것인가요?

    1. 예를들어, 메모리 버퍼 공간을 테이블 1개당 1개 만들어서 재활용한다고 하면 varchar(30)는 겨우 (latin기준) 30바이트, varchar(255)는 겨우 255바이트를 사용하니까 메모리 공간 차이가 별로 없을 것 같습니다.

    2. 그래서 테이블 1개당 1개만 사용하는 것은 아닐 것 같은데, 가져오는(예상되는?) row갯수만큼 할당해두는 것이려나요?

  4. (text 디폴트 관련) 표현식이라는 용어를 처음 들어봤는데요, 표현식이 무엇인가요?

    1. 구글에 나이브하게 검색하면 정규표현식만 나오네요.

    2. https://dev.mysql.com/doc/refman/8.4/en/expressions.html 이 문서의 expression을 의미하는 것일까요?

    3. 'abc'와 ('abc') 사이에 어떤 차이가 있는지 궁금합니다.

  5. text는 어떻게 저장되기 때문에 row사이즈 제한에 포함이 안되나요?

    1. 혹시 언제나 오프페이지로 저장되는건가요?

답변 4

0

hoon님의 프로필 이미지
hoon
질문자

2024. 07. 25. 01:08

MySQL 서버에 연결된 컨넥션중에서 해당 테이블을 사용하는 컨넥션의 개수만큼 해당 메모리 공간 예약이 필요합니다.

그렇군요 😃

내부적으로 테이블을 리빌드하며, 온라인으로 컬럼 추가가 불가능합니다.

default를 표현식으로 추가하는 경우는 instant로 컬럼추가가 불가능하군요. 신기하네요.

TEXT 타입은 항상 오프페이지로 저장되는 것은 아닙니다. 하나의 레코드 사이즈가 데이터페이지의 절반 크기보다 작은 경우 가변길이 컬럼의 값은 기존 다른 컬럼들과 함께 동일한 데이터페이지에 저장됩니다.

text는 왜 row사이즈 제한(64KB)에 포함안되는지는 잘 이해가 안되네요. text나 varchar 둘다 오프페이지로도 저장될 수 있고 저장될 수 있어서 비슷한거같은데..

https://dev.mysql.com/doc/refman/8.0/en/column-count-limit.html#row-size-limits 공식문서에도 이유는 안나와있군요 🤔 근데 프로그램이 다 이유가 있는 동작만 하는건 아니니 그냥 그러려니..

 

답변 감사합니다.

좀더 찾아보니 성욱님이 적으신 블로그글에 제 질문과 관련된 내용들이 많이 나오네요.

https://medium.com/daangn/varchar-vs-text-230a718a22a1

0

백은빈님의 프로필 이미지
백은빈
지식공유자

2024. 07. 10. 09:23

안녕하세요.

4.(text 디폴트 관련) 표현식이라는 용어를 처음 들어봤는데요, 표현식이 무엇인가요?
구글에 나이브하게 검색하면 정규표현식만 나오네요.
https://dev.mysql.com/doc/refman/8.4/en/expressions.html 이 문서의 expression을 의미하는 것일까요?
'abc'와 ('abc') 사이에 어떤 차이가 있는지 궁금합니다.

MySQL 공식 문서에서 expression이라는 단어는 여러 페이지에서 언급되고 있는데요. 각 페이지마다 expression이라는 단어가 의미하는 바는 조금씩 다릅니다. 말씀해주신 컬럼의 디폴트 값 관련해서 expression에 대한 내용을 좀 더 확인하고 싶으시다면 아래 문서를 살펴보시는 것이 좋습니다.

표현식은 간단하게는 "어떤 결과를 생성하는 수식"이라고 얘기할 수 있을 것 같은데요. 제가 공유해드린 문서에 나와있듯이 표현식은 하나의 특정한 값이 될 수도 있고, 연산이나 함수의 조합이 될 수도 있습니다. 어떤 컬럼에 default 'abc' 또는 default ('abc')로 디폴트 값을 설정한 경우 결과적으로 컬럼의 기본값으로 'abc'라는 값이 지정되는 것은 동일하지만, MySQL 내부적으로 처리되는 방식이 다릅니다.

표현식으로 디폴트 값을 설정한 경우 지정된 표현식을 바탕으로 디폴트 값을 계산하는 작업이 수행됩니다. (표현식으로 'abc'와 같은 고정값이 주어지더라도 동일하게 동작합니다.)

그래서 아래와 같이 컬럼을 추가하면 내부적으로 테이블을 리빌드하며, 온라인으로 컬럼 추가가 불가능합니다.

ALTER TABLE tab1 ADD COLUMN col1 VARCHAR(100) DEFAULT('abc');

표현식이 아닌 경우에는 온라인으로(algorithm=instant) 빠르게 컬럼 추가가 가능합니다.

ALTER TABLE tab1 ADD COLUMN col1 VARCHAR(100) DEFAULT 'abc';

 

5. text는 어떻게 저장되기 때문에 row사이즈 제한에 포함이 안되나요?
혹시 언제나 오프페이지로 저장되는건가요?

안녕하세요. TEXT 타입은 항상 오프페이지로 저장되는 것은 아닙니다. 하나의 레코드 사이즈가 데이터페이지의 절반 크기보다 작은 경우 가변길이 컬럼의 값은 기존 다른 컬럼들과 함께 동일한 데이터페이지에 저장됩니다.

일반적으로 데이터페이지는 16KB로 설정돼있는데, 이 경우 대략 하나의 레코드 사이즈가 8KB 보다 크게되면 레코드 사이즈가 페이지의 절반보다 작아질 때까지 레코드에서 가변길이 컬럼들에 대해 큰 값부터 하나씩 외부 페이지로 데이터를 옮깁니다.

그리고 레코드의 저장 형식(InnoDB Row Format)에 따라 Off-Page로 저장 시 본래의 데이터 페이지에 얼만큼의 데이터를 남겨둘건지, 어느정도 크기 이내면 레코드 사이즈가 크더라도 Off-Page로 저장되지 않는지 등의 내용이 달라집니다.

MySQL 최신 버전에서 InnoDB 테이블의 기본 레코드 저장 형식은 DYNAMIC인데요. 이 형식에서는 40Bytes 이하인 가변길이 컬럼 값은 Off-Page로 저장되지 않으며, Off-Page 형태로 가변길이 컬럼 값을 저장하는 경우 본래의 데이터페이지에는 외부 페이지를 가리키는 20Byte의 포인터 값만 저장됩니다.

이와 관련해서는 아래 공식 문서 내용을 참고하시면 좋을 것 같습니다.

0

이성욱님의 프로필 이미지
이성욱
지식공유자

2024. 07. 06. 17:28

안녕하세요.

 

1. 그렇다면 varchar와 마찬가지로 길이가 자주 변경되는 경우 사용하면 안되겠네요. 맞나요?

동영상 강의에서도 언급하고 있듯이, CHAR(N)에 명시된 길이보다 바이트수가 길어질 때에 발생하는 현상입니다. 그런데 일반적으로 CHAR 타입은 UTF8MB4 문자 셋과 관계없이 alpha-numeric 문자가 사용되는 경우가 많은데, 이런 경우에는 여전히 CHAR 타입의 강점이 있습니다.

 

2. varchar가 char과 달리 공간을 미리 예약하지 않는다면, varchar(50)에서 50은 무슨 의미인가요?
2강에 나오는 메모리 버퍼 크기에만 영향을 주는 것인가요?

VARCHAR(50) 타입에서 50은, 문자열 타입에 저장 가능한 최대 문자 수를 지정하는 것입니다. VARCHAR(50) 타입이 50 글자를 저장할 수 있는 공간을 미리 예약하진 않지만, 저장 가능한 최대 공간의 크기를 제한하는 용도입니다. CHAR(50)에서 50도 동일하게 공간의 크기를 제한하는 목적도 같이 있는거죠.

 

3. varchar 타입의 메모리 버퍼 공간은 어떤식으로 사용되는 것인가요? 예를들어, 메모리 버퍼 공간을 테이블 1개당 1개 만들어서 재활용한다고 하면 varchar(30)는 겨우 (latin기준) 30바이트, varchar(255)는 겨우 255바이트를 사용하니까 메모리 공간 차이가 별로 없을 것 같습니다. 그래서 테이블 1개당 1개만 사용하는 것은 아닐 것 같은데, 가져오는(예상되는?) row갯수만큼 할당해두는 것이려나요?

MySQL 서버에 연결된 컨넥션중에서 해당 테이블을 사용하는 컨넥션의 개수만큼 해당 메모리 공간 예약이 필요합니다. 이걸 명확히 계산하기 어렵습니다. 지금 예시는 Latin1 VARCHAR(255)를 예시로 말씀하셨는데, 이건 매우 매우 compact 한 예제라고 볼 수 있어요. 일반적으로 테이블에 컬럼이 100개 정도 있는데, 이 100개의 컬럼중에서 VARCHAR(200) 그리고 VARCHAR(1000)이랑 VARCHAR(2000) 등등의 컬럼이 20개 정도만 있어도, 필요한 메모리 공간의 크기는 1000 x 4 x 20 가 되고, 컨넥션중에서 테이블을 동시에 사용하는 컨넥션의 개수를 곱하면 메모리 사용량이 많이 높아질 수도 있습니다. 그렇다고 테이블을 모델링할 때 이 공간을 계산하면서 해야 한다는 것은 아닙니다. 다만 컬럼을 선정할 때, 이런 부분을 염두에 두고 최대한 compact하게 varchar max length를 설정하는 것이 좋다는 의미로 이해하시면 좋을 것 같아요.

 

4번과 5번 질문은 (동영상 강의 내용 확인이 필요한 것 같아서)

강의를 진행해주셨던 백은빈님께서 답변을 주시는 것이 더 정확할 것 같으니, 조금만 기다려주세요.

hoon님의 프로필 이미지

작성한 질문수

질문하기