20250502

mysql json 인덱스

MySQL에서 JSON 인덱스 생성 및 활용 방법

MySQL에서 JSON 타입 컬럼의 특정 값을 빠르게 검색하려면, 해당 값에 대해 인덱스를 생성해야 합니다. JSON 전체에 직접 인덱스를 걸 수는 없고, JSON 내부의 특정 속성을 대상으로 인덱스를 생성하는 것이 일반적입니다.

1. Generated Column(가상/생성 열) + 인덱스

MySQL 5.7 이상에서는 Generated Column(생성 열, 가상 열 또는 저장 열)을 활용하여 JSON 속성을 별도 컬럼으로 추출한 뒤, 이 컬럼에 인덱스를 생성하는 방식이 가장 널리 사용됩니다23613.

예시

sql
-- 1. 가상 컬럼 추가 (예: user라는 키 값 추출) ALTER TABLE customers ADD COLUMN user VARCHAR(100) GENERATED ALWAYS AS (JSON_UNQUOTE(custinfo->'$.user')) STORED; -- 2. 인덱스 생성 ALTER TABLE customers ADD INDEX idx_user (user);
  • VIRTUAL: 실제 데이터 저장 없이 쿼리 시 계산 (디스크 공간 절약, 성능은 다소 낮을 수 있음)

  • STORED: 실제로 값을 저장 (조회 성능 우수, 저장 공간 필요)

쿼리 예시

sql
SELECT * FROM customers WHERE user = 'Jill';

이렇게 하면 해당 인덱스가 사용되어 빠른 검색이 가능합니다.

2. 함수 기반 인덱스(Functional Index)

MySQL 8.0.13 이상에서는 함수 기반 인덱스(Functional Index)를 직접 생성할 수 있습니다.
즉, JSON 추출 함수 결과에 바로 인덱스를 걸 수 있습니다168.

예시

sql
ALTER TABLE customers ADD INDEX idx_user ((CAST(custinfo->>'$.user' AS CHAR(100)) COLLATE utf8mb4_bin));
  • custinfo->>'$.user'는 JSON에서 user 값을 문자열로 추출합니다.

  • COLLATE utf8mb4_bin을 명시해야 인덱스와 쿼리의 정렬 방식이 일치하여 인덱스가 정상적으로 동작합니다1.

쿼리 예시

sql
SELECT * FROM customers WHERE custinfo->>'$.user' = 'Jill';

3. 인덱스 생성 시 주의사항

  • 정렬(COLLATION): 함수 기반 인덱스 생성 시, 인덱스의 collation과 쿼리의 collation이 일치해야 인덱스가 제대로 사용됩니다.
    예를 들어, COLLATE utf8mb4_bin을 명시적으로 지정해야 할 수 있습니다1.

  • 인덱스 오버헤드: 인덱스를 추가하면 검색은 빨라지지만, 데이터 추가/수정/삭제 시에는 인덱스 유지 비용이 발생합니다6.

  • JSON 전체 인덱스 불가: JSON 전체에 인덱스를 걸 수는 없고, 반드시 특정 속성(키)에 대해 인덱스를 생성해야 합니다11.

4. 참고: MySQL 8 이상 JSON 인덱스 예시

sql
ALTER TABLE my_table ADD INDEX idx_json_field ((json_column->>'$.key'));

이렇게 하면 json_columnkey 값에 대해 인덱스가 생성되고, WHERE 조건에서 해당 값을 검색할 때 인덱스를 사용할 수 있습니다689.

요약

  • 가상(생성) 컬럼을 만들고 인덱스 생성 → 가장 일반적, 호환성 높음

  • 함수 기반 인덱스로 바로 생성(MySQL 8.0.13 이상) → 더 간편

  • COLLATE 옵션 주의

  • JSON 전체가 아닌, 특정 키에만 인덱스 가능

이 방식을 적용하면 대용량 JSON 데이터에서도 원하는 값에 대한 빠른 검색이 가능합니다.

Citations:

  1. https://hoing.io/archives/78968
  2. https://iamwhat.tistory.com/65
  3. https://wildeveloperetrain.tistory.com/227
  4. https://ks2colorworld.tistory.com/20
  5. https://mysqldba.tistory.com/278
  6. https://wikidocs.net/226201
  7. https://kangworld.tistory.com/309
  8. https://rawshrimpsushi.tistory.com/78
  9. https://kti.or.kr/mysql%EC%97%90%EC%84%9C%EC%9D%98-json-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B2%98%EB%A6%AC-%EB%B0%A9%EB%B2%95/
  10. https://accept.tistory.com/35
  11. https://devocean.sk.com/blog/techBoardDetail.do?ID=165191&boardType=techBlog
  12. https://oneoneone.kr/content/c4ee16d7
  13. https://knight76.tistory.com/entry/mysql-5714%EB%B6%80%ED%84%B0-%EC%A7%80%EC%9B%90%EB%90%98%EB%8A%94-json-%ED%95%84%EB%93%9C-%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EC%A7%80%EC%9B%90
  14. https://velog.io/@jhbaik1501/MySQL-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D%EC%97%90%EC%84%9C-%EC%83%9D%EA%B8%B4-%EC%84%B1%EB%8A%A5-%EC%9D%B4%EC%8A%88-%ED%95%B4%EA%B2%B0
  15. https://jojoldu.tistory.com/565
  16. https://iamwhat.tistory.com/66
  17. https://wikidocs.net/226252

댓글 없음: