
show variables like 'version';
select @version;
기본적으로 MySQL과 오라클은 데이터가 저장되는 스토리지 구조 측면에서 큰 차이를 보인다. 오라클은 통합된 스토리지 하나를 공유하여 사용하는 방식이지만 MySQL은 물리적인 DB 서버마다 독립적으로 스토리지를 할당하여 구성한다.
오라클은 아래 그림과 같이 공유 스토리지를 사용하므로 사용자가 어느 DB 서버에 접속하여 SQL을 수행하더라도 같은 결과를 출력하거나 동일한 구문을 처리할 수 있다.

반면 MySQL은 독립적인 스토리지 할당에 기반을 두고, 이중화를 위한 클러스터나 복제 구성으로 운영하더라도 보통은 마스터-슬레이브 구조가 대부분이다. 이때 마스터 노드는 R/W를 모두 수행할 수 있고 슬레이브 노드는 읽기 처리만 수행 가능하다.
다시 말해, 물리적으로 여러 대의 MySQL DB 서버에 접속하더라도 동일 구문이 처리되지 않을 수 있으며 DB 서버마다 각자의 역할이 부여될 수 있다. 쿼리문이 수행하는 서버의 위치를 파악하고 튜닝을 진행하면 물리적인 위치 특성이 내포된 쿼리 튜닝을 수행할 수 있다.
아래 그림은 마스터-슬레이브 구조로 구축된 두 대의 MySQL 서버를 보여준다. 애플리케이션을 통해 쿼리 오프로딩이 적용되므로 마스터 노드에서는 UPATE,INSERT,DELETE 문을 수행하고 슬레이브 노드에서는 SELECT 문을 수행한다. 만약 SELECT 문에 대한 쿼리 튜닝을 마스터 노드에서 수행하거나, UPDATE 문에 대한 쿼리 튜닝을 슬레이브 노드에 접속해서 수행한다면 어떨까? 정상적인 결과가 도출되지 않을 것이다. 구축된 DB 서버의 구조를 충분히 이해하고 적합한 서버에 접근하여 쿼리 튜닝을 수행하는 것이 중요하다.
다만, 각 DB 서버의 OS 설정 ,할당된 스토리지 크기, 시스템 변수, 하드웨어 사양 등이 같다면 마스터 노드 중심으로 쿼리 튜닝을 진행해도 무방하다.

쿼리 오프로딩
DB 서버의 트랜잭션에서 쓰기 트랜잭션과 읽기 트랜잭션을 분리하여 DB 처리량을 증가시키는 성능 향상 기법이다.
Null 대체
MySQL에서는 IFNULL(열명, '대체값') 을 사용한다.
SELECT IFNULL(col1, 'N/A') col1 FROM tab;
오라클에서는 NVL(열명, '대체값') 을 사용한다.
SELECT NVL(col1, 'N/A') col1 FROM tab;
페이징 처리
MySQL에서는 LIMIT 을 오라클에서는 ROWNUM 을 사용한다.
--MySQL
SELECT col1 FROM tab LIMIT 5;
--Oracle
SELECT col1 FROM tab WHERE ROWNUM<=5;
현재 날짜
MySQL에서는 NOW() 를 사용하고 오라클에서는 SYSDATE 키워드를 사용한다. MySQL은 FROM 절없이 현재 날짜를 출력할 수 있지만 오라클은 가상 테이블을 명시해야 현재 날짜를 출력할 수 있다.
--MySQL
SELECT NOW() AS date;
--Oracle
SELECT SYSDATE AS date FROM dual;
조건문
MySQL은 IF 와 CASE WHEN-THEN 을 사용하며 오라클에서는 DECODE , IF 와 CASE WHEN-THEN 을 사용한다.
--MySQL
SELECT IF(col1='A', 'apple', '-') AS col1 FROM tab;
--Oracle
SELECT DECODE(col1, 'A', 'apple', '-') AS col1 FROM tab;
날짜 형식
MySQL에서는 DATE_FORMAT(날짜열, '형식') 을 오라클에서는 TO_CHAR(날짜열, '형식') 을 사용한다.
--MySQL
SELECT DATE_FORMAT(NOW(), '%Y%m%d %H%i%s') AS date;
--Oracle
SELECT TO_CHAR(SYSDATE, 'YYYYMMDD HH24MISS') AS date FROM DUAL;
자동 증가값
MariaDB와 오라클에서는 각각 시퀀스라는 오브젝트를 활용한다(오라클 시퀀스는 기존 데이터보다 작은 값으로 순번을 매길 수도 있다). 먼저 CREATE SEQUENCE 문으로 시퀀스 오브젝트를 생성한 뒤, 해당 시퀀스명으로 함수를 호출하여 신규 숫자를 채번할 수 있습니다. 이때 SELECT 시퀀스명.nextval FROM dual; 구문으로 신규 데이터의 시퀀스 숫자를 가져온다.
한편 MySQL에서는 다음 두 방법으로 자동 증가값을 저장한다.
auto_increment 를 명시하는 방법--MySQL
CREATE TABLE tab(
seq INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(20) NOT NULL
);
--MariaDB 10.3 이상
CREATE SEQUENCE MARIA_SEQ_SAMPLE
INCREMENT BY 1
START WITH 1
MINVALUE 1
MAXVALUE 999999999999
CYCLE
CACHE;
SELECT NEXTVAL(MARIA_SEQ_SAMPLE);
--Oracle
CREATE SEQUENCE ORACLE_SEQ_SAMPLE
INCREMENT BY 1
START WITH 1
MINVALUE 1
MAXVALUE 999999999999
CYCLE
CACHE;
SELECT ORABLE_SEQ_SAMPLE.NEXTVAL FROM DUAL;
문자 결합
MySQL에서는 CONCAT 을 사용하고 오라클에서는 || 이나 CONCAT 을 사용한다.
--MySQL
SELECT CONCAT('A', 'B') TEXT;
--Oracle
SELECT 'A'||'B' TEXT FROM DUAL;
SELECT CONCAT('A','B') TEXT;
문자 추출
MySQL에서는 SUBSTRING 을 오라클에서는 SUBSTR 를 사용한다.
--MySQL
SELECT SUBSTRING('ABCDE',2,3) AS sub_string; -- 결과 BCD
--Oracle
SELECT SUBSTR('ABCDE', 2, 3) AS sub_string FROM DUAL;
MySQL/MariaDB는 대다수의 SQL문이 중첩 루프 조인 알고리즘으로 수행되고, 상용 DBMS와 다르게 수행된 쿼리 결과가 메모리에 적재되는 캐시 기능에 한계가 있으므로(데이터가 변경되면 캐시 내용을 모두 삭제) 일반적인 쿼리 작성 및 튜닝이 통하지 않을 수 있다. 따라서 제공되는 실행 계획 정보를 해석하고 문제에 대응할 수 있는 능력을 갖춘 뒤 쿼리 튜닝을 실행해야 한다.