1. 문자열

    1. SQL표준에서 문자열은 항상 홑따옴표(’’)를 사용해서 표기

    2. MySQL에서는 문자열을 쌍따옴표(””)를 사용해서 표기 가능

    3. SQL표준에서 문자열이 홑따옴표를 포함하는 경우 홑따옴표를 두 번 연속해서 입력

    4. MySQL에서는 쌍따옴표와 홑따옴표를 혼합사용하여 해결

    5. SQL문자열 표기

      (SQL 표준) SELECT * FROM departments WHERE dept_no='d''100';
      
      (SQL 표준) SELECT * FROM departments WHERE dept_no='d"100';
      
      (MySQL only) SELECT * FROM departments WHERE dept_no-"d'001";
      
      (MySQL only) SELECT * FROM departments WHERE dept_no="d""001";
      
  2. 식별자 충돌

    1. SQL에서 식별자(테이블명, 컬럼명 등)가 키워드와 충돌하는 경우 오라클, PostgreSQL에서는 쌍따옴표, 대괄호를 사용해서 해결
    2. MySQL에서는 **백틱(``)**으로 감싸서 해결
    3. MySQL서버의 시스템 변수값에 ANSI_QUOTES를 설정하면, 쌍따옴표는 문자열표기에 사용할 수 없게 되고, 식별자에 백틱(``)대신 쌍따옴표를 사용하여 해결해야함
    4. sql_mode
      1. MySQL의 sql_mode 시스템 변수에 많은 모드가 있는데 ‘ANSI’를 설정하면 SQL표준 표기법만 사용할 수 있게 강제함
  3. 숫자

    1. 숫자표기는 다른 DBMS처럼 따옴표없이 숫자만 입력하면 됨

    2. 만약, 따옴표를 사용하더라도 비교하는 과정에서 비교대상이 숫자라면 문자열을 숫자로 형변환을 하고 비교를 수행

    3. MySQL은 숫자타입과 문자열 타입간의 비교에서 숫자타입을 우선시하기 때문에 문자열을 숫자타입으로 변환하여 비교 수행

      SELECT * FROM tab_test WHERE number_column='10001';
      
      SELECT * FROM tab_test WHERE string_column=10001;
      
    4. 위 첫번째 쿼리는 숫자컬럼과 문자열 상수의 비교이기 때문에 문자열 상수만 숫자타입으로 변환 후 비교 수행

    5. 두번째 쿼리의 경우 문자열 컬럼을 상수와 비교하기 때문에 모든 문자열 컬럼을 숫자타입으로 형변환 후 비교하기 때문에, 인덱스가 있더라도 활용하지 못하게 됨

    6. 만약 string_column에 ‘A’와 같은 문자열이 있다면 형변환이 불가능하여 쿼리가 실패할 수도 있음

    7. 이러한 이유로 숫자는 숫자타입의 컬럼에만 저장하도록 함

  4. 날짜

    1. MySQL은 다른 DBMS와 달리 정해진 형태로 입력만 한다면 자동으로 DATE, DATETIME형식으로 변환하기 때문에 STR_TO_DATE()같은 함수 사용하지 않아도 됨

      SELECT * FROM dept_emp WHERE from_date='2011-04-29';
      
      SELECT * FROM dept_emp WHERE from_date=STR_TO_DATE('2011-04-29', '%Y-%m-%d');
      
    2. 첫번째 쿼리는 날짜 타입의 컬럼과 문자열을 비교하는 경우 MySQL은 문자열값을 DATE타입으로 변환하여 비교

    3. 두번째 쿼리는 문자열을 DATE타입으로 강제 변환하여 비교하는 예제인데, 첫번쨰 쿼리와 차이점은 없음

    4. 두 쿼리 모두 from_date를 문자열로 변환하여 비교하는 것이 아니기 때문에 index활용에서는 문제가 없음

  5. 불리언

    1. BOOL이나 BOOLEAN이라는 타입이 있지만 TINYINT타입의 동의어일 뿐임
    2. INSERT시에는 true, false로 값을 저장할 수 있으나
    3. SELECT하는 과정에서는 0, 1로 조회가 이루어짐(즉, 데이터 상으로는 0, 1로 저장)
    4. false : 0, true : 1
    5. 만약 0,1 과 다른 2, 3의 값도 저장은 가능하지만 true, false와 비교시 비교가 되지 않음
  6. 동등 비교(=, <=>)

    1. 다른 DBMS와 같이 “=”를 통해 비교를 수행
    2. MySQL에서는 “<=>”연산자도 제공하며 “=”와 같은 역할이지만 NULL값에 대한 비교까지 수행 가능
    3. MySQL에서는 “<=>”연산자를 NULL-safe 비교 연산자라고 함
    4. 예시 : SELECT * FROM <table_name> WHERE <string_column> <=> NULL
    5. 특정 컬럼이 null인지 비교할 수 있는 쿼리(null을 하나의 값으로 인식하고 비교)
  7. 부정 비교(!=, <>)

    1. 일반적으로 “<>”를 많이 사용함
    2. 어느것을 사용하더라도 차이는 없지만 하나만 사용하는 것이 가독성에 좋다
  8. NOT연산자(!)

    1. 연산의 결과를 반대로 출력
    2. 부정의 결과값을 정확히 예측어려운 경우 사용 자제
  9. 나누기와 나머지 연산자

    1. 나누기 연산자
      1. “/”: 나누기를 하고 몫과 나누어질 때 까지의 나머지를 가져옴(나머지는 최대 4자리)
      2. “DIV”: 나누기를 수행하고 몫의 정수부분만 가져옴
    2. 나머지 연산자
      1. “%”, “MOD”: 나누기를 수행하고 나머지를 가져옴
  10. LIKE 연산자

    1. REGEXP보다는 단순한 문자열 패턴 비교 연산자이지만 DBMS에서는 LIKE를 더 많이 사용

    2. REGEXP 연산자는 인덱스를 전혀 사용하지 못함

    3. LIKE는 인덱스를 사용해서 처리 가능함

    4. LIKE에서 사용할 수 있는 와일드카드 문자

      1. “%”: 0또는 1개 이상의 모든 문자에 일치
      2. “_”: 정확히 1개의 문자에 일치
    5. 와일드카드 문자 자체를 비교한다면 ESCAPE절을 LIKE조건 뒤에 추가해 이스케이프 문자 설정 가능

      SELECT ‘abc’ LIKE ‘a/%’ ESCAPE ‘/’;
      
    6. 인덱스 활용

      SELECT * FROM employees WHERE first_name LIKE ‘Christ%’;
      
      SELECT * FROM employees WHERE first_name LIKE ‘%rist’;
      
    7. BETWEEN연산자

      1. 크거나 같다작거나 같다라는 두 개의 연산자를 하나로 합친 연산
      SELECT * FROM dept_emp WHERE dept_no=’d001’ AND emp_no=10001;
      
      SELECT * FROM dept_emp WHERE dept_no BETWEEN ‘d003’ AND ‘d005’ AND emp_no=10001;
      
    8. BETWEEN과 IN

      1. BETWEEN은 사실 크다와 작다 비교를 묶어둔 것과 같지만, IN의 경우 동등(=)연산자와 비슷함
      SELECT * FROM dept_emp WHERE dept_no IN (’d003’, ‘d004’, ‘d005’) AND emp_no=10001;
      
    9. 윈도우 함수

      1. 참조 : https://kimsyoung.tistory.com/entry/대표적인-윈도우-함수-6가지-알아보기
    10. LETERAL

      1. 기존 서브쿼리에서는 메인쿼리에 있는 값을 서브쿼리에서 조건절등에 사용할 수 없었음
      2. 하지만, LETERAL을 사용하면 서브쿼리에서 메인쿼리 컬럼을 참조 가능하게 됨
    11. BENCHMARK()

      1. 특정 쿼리등을 입력받은 횟수만큼 반복하고, 걸린시간을 측정할 수 있는 함수
      2. 첫번째 인자로 반복할 횟수, 두번째 인자로 수행할 쿼리를 받음
      3. 주의할 점은 쿼리를 10번 실행하는 것과 BENCHMARK()를 이용하는 것은 차이가 있음
      4. 일반적인 쿼리 10번 실행은 매번 파싱, 최적화, 테이블 잠금 등을 실행
      5. 하지만, BENCHMARK()의 경우 이미 할당한 메모리 자원 공유하는 등 일반적인 실행의 1/10밖에 일어나지 않음
      6. 위 이유로 하나의 쿼리의 성능을 보는 것보다, 두 쿼리를 비교하는 용도로 사용하는 것이 옳음
    12. 드라이빙, 드리븐 테이블

      1. 드라이빙 테이블: 조인시 먼저 접근하는 테이블
      2. 드리븐 테이블: 조인시 나중에 접근하는 테이블
      3. 조인에서 테이블 우선순위는 인덱스 존재 여부, FROM절에서 지정 순서 등에 영향을 받음
      4. 만약 50만건의 드라이빙 테이블을 먼저 드라이빙 한다면 50만번을 반복하며 드리븐 테이블을 탐색
      5. 10만건의 드라이빙 테이블을 먼저 드라이빙 한다면 10만번을 반복하여 드리븐 테이블을 탐색
      6. 위 이유로 레코드수가 적은 테이블부터 드라이빙 하여 검색 영역을 줄여야함
    13. EXPLAIN 참조: https://denodo1.tistory.com/306

    14. SELECT

      1. 쿼리 실행 순서: SELECT절(WHERE 적용 및 조인) → GROUP BY → DISTINCT → HAVING → ORDER BY → LIMIT
      2. 위 순서에서 각 절의 생략은 가능, 순서가 바뀌는 경우는 없음, ORDER BYGROUP BY 절이 있더라도 인덱스를 이용하는 경우 불필요하므로 생략됨
      3. 예외적으로 ORDER BY가 조인보다 먼저 이루어지는 경우: SELECT(WHERE 적용) → ORDER BY → 조인 → LIMIT
      4. 위 순서는 첫번째 테이블을 읽은 후 정렬을 수행하고 나머지 테이블을 읽는 순서, 주로 GROUP BY없이 ORDER BY만 사용된 쿼리에서 발견 가능한 순서
      5. 위 경우를 제외한 순서의 쿼리를 사용하려면 서브쿼리로 작성된 인라인 뷰를 사용해야 함(예: LIMIT을 한 레코드에 대해서 ORDER BY를 수행하고 싶은 경우)
      6. 인라인뷰: 서브쿼리가 FROM 절에서 사용되어 서브쿼리 결과가 하나의 테이블에 대한 뷰처럼 사용됨

      Untitled

      1. WHERE절, ORDER BY절, GROUP BY절에서 인덱스를 사용하려면 가장 중요한 것은 인덱스된 컬럼의 값 자체를 변환하지 않고 사용해야함(아무리 간단한 연산을 하더라도 인덱스를 사용하지 못함)
      2. WHERE절의 인덱스 활용
        1. WHERE절에서 범위 조건문(BETWEEN, <, > 등)은 해당 컬럼은 인덱스를 활용하지만, 그 다음 조건에서는 인덱스 유무 상관없이 인덱스로 사용하지 않음
        2. 추가적으로 WHERE절 조건 컬럼이 변형된 경우 인덱스를 활용하지 못함
        3. 예: SELECT * FROM salaries WHERE salary * 10 = 100000;
        4. 대체: SELECT * FROM salaries WHERE salary = 100000 / 10;
        5. 마지막으로 부정 조건은 인덱스를 활용하지 못함(!=, NOT)
      3. WHERE절에서 조건의 순서와 인덱스 컬럼의 순서는 상관이 없다고 봐도 됨, 서버 옵티마이저는 인덱스를 사용할 수 있는 조건을 뽑아서 최적화 수행
      4. 위의 이유로 조건의 순서보다는 조건을 사용할 수 있는 인덱스가 있는 지가 우선적으로 고려됨
      5. 현재까지는 AND로 연결된 경우만 고려했지만, OR로 연결되는 경우는 상황이 달라짐
      6. 만약 인덱스 스캔인 가능한 컬럼이 조건문에 들어가더라도, OR로 연결된 경우 풀 스캔을 할 수 밖에 없음
      7. GROUP BY
        1. 인덱스 예시 : col_1, col_2, col_3, col_4
        2. 각 컬럼에 비교 연산자를 가지지 않기 때문에 범위 결정, 체크 조건과 같이 구분할 필요는 없음
        3. 명시된 컬럼의 순서인덱스 구성 컬럼의 순서와 같다면 인덱스를 사용할 수 있음
        4. 인덱스 컬럼 중 순서가 뒤에 있는 인덱스 컬럼을 명시하지 않아도 인덱스 사용 가능**(GROUP BY col_1, col_2)**
        5. 인덱스 컬럼 중 순서가 앞에 있는 인덱스 컬럼을 명시하지 않으면 인덱스 사용 불가능**(GROUP BY col_2, col_3)**
        6. 위 경우에서 WHERE 조건절에 앞서 빠진 인덱스 컬럼 조건이 있다면 GROUP BY에서 앞 순서의 인덱스 컬럼을 생략해도 인덱스 활용 가능**(WHERE col_1 = ‘${상수}’ GROUP BY col_2, col_3)**
        7. 순서가 모두 맞더라도 인덱스 컬럼에 없는 컬럼을 명시한 경우도 인덱스 사용 불가**(GROUP BY col_1, col_2, col_3, col_4, col_5)**
      8. ORDER BY
        1. 인덱스 사용 조건을 GROUP BY와 유사함
        2. 다른 조건은 정렬되는 각 컬럼의 오름차순, 내림차순 옵션이 인덱스와 같거나 정반대인 경우만 사용할 수 있음(ORDER BY컬럼이 모두 오름차순, 내림차순이어야 함)!!
      9. Short-Circuit-Evalution
      10. eager operator

INSERT(미완)

03) 사용자 및 권한

4) 아키텍처 구조(미완)

5) 트랜잭션과 잠금(미완)

MySQL의 격리 수준

데이터 암호화

인덱스(미완)

B-Tree 인덱스 활용 조건

MySQL 성능 최적화(미완)