목차
배경
Slack에서 같은 팀원분이 MySql Query에 대해서 질문을 주셨는데 나도 몰랐던 부분이라 이를 알아보고 기억해 두려고 이 문서를 작성한다. 이 문서의 내용은 MySql에서의 비트 연산자가 주제이다.
문제의 Query
문제가 되었던 Query는 다음과 같았다. ( 사내에서 직접 쓰는 Query라서 일부 수정하였다.)
SELECT id, client_id, token
FROM example.EXAMPLE_TABLE
WHERE (flag & 1) != 0 AND
(flag & 2) = 0 AND
(flag & 4) = 0 AND
여기서 & 연산자를 사실 Query에서 처음 보았었고, 결과물이 어떻게 나오는지 몰랐다. 일단 차근차근 하나씩 알아보자.
MySql 비트 연산자
MySql에서 지원하는 비트 연산자는 다음과 같다.
연산자 | 설명 |
---|---|
& | AND 연산을 수행한다. (대응 하는 비트가 둘다 1이면 1을 반환한다.) |
| | OR 연산을 수행한다. (대응 하는 비트중 하나라도 1이면 1을 반환한다.) |
^ | XOR 연산을 수행한다. (대응 하는 비트가 서로 다르면 1을 반환한다.) |
~ | NOT 연산을 수행한다. (비트를 반전시킨다.) |
>> | Right Shift 연산을 수행한다. (부호를 유지한 채로 지정된 수만큼 비트를 오른쪽으로 이동한다.) |
<< | Left Shift 연산을 수행한다. (지정된 수만큼 비트를 왼쪽으로 이동한다.) |
이렇게 봐서는 어떤식으로 나오는지 잘 이해가 안간다. 예시를 보자. 문제가 되는 쿼리에서 flag를 55(110111)를 기준으로 1 ~ 11까지 비트 연산을 해보자.
flag | 연산 숫자 | 결과물_bin | 결과물_dec |
---|---|---|---|
55(110111) | 0(0) | 0 | 0 |
55(110111) | 1(1) | 0 | 1 |
55(110111) | 2(10) | 10 | 2 |
55(110111) | 3(11) | 11 | 3 |
55(110111) | 4(100) | 100 | 4 |
55(110111) | 5(101) | 101 | 5 |
55(110111) | 6(110) | 110 | 6 |
55(110111) | 7(111) | 111 | 7 |
55(110111) | 8(1000) | 0 | 0 |
55(110111) | 9(1001) | 1 | 1 |
55(110111) | 10(1010) | 10 | 2 |
55(110111) | 11(1011) | 11 | 3 |
# 다음 쿼리로 쉽게 확인 할 수 있다.
SELECT 55, BIN(55), 55 & 0, 55 & 1, 55 & 2, 55 & 3, 55 & 4, 55 & 5, 55 & 6, 55 & 7, 55 & 8, 55 & 9, 55 & 10, 55 & 11;
# 여기서 주의할게 연산 결과는 이진수가 아닌 십진수로 나온다. 이거때문에 저게 맞는건가 싶었다.
# BIN() 함수는 십진수를 이진수로 변환해준다.
결과물만 써서 어떤식으로 비트 연산을 하는지 모를수도 있는데, 간단히 예시로 하는법을 설명하면 다음과 같다.
# 55(110111)을 9(1001)로 AND 연산을 하는 경우
110111
1001
------
000001 => 1이 된다.
# 55(110111)을 9(1001)로 OR 연산을 하는 경우
110111
1001
------
111111 => 63이 된다.
# 55(110111)을 9(1001)로 XOR 연산을 하는 경우
110111
1001
------
111110 => 62가 된다.
# 55(110111)을 오른쪽으로 2칸 이동 하는 경우 ( >> 2)
110111
011011 => 1칸 이동
001101 => 2칸 이동, 13이 된다.
# 55(110111)을 왼쪽으로 2칸 이동 하는 경우 ( << 2)
110111
1101110 => 1칸 이동
11011100 => 2칸 이동, 220이된다.
여기서 flag 필드는 int로 선언되어 있다. 비트 연산을 하다가 MAX, MIN 값으로 도달하면 해당 값으로 표시된다. MySql이라고 다를건 없다. 그냥 비트연산자를 써보질 않아서 몰랐던 것일뿐, MySql도 비트 연산자를 쓰고 있다는 것을 기억해두면 좋을 것 같다.
결론
- 결국 MySql도 비트 연산자를 제공하며, Query에 비트연산자가 나오더라도 당황하지 말자.
- BIN() 함수도 기억해 두자.
- 컬럼을 어떤 데이터 형으로 선언했는지에 따라서 연산 결과에 영향을 미칠수 있다.