varchar_patteren_ops는 잘모르겠는데
그냥 각 컬럼 별로 단일 인덱스 추가했다고 가정하자.
여긴 OK


Lower(term.name) 이렇게 칼럼에 함수를 쓰면 당연히 풀스캔함
함수형 인덱스를 만드는 곳은 응급처방에 불과하고
정책 자체를 자동완성 term 테이블에는 항상 소문자로 변환해서 저장되게 해야함

테이블 설계가 잘못됐으니 lower 인덱스 이런걸 쓰는거


이건 내용이 완전히 틀림
exist로 바꾸면 옵티마이저가 내부적으로 semi join으로 다시 바꿔준다 헛고생하는거

INNER JOIN은 모든 행의 매칭 조합을 모두 계산해야 합니다. 반면에 EXISTS는 데이터 존재 여부만 확인하기에 확인만 되면 바로 스캔이 끝나기에 더 유리합니다.
>>> 조인 동작을 잘못 이해하고 있음 선행테이블에서 좁힌 후 하지, 모든 조합 계산 안함




like로 접두사로 하면 충분히 좁혀질텐데 굳이 반정규화도 안할듯

커버링 인덱스는 자제합시다.


저기서 pg는 OR이 인덱스 잘탈지 모르겠는데 해봐야 알음

결론적으로 튜닝을 한다면

1. 정책 자체를 자동완성 키워드는 항상 소문자로 변환 후 저장 후
검색어 like abc%로 타게 / 쿼리 파라미터도 소문자로 넣어줘
2. join은 냅둬라
3. or은 인덱스 안타면 union으로 함
4. 반정규화도 굳이 안해도 됨  저기선 오버엔지니어링임

이정도만 해도 저렇게 인덱스 덕지덕지 안붙여도
충분히 빠름
반정규화 칼럼 업데이트도 필요없어

JPQL은 모르겠고
native query로 쓰면
얼추 아래처럼 짜면 됨

union 각각 안에서 like 인덱스 타면서
결과 뽑고 -> 거기에 대해서 조인 매칭
-> 좁혀진 집합에서 union 처리
->집계 및 정렬 처리 필요시 limit 도


SELECT term, SUM(score) AS total
FROM (
    SELECT t.term, a.score
    FROM term t
    JOIN article a ON ...
    WHERE t.col1 LIKE 'b%'

    UNION

    SELECT t.term, a.score
    FROM term t
    JOIN article a ON ...
    WHERE t.col2 LIKE 'b%'

    UNION

    SELECT t.term, a.score
    FROM term t
    JOIN article a ON ...
    WHERE t.col3 LIKE 'b%'
) s
GROUP BY term
ORDER BY SUM(score) DESC;