영원히 남는 기록, 재밌게 쓰자

@Lob의 사용, tinytext?, text?, varchar? 무엇을 사용할까..!? 본문

springboot/DB

@Lob의 사용, tinytext?, text?, varchar? 무엇을 사용할까..!?

youngjae-kim 2024. 5. 29. 01:04
728x90
반응형

피드백 게시판 프로젝트를 배포 후 피드백 작성을 페이지에서 직접 해보다가 작성할 수 없다고 오류가 발생했다.

분명 @Lob을 사용했는데..?

@Lob이 Large Object라고 해서 많은 양의 데이터를 저장할 수 있다고 생각했지만 @Lob을 사용한 필드가 MySQL에서 tinytext를 default로 맵핑하는 것을 볼 수 있었다 (@Lob만 사용했을 때).

tinytext는 0~255바이트만큼 데이터를 할당할 수 있는데 내 프로젝트의 요구 사항은 학생들의 피드백이 많을 수도 있기 때문에 넉넉하게 잡아주는 것이 좋다고 생각해서 @Lob을 사용하려고 했다.

 

작성해야 할 내용이 많다고 해서 데이터를 크게 잡기 위해 @Lob을 사용하는 것이 좋은 방법일까?

공식 문서에 mysql이 저장할 수 있는 최대 행 크기는 65535 바이트라고 한다.

 

Lob 데이터의 TEXT,BLOB 타입은 256 바이트가 고정적으로 실제 테이블(in-row storage)에 저장되고, 256 바이트를 넘어가는 경우 2000바이트까지 off-row storage에 저장된다고 한다. 

  1. In-Row Storage:
    • 데이터가 충분히 작으면, 데이터는 테이블의 행에 직접 저장.
  2. Off-Row Storage:
    • 데이터가 256바이트를 초과하는 경우, 데이터는 테이블의 행에 직접 저장되지 않고, 별도의 저장 공간에 저장된다. 이 저장 공간을 "LOB (Large Object) Storage"라고 부를 수 있다. 여기에는 텍스트 데이터나 바이너리 데이터가 저장.
    • 테이블 행에는 이 데이터를 참조하는 포인터(참조 값)만 저장. 이 포인터는 실제 데이터가 저장된 위치를 가리킨다.

 

TINYTEXT와 VARCHAR(255)를 비교했을 때

TINYTEXT와 VARCHAR(255)는 MySQL에서 문자열 데이터를 저장하는 데 사용되는 두 가지 데이터 유형입니다. 이 두 유형의 주요 차이점은 저장 공간, 최대 길이, 사용 방법 등에 있습니다.

  1. 저장 공간과 최대 길이:
    • VARCHAR(255)는 최대 255 문자까지 저장할 수 있으며, 저장되는 실제 문자의 수에 따라 필요한 저장 공간이 달라집니다. 문자열의 길이 정보가 함께 저장되므로, 최대 길이는 255바이트이며, 사용하는 문자 인코딩에 따라 저장할 수 있는 문자의 수가 달라집니다 (예: UTF-8 인코딩에서 한글은 한 글자당 3바이트를 사용하므로 약 85글자까지 저장 가능).
    • TINYTEXT는 최대 255바이트까지 저장할 수 있지만, VARCHAR와 달리 문자열 길이에 상관없이 항상 255바이트의 공간을 차지하는 것이 아니라 실제 저장된 데이터의 크기만큼만 공간을 사용합니다. 그러나 이 또한 사용하는 문자 인코딩에 따라 저장할 수 있는 문자의 수가 달라집니다.
  2. 성능:
    • VARCHAR는 길이가 가변적이기 때문에, TINYTEXT보다 더 효율적으로 공간을 사용할 수 있습니다. 즉, VARCHAR(255)는 필요한 만큼의 공간만 사용하지만, TINYTEXT는 텍스트의 길이에 상관없이 동일한 처리를 해야 하므로 약간 더 많은 오버헤드가 발생할 수 있습니다.
  3. 사용 사례:
    • VARCHAR는 길이가 비교적 짧은 문자열을 저장할 때 주로 사용됩니다. 예를 들어, 이름, 이메일 주소 등의 데이터에 적합합니다.
    • TINYTEXT는 텍스트의 길이가 가변적이거나 약간 더 긴 텍스트를 저장할 때 사용될 수 있습니다. 그러나 TINYTEXT의 최대 저장 가능 크기도 255바이트이므로, 실제로는 VARCHAR(255)와 매우 유사한 사용 사례를 가집니다.

결론적으로, 두 데이터 유형은 비슷한 범위의 데이터를 저장할 수 있지만, 성능과 저장 방식의 차이로 인해 사용 사례에 따라 적합한 유형을 선택하는 것이 중요합니다. 일반적으로는 VARCHAR가 더 널리 사용되며, 특별한 경우가 아니라면 VARCHAR를 선호하는 것이 좋습니다.

 

VARCHAR와 TEXT 타입을 비교했을 때

VARCHAR

  • 데이터의 최대 길이가 상대적으로 짧은 경우
  • 해당 컬럼의 데이터가 테이블을 조회할 때마다 항상 필요할 경우
  • DBMS 서버의 메모리가 (상대적으로) 충분한 경우

TEXT

  • 데이터의 최대 길이가 상대적으로 긴 경우
  • 테이블에서 긴 문자열 데이터를 저장해야 할 컬럼이 여러 개 필요한 경우
  • 해당 컬럼의 데이터가 테이블을 조회할 때마다 필요하지 않은 경우

 

그래서 엔티티나 db 상의 데이터 타입은 무엇이 좋을까...??

돌고 돌아 다시 리팩토링 이슈로 돌아와서 두 가지 방법을 생각해볼 수 있었다. 구글링을 해보면서 정해진 정답은 없다. 자기 프로젝트의 성향과 요구 사항에 맞는 적절한 데이터 타입을 선언해 주는 것이 맞는 것 같다.

 

나는 일단 db에서 tinytext로 지정해주니 너무 짧은 글만 저장할 수 있어서

밑의 경우 중 첫번 째 케이스인 text 타입을 적용해 놓은 상태였다.

@Lob
@Column(columnDefinition = "TEXT")
  • TEXT컬럼으로 맵핑되도록 해서 기존 255바이트만 쓸 수 있던 tinytext 대신 text로 맵핑되도록 하여 65535바이트까지 쓸 수 있도록 하는 것
@Column(length = 500, nullable = false) // 적당한 길이를 요구사항에 맞게 정해주자
  • VARCHAR컬럼으로 맵핑
  • 컬럼 어노테이션과 length 옵션을 추가로 주어 매핑하기.
  • 현재 연결되어 있는 character_set이 utf8mb4이기에 최대 4 byte까지 저장할 수 있어서 적절하게 length를 선언하는 것이 필요하다.

결론은...!!

TEXT 타입을 사용을 고려할 때

  • 데이터의 최대 길이가 상대적으로 긴 경우
  • 테이블에서 긴 문자열 데이터를 저장해야 할 컬럼이 여러 개 필요한 경우
  • 해당 컬럼의 데이터가 테이블을 조회할 때마다 필요하지 않은 경우

다음 상황에서 첫 번째 경우 말고는 2, 3 번째의 경우에 해당하지 않기 때문에 VARCHAR 형으로 변경 후 최대 길이를 지정해주는 방법으로 리팩토링을 진행해야 할 것 같다!!

 

  • 그냥 갑자기 @Lob 어노테이션에 대해서 찾아보다가 적절한 데이터 타입을 쓰는 것에 따라 성능 차이로 이어질 수 있다는 부분에 대해서 공부할 수 있었던 시간이었다.
  • MySQL 공식 문서도 열심히 읽고 해석(번역기 돌리고 이해) 해보며 데이터 타입이 어떻게 저장되는지, innoDB, in/off-row storage 등에 대해서 공부할 수 있었다.

 

 

 

 

참고

https://dev.mysql.com/doc/refman/8.0/en/storage-requirements.html

https://dev.mysql.com/doc/refman/8.0/en/blob.html

https://dkswnkk.tistory.com/714

 

728x90
반응형