Day 82
- 실전 프로젝트
오늘은 스프링 배치의 이론적 내용을 공부하고 이번주에 주구장창했던 mysql의 인덱스의 장점과 한계에 대해서 정리해봤다. 아무래도 내일이 멘토링이니 정리해서 현상황을 알려주는 것이 좋다고 판단했기 때문이다. 그리고 갑자기 쓰레드와 프로세스의 개념을 좀 더 명확하게 알고싶어서 그 부분을 공부해봤다. 여러 영상을 보면서 명확한 개념보다는 전체적인 흐름과 핵심을 알아내려고 노력했다. 가장 기억에 남는 말은 '프로세스는 프로그램의 인스턴스다.' 라는 말이다. 인스턴스가 뭔지 아니까 바로 이해가됐다. 이렇게 조금씩 CS지식도 늘려갈 필요가 있따고 생각한다. 오늘은 아래에 아까 정리한 mysql 인덱스의 장점과 한계를 적고 마무리하겠다.
장점
- 검색 속도가 매우 빨라진다.
- 인덱싱된 컬럼은 정렬이 되기 때문
- 복합 인덱스를 사용하면 한 번에 다수의 인덱스를 태울 수 있다.
- 그리고 앞에 있는 컬럼은 단독으로도 인덱스 사용 가능
한계
하나의 쿼리에 다수의 인덱스 사용 불가
복합인덱스를 사용하면 여러개의 컬럼에 인덱스를 사용할 수 있다. 하지만 그 한계도 명확하다. a b c의 순서로 복합인덱스를 형성했다면 a는 단독으로 인덱스를 이용할 수 있지만 b나 c는 그렇지 못하다. 여러 인덱스를 사용할 수는 있지만 독립적으로 사용하기에는 한계가 있다.
그렇다고 해서 하나의 쿼리에 여러 단독 인덱스를 태우는 것은 가능하냐? 그것도 아니다. mysql은 하나으 쿼리에 최적의 인덱스를 골라서 하나만 태워준다. 그래서 현재 우리가 진행중인 프로젝트에 맞지 않다고 판단했다. 여러 가지의 필터를 적용시키면 필연적으로 여러 조건이 붙게 되는데 많은 조건중에서 딱 한 가지만 인덱스를 건다? 힘들다. 그리고 이미 검색에 있어서 fulltext 인덱스는 필수이기 때문에 카테고리를 비롯하여 다른 세부 필터는 인덱스 적용이 불가하다.
그럼 쿼리는 하나가 아닌 여러개의 쿼리들로 나누면 되지않을까?
첫 번째로 서브쿼리를 활용해서 쿼리를 분리해봤다. 하지만 결국 서브쿼리들의 결과와 어떤 조건에 맞춰서 조인을 해야하는데 대부분 id equal 조건을 사용한다. 그러면 설정한 인덱스를 타지 못하고 PRIMARY키의 기본 인덱스로 구성된다.
그러면 강제로 인덱스를 타게 하면 되지않을까? 그것도 안되는 것같다. SQL의 실행순서를 보면 ON절의 조건을 확인하고 JOIN을 진행한다. JOIN에서의 서브쿼리가 실행되고 ON절의 조건까지 하나의 과정으 보는 것 같아서 옵티마이저가 설정한 PRIMARY 인덱스가 최적이지 않을까? 하는 생각을 가지고 있다.
두 번째로는 실제로 쿼리를 여러 번 나누어서 결과를 받아온 뒤 서버에서 교집합의 데이터만 추출하는 방법이 있다. 이렇게 하면 모든 쿼리가 원하는 인덱스를 타서 결과를 받아온다. 하지만 문제가 많은 방법이다. 우선 모든 결과의 교집합을 구한 뒤 정렬을 할 수 있으므로 각각의 조회 쿼리에 LIMIT 조건을 넣을 수 없다. 즉, 조회시 모든 결과를 받아와야 한다. 여기서부터 부하가 굉장히 심하다. 그리고 어찌어찌 데이터들을 받아왔다고 쳐도 이 값들의 교집합을 구하는 것도 많은 시간을 소요한다. 로컬에서 테스트 했을 경우에 한 40초 정도가 소요되었다.
정확도 문제
Fulltext 검색은 우선적으로 정확도를 기준으로 정렬된다. 그럼 정확도는 어떻게 계산되는 것일까? 그건 아래의 글을 참고하자.
가장 큰 차이점은 검색 대상의 문자열 길이가 점수에 영향을 끼치냐 그렇지 않냐하는 문제다. fulltext는 검색 빈도와 전체 row수 검색된 row수만 가지고 점수를 매긴다. 엘라스틱 서치도 비슷하긴하지만 길이도 점수에 반영된다. 검색 대상의 문자열의 길이가 평균 길이보다 길면 점수가 낮아지게 된다. 그러면 우리가 겪었던 세트나 패키지가 항상 상위에 올라왔던 문제들을 어느정도는 해결할 수 있지 않을까 하는 생각을 해본다.
parser 종류
fulltext는 기본적으로 stop word와 ngram parser를 제공한다. 하지만 두 파서 모두 장단점이 분명하다. stop word는 띄어쓰기를 기준으로 인덱싱을 하는데 검색 시 앞에 와일드카드를 붙이면 인덱스를 탈 수없다. 검색속도는 향상되었지만 정확도와 검색 범위의 부분에서는 아쉬운 부분이 많았다.
ngram은 한글이나 일본어같이 띄어쓰기로 정확한 단어 구분이 되지않는 글자들을 위해서 만들어지 파서다. 이 파서를 사용하면 stop word보다 정확한 검색이 가능하다. boolean mode를 사용하면 인덱싱된 순서까지 적용되니 stop word보다는 더 확실한 값을 반환해준다. 속도도 stop word와 비슷한 수준이다. 하지만 치명적인 단점이 있는데, 영어를 검색하면 너무느려서 검색이 불가능할 정도다. 영어는 2글자씩 인덱싱하면(n=2가 기본세팅) 인덱스 수와 해당되는 수가 엄청 많아서 조회하고 점수를 매기는데 시간이 많이 소요됐다고 판단한다.
와일드카드 postfix 안됨
위에서 언급했지만 stop word를 사용하면 앞에 와일드카드를 붙이는 것이 불가능하다. ngram을 사용해서 문제를 해결할 수는 있지만 그러면 영어 검색을 포기해야 한다. 대용량 데이터 검색 시 fulltext 인덱스에 대한 mysql은 한계는 명확했다.
'항해99 > TIL | WIL' 카테고리의 다른 글
| WIL(11주) (0) | 2023.04.02 |
|---|---|
| 2023.04.01 (83일) (0) | 2023.04.02 |
| 2023.03.30 (81일) (0) | 2023.03.31 |
| 2023.03.29 (80일) (0) | 2023.03.29 |
| 2023.03.28 (79일) (0) | 2023.03.29 |