SQL에서 문자열 비교와 대소문자 구분 – LIKE, =, ILIKE의 차이점

Posted by heoncode
2025. 4. 16. 14:14 SQL 기초 정리
728x90
반응형
SMALL

SQL에서 문자열 비교와 대소문자 구분 – LIKE, =, ILIKE의 차이점

SQL에서 문자열을 비교할 때, 사용되는 연산자나 함수에 따라 대소문자 구분 여부가 달라질 수 있습니다. 이로 인해 예상치 못한 결과가 나올 수 있으므로, 문자열 비교 시 어떤 연산자를 사용해야 할지 정확히 이해하는 것이 중요합니다. 이 글에서는 SQL에서 LIKE, =, ILIKE의 차이점과 대소문자 구분에 대해 정리합니다.

1. = 연산자: 정확한 일치 비교

= 연산자는 두 문자열이 완전히 동일한지 비교할 때 사용됩니다. 이 연산자는 대소문자를 구분합니다. 즉, Aa는 다른 값으로 간주됩니다.

예시:

SELECT * FROM users
    WHERE username = 'JohnDoe';

위 쿼리는 username이 정확히 'JohnDoe'인 경우만 반환합니다. 만약 johnDoeJOHNDOE가 있다면 결과에 포함되지 않습니다.

2. LIKE 연산자: 패턴 일치 비교

LIKE 연산자는 문자열의 일부분이 일치하는지 확인할 때 사용됩니다. 이때 대소문자 구분 여부는 사용하는 DBMS에 따라 다릅니다. 예를 들어, MySQL에서는 기본적으로 대소문자를 구분하지 않지만, PostgreSQL에서는 기본적으로 대소문자를 구분합니다.

예시:

SELECT * FROM users
    WHERE username LIKE 'john%';

위 쿼리는 username이 'john'으로 시작하는 모든 값을 반환합니다. MySQL에서는 'john'과 'John'이 모두 매칭될 수 있지만, PostgreSQL에서는 'john'만 매칭됩니다.

3. ILIKE 연산자: 대소문자 구분 없는 비교 (PostgreSQL 전용)

PostgreSQL에서는 ILIKE 연산자를 사용하여 대소문자를 구분하지 않고 문자열을 비교할 수 있습니다. 이 연산자는 LIKE와 동일한 방식으로 패턴을 비교하지만, 대소문자를 무시합니다.

예시:

SELECT * FROM users
    WHERE username ILIKE 'john%';

위 쿼리는 username이 'john', 'John', 'JOHN' 등 어떤 형태든 'john'으로 시작하면 모두 매칭됩니다. 단, ILIKE는 PostgreSQL에서만 사용 가능하므로 다른 DBMS에서는 동작하지 않습니다.

실무 팁

  • Oracle이나 SQL Server에서는 ILIKE가 지원되지 않기 때문에, 대소문자 무시 비교를 하려면 UPPER() 또는 LOWER() 함수를 함께 사용해야 합니다.
  • 인덱스를 활용하고 싶다면 가공된 컬럼(예: LOWER(username))에 대해 별도 인덱스를 생성해야 성능 저하를 방지할 수 있습니다.

예시 (Oracle 기준):

SELECT * FROM users
    WHERE LOWER(username) = 'johndoe';

이렇게 하면 대소문자를 구분하지 않고 비교할 수 있습니다.

결론

SQL에서 문자열 비교 시 대소문자 구분 여부는 연산자와 DBMS에 따라 다릅니다. =는 항상 구분하며, LIKE는 DBMS에 따라 다르고, PostgreSQL에서는 ILIKE로 대소문자 무시 비교가 가능합니다. 실무에서는 이러한 차이를 이해하고 상황에 맞는 비교 방식을 선택해야 합니다.

#sql #문자열비교 #like #ilike #대소문자구분 #sql기초

728x90
반응형
LIST

서브쿼리 성능 최적화 – 서브쿼리에서 성능을 끌어올리는 5가지 방법

Posted by heoncode
2025. 4. 16. 09:12 오라클 실무 쿼리 튜닝
728x90
반응형
SMALL

서브쿼리는 SQL에서 매우 유용하게 쓰이는 기능이지만, 잘못 사용하면 전체 쿼리 성능을 크게 떨어뜨릴 수 있습니다. 특히 실무 환경에서는 서브쿼리가 느려지는 원인을 정확히 파악하고, 효율적으로 개선하는 것이 중요합니다. 이 글에서는 서브쿼리를 성능 저하 없이 사용하는 실전 최적화 팁 5가지를 소개합니다.

1. 불필요한 서브쿼리는 조인으로 대체

단순히 조건 확인용으로 쓰이는 서브쿼리는 조인으로 바꾸는 것이 더 나은 경우가 많습니다. 서브쿼리가 테이블을 여러 번 조회할 가능성이 있기 때문에, 조인으로 바꾸면 물리적 접근 횟수를 줄일 수 있습니다.

예시:

SELECT E.ename, D.dname
FROM emp E
JOIN dept D ON E.deptno = D.deptno
WHERE D.loc = 'DALLAS';

이와 같은 방식으로 WHERE 절 서브쿼리를 JOIN으로 바꾸면 쿼리 최적화에 유리해집니다.

2. 스칼라 서브쿼리는 주의해서 사용

SELECT 절에서 서브쿼리를 쓰는 경우, 특히 테이블 로우마다 반복 실행되기 때문에 성능 저하의 주범이 될 수 있습니다. 이런 경우도 조인으로 바꾸는 게 훨씬 효율적입니다.

비효율적인 예:

SELECT ename,
       (SELECT dname FROM dept D WHERE D.deptno = E.deptno) AS dname
FROM emp E;

대체 가능한 방식:

SELECT E.ename, D.dname
FROM emp E
JOIN dept D ON E.deptno = D.deptno;

3. EXISTS vs IN – 상황에 따라 구분

서브쿼리 안에서 IN을 사용하는 경우와 EXISTS를 사용하는 경우는 성능 차이가 발생할 수 있습니다. 일반적으로 EXISTS는 조건을 만족하는 첫 행만 찾으면 종료되므로 더 빠르게 처리됩니다.

-- EXISTS 예시
SELECT ename
FROM emp E
WHERE EXISTS (SELECT 1 FROM dept D WHERE D.deptno = E.deptno AND D.loc = 'DALLAS');

-- IN 예시
SELECT ename
FROM emp
WHERE deptno IN (SELECT deptno FROM dept WHERE loc = 'DALLAS');

두 방식 모두 테스트 후 더 빠른 쪽을 선택하는 것이 좋습니다.

4. 서브쿼리 결과를 뷰 또는 인라인 뷰로 활용

복잡한 서브쿼리를 여러 번 사용할 경우, 해당 서브쿼리를 뷰로 분리하거나 인라인 뷰로 활용하는 것이 성능을 개선하는 데 도움이 됩니다.

SELECT E.ename, V.dname
FROM emp E
JOIN (SELECT deptno, dname FROM dept WHERE loc = 'DALLAS') V
  ON E.deptno = V.deptno;

이렇게 하면 서브쿼리 결과를 캐시처럼 활용할 수 있어 반복 실행을 방지할 수 있습니다.

5. 서브쿼리 내부에도 인덱스가 필요하다

서브쿼리가 아무리 작아도, 내부에서 WHERE, JOIN, IN 등을 사용하는 경우 해당 조건 컬럼에 인덱스가 없다면 성능 병목이 생깁니다. 서브쿼리라고 해서 옵티마이저가 무시하지 않기 때문에, 내부 테이블의 통계 정보 및 인덱스 구성도 반드시 확인해야 합니다.


서브쿼리는 무조건 나쁘다는 오해가 많지만, 목적과 상황에 맞게 작성하면 충분히 강력한 도구가 됩니다. 위의 팁들을 실제 쿼리에 적용해보고, 옵티마이저 실행 계획을 분석해 보며 성능 개선 효과를 확인해보시기 바랍니다.


#서브쿼리 #SQL성능최적화 #오라클튜닝 #서브쿼리조인 #EXISTSvsIN #인라인뷰

728x90
반응형
LIST