문제 설명
SKILLCODES 테이블은 개발자들이 사용하는 프로그래밍 언어에 대한 정보를 담은 테이블입니다. SKILLCODES 테이블의 구조는 다음과 같으며, NAME, CATEGORY, CODE는 각각 스킬의 이름, 스킬의 범주, 스킬의 코드를 의미합니다. 스킬의 코드는 2진수로 표현했을 때 각 bit로 구분될 수 있도록 2의 제곱수로 구성되어 있습니다.NAME | TYPE | UNIQUE | NULLABLE |
NAME | VARCHAR(N) | Y | N |
CATEGORY | VARCHAR(N) | N | N |
CODE | INTEGER | Y | N |
DEVELOPERS 테이블은 개발자들의 프로그래밍 스킬 정보를 담은 테이블입니다. DEVELOPERS 테이블의 구조는 다음과 같으며, ID, FIRST_NAME, LAST_NAME, EMAIL, SKILL_CODE는 각각 개발자의 ID, 이름, 성, 이메일, 스킬 코드를 의미합니다. SKILL_CODE 컬럼은 INTEGER 타입이고, 2진수로 표현했을 때 각 bit는 SKILLCODES 테이블의 코드를 의미합니다.NAME | TYPE | UNIQUE | NULLABLE |
ID | VARCHAR(N) | Y | N |
FIRST_NAME | VARCHAR(N) | N | Y |
LAST_NAME | VARCHAR(N) | N | Y |
EMAIL | VARCHAR(N) | Y | N |
SKILL_CODE | INTEGER | N | N |
예를 들어 어떤 개발자의
SKILL_CODE가 400 (=b'110010000')이라면, 이는 SKILLCODES 테이블에서 CODE가 256 (=b'100000000'), 128 (=b'10000000'), 16 (=b'10000') 에 해당하는 스킬을 가졌다는 것을 의미합니다.예시
예를 들어
SKILLCODES 테이블이 다음과 같고,NAME | CATEGORY | CODE |
C++ | Back End | 4 |
JavaScript | Front End | 16 |
Java | Back End | 128 |
Python | Back End | 256 |
C# | Back End | 1024 |
React | Front End | 2048 |
Vue | Front End | 8192 |
Node.js | Back End | 16384 |
DEVELOPERS 테이블이 다음과 같다면ID | FIRST_NAME | LAST_NAME | EMAIL | SKILL_CODE |
D165 | Jerami | Edwards | jerami_edwards@grepp.co | 400 |
D161 | Carsen | Garza | carsen_garza@grepp.co | 2048 |
D164 | Kelly | Grant | kelly_grant@grepp.co | 1024 |
D163 | Luka | Cory | luka_cory@grepp.co | 16384 |
D162 | Cade | Cunningham | cade_cunningham@grepp.co | 8452 |
다음과 같이
DEVELOPERS 테이블에 포함된 개발자 중 Front End 스킬을 가진을 가진 개발자의 정보가 결과에 나와야 합니다.ID | EMAIL | FIRST_NAME | LAST_NAME |
D161 | carsen_garza@grepp.co | Carsen | Garza |
D162 | cade_cunningham@grepp.co | Cade | Cunningham |
D165 | jerami_edwards@grepp.co | Jerami | Edwards |
코드 - JOIN
SELECT
DISTINCT
D.ID,
D.EMAIL,
D.FIRST_NAME,
D.LAST_NAME
FROM
DEVELOPERS D
JOIN
(
SELECT
CODE
FROM
SKILLCODES
WHERE
CATEGORY = 'Front End'
) S
ON
(D.SKILL_CODE & S.CODE) <> 0
ORDER BY
D.ID ASC;
EXPLAIN 예상
Nested loop join
-> full scan / index scan SKILLCODES
-> full scan DEVELOPERS대규모 데이터에서 가장 느림.
코드 - WHERE
SELECT
D.ID,
D.EMAIL,
D.FIRST_NAME,
D.LAST_NAME
FROM
DEVELOPERS D
WHERE
EXISTS (
SELECT
1
FROM
SKILLCODES S
WHERE
S.CATEGORY = 'Front End' AND
(D.SKILL_CODE & S.CODE) <> 0
)
ORDER BY
D.ID ASC;EXPLAIN 예상
Semi-join / exists subquery
-> better optimization코드 - BITWISE & SUM(최적 성능)
SELECT
D.ID,
D.EMAIL,
D.FIRST_NAME,
D.LAST_NAME
FROM
DEVELOPERS D
WHERE
D.SKILL_CODE & (
SELECT
SUM(CODE)
FROM
SKILLCODES
WHERE
CATEGORY = 'Front End'
) <> 0
ORDER BY
D.ID ASC;EXPLAIN 예상
Select SUM() using index
Full or index scan DEVELOPERS
bitwise comparison per row대규모 데이터에서 가장 빠른 방식
성능 비교
방식 | 성능 | 이유 | 추천 상황 |
JOIN | 가장 느릴 가능성 큼 | 조인 연산 + 중복 결과 + 불필요한 스캔 발생 | 어떤 CODE와 매칭되는지 확인해야 할 때 |
WHERE EXISTS | JOIN보다 빠름 | 중복 제거, 조건 충족 시 즉시 종료 | 일반 조건 필터링 |
BITWISE & SUM | 가장 빠름 | 한 번만 SUM 계산 → 단일 비교 | 실 서비스 / 대규모 데이터 / index 활용 |
Share article