Oracle Database에서 MySQL용 Cloud SQL로 쿼리 변환 및 최적화

이 문서에서는 Oracle®과 MySQL용 Cloud SQL 사이의 기본적인 쿼리 차이를 설명하고 Oracle 기능이 MySQL용 Cloud SQL 기능과 어떻게 연결되는지 보여줍니다. 또한 MySQL용 Cloud SQL의 성능 고려 사항과 Google Cloud에서 쿼리 성능을 분석하고 최적화하는 방법을 살펴봅니다. 이 문서에서는 MySQL용 Cloud SQL을 위한 저장 프로시져 및 트리거를 최적화기 위한 기술을 설명하지만, PL/SQL 코드를 MySQL 저장 프로시져 및 함수로 변환하는 방법은 다루지 않습니다.

Oracle Database에서 MySQL용 Cloud SQL로 쿼리를 변환할 때는 SQL과 관련해서 몇 가지 언어적 차이를 고려해야 합니다. 또한 두 데이터베이스 플랫폼 간에는 서로 다르거나 호환되지 않는 몇 가지 기본 제공 함수가 존재합니다.

기본 쿼리 차이

Oracle과 MySQL용 Cloud SQL 모두 ANSI SQL을 지원하지만, 데이터를 쿼리할 때는 주로 시스템 함수 사용과 관련해서 몇 가지 기본적인 차이가 있습니다.

다음 표에서는 Oracle 및 MySQL용 Cloud SQL에 대한 SELECTFROM 구문의 차이를 보여줍니다.

Oracle 기능 이름 Oracle 구현 MySQL용 Cloud SQL 지원 MySQL용 Cloud SQL 상응
데이터 검색을 위한 SQL 기본 구문 SELECT
FROM
WHERE
GROUP BY
HAVING
ORDER BY
SELECT
FROM
WHERE
GROUP BY
HAVING
ORDER BY
출력 인쇄를 위한 SELECT SELECT 1 FROM DUAL SELECT 1
또는
SELECT 1 FROM DUAL
열 별칭 SELECT COL1 AS C1 SELECT COL1 AS C1
또는
SELECT COL1 C1
테이블 이름 대소문자 구분 대소문자 구분 없음(예: ordersORDERS 모두 테이블 이름으로 사용 가능) 아니요 정의된 테이블 이름에 따라 대소문자 구분(예: orders 또는 ORDERS만 테이블 이름으로 사용 가능)

인라인 뷰

인라인 뷰(파생된 테이블이라고도 함)는 FROM 절에 있는 SELECT 문이며, 서브 쿼리로 사용됩니다. 인라인 뷰는 복합 계산을 없애거나 조인 연산을 제거하고, 여러 개별 쿼리를 간소화된 단일 쿼리로 압축하여 복잡한 쿼리를 간단하게 만드는 데 도움이 될 수 있습니다.

다음 예시에서는 인라인 뷰를 Oracle 11g/12c에서 MySQL용 Cloud SQL로 변환하는 예시를 보여줍니다.

Oracle 11g/12c의 인라인 뷰:

 SELECT FIRST_NAME,
            DEPARTMENT_ID,
            SALARY,
            DATE_COL
     FROM EMPLOYEES,
          (SELECT SYSDATE AS DATE_COL FROM DUAL);

MySQL용 Cloud SQL 5.7에서 사용되는 별칭 포함 뷰:

SELECT FIRST_NAME,
              DEPARTMENT_ID,
              SALARY,
              DATE_COL
       FROM EMPLOYEES, (SELECT SYSDATE() AS DATE_COL FROM DUAL) AS A1;

조인

Oracle의 join 유형은 FULL JOIN을 제외하고 MySQL용 Cloud SQL에서 지원됩니다. MySQL용 Cloud SQL 조인에서는 USING 절, ON 절 대신의 WHERE 절, JOIN 문의 SUBQUERY와 같은 대체 구문 사용이 지원됩니다.

다음 표에서는 JOIN 변환 예시를 보여줍니다.

Oracle JOIN 유형 MySQL용 Cloud SQL 지원 MySQL용 Cloud SQL JOIN 구문
INNER JOIN SELECT E.FIRST_NAME, D.DEPARTMENT_NAME FROM EMPLOYEES E JOIN DEPARTMENTS D ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;
CROSS JOIN SELECT E.FIRST_NAME, D.DEPARTMENT_NAME FROM EMPLOYEES E CROSS JOIN DEPARTMENTS D
FULL JOIN 아니요 LEFTRIGHT JOINS:UNION 사용 고려
SELECT E.FIRST_NAME, D.DEPARTMENT_NAME FROM EMPLOYEES E LEFT JOIN DEPARTMENTS D ON E.DEPARTMENT_ID = D.DEPARTMENT_ID UNION SELECT E.FIRST_NAME, D.DEPARTMENT_NAME FROM EMPLOYEES E RIGHT JOIN DEPARTMENTS D ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;
LEFT JOIN [ OUTER ] SELECT E.FIRST_NAME, D.DEPARTMENT_NAME FROM EMPLOYEES E LEFT JOIN DEPARTMENTS D ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;
RIGHT JOIN [ OUTER ] SELECT E.FIRST_NAME, D.DEPARTMENT_NAME FROM EMPLOYEES E RIGHT JOIN DEPARTMENTS D ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;
SUBQUERY SELECT E.FIRST_NAME, D.DEPARTMENT_NAME FROM EMPLOYEES E JOIN (SELECT * FROM DEPARTMENTS)D ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;

MySQL용 Cloud SQL이 UNIONUNION ALL 함수를 모두 지원하지만 Oracle의 INTERSECTMINUS 함수를 지원하지 않습니다.

  • UNION은 중복 레코드를 없앤 후 두 SELECT 문의 결과 집합을 연결합니다.
  • UNION ALL은 중복 레코드를 없애지 않고 두 SELECT 문의 결과 집합을 연결합니다.
  • INTERSECT는 두 쿼리의 결과 집합 모두에 레코드가 존재할 경우에만 두 SELECT 문의 교집합을 반환합니다.
  • MINUS는 2개 이상의 SELECT 문을 비교하고 두 번째 쿼리로 반환되지 않은 첫 번째 쿼리의 고유 행만 반환합니다.

다음 표에서는 Oracle에서 MySQL용 Cloud SQL로의 몇 가지 변환 예시를 보여줍니다.

Oracle 함수 Oracle 구현 MySQL용 Cloud SQL 지원 MySQL용 Cloud SQL 상응
UNION SELECT COL1 FROM TBL1
UNION
SELECT COL1 FROM TBL2
SELECT COL1 FROM TBL1
UNION
SELECT COL1 FROM TBL2
UNION ALL SELECT COL1 FROM TBL1
UNION ALL
SELECT COL1 FROM TBL2
SELECT COL1 FROM TBL1
UNION ALL
SELECT COL1 FROM TBL2
INTERSECT SELECT COL1 FROM TBL1
INTERSECT
SELECT COL1 FROM TBL2
아니요 SELECT COL1 FROM TBL1
WHERE COL1 IN
(SELECT COL1 FROM TBL2)
MINUS SELECT COL1 FROM TBL1
MINUS
SELECT COL1 FROM TBL2
아니요 SELECT A.COL1 FROM TBL1 A LEFT JOIN TBL2 B ON USING(COL1) WHERE B.COL1 IS NULL

스칼라 및 그룹 함수

MySQL용 Cloud SQL은 광범위한 스칼라(단일 행) 및 집계 함수 목록을 제공합니다. 일부 MySQL용 Cloud SQL 함수는 해당 Oracle 함수와 비슷합니다. 여기에는 이름과 기능이 같은 경우도 있고 이름은 다르지만 기능이 비슷한 경우도 있습니다. 일부 MySQL용 Cloud SQL 함수는 해당 Oracle 함수와 이름이 같아도, 기능이 다를 수 있습니다.

다음 표에서는 Oracle 및 MySQL용 Cloud SQL 문자 함수의 이름 및 기능이 동일한 경우와 변환이 권장되는 경우를 보여줍니다.

Oracle 함수 Oracle 구현 MySQL용 Cloud SQL 상응 MySQL용 Cloud SQL 함수 MySQL용 Cloud SQL 구현
CONCAT 첫 번째 문자열을 두 번째 문자열과 연결하여 반환합니다.
CONCAT('A', 1) = A1
CONCAT CONCAT('A', 1) = A1
CONCAT USING PIPE FNAME |' '| LNAME 아니요 CONCAT CONCAT(FNAME, ' ', LNAME)
LOWER 또는 UPPER 모든 문자를 소문자 또는 대문자로 바꿔서 문자열을 반환합니다.
LOWER('SQL') = sql
LOWER 또는 UPPER LOWER('SQL') = sql
LPAD/RPAD n 문자 길이가 되도록 왼쪽 또는 오른쪽에 expression2의 문자 시퀀스가 채워진 상태로 expression1을 반환합니다.
LPAD('A',3,'*') = **A
LPAD 또는 RPAD LPAD('A',3,'*') = **A
SUBSTR 제공된 문자열에서 x번째 위치(여기에서는 세 번째 문자)부터 시작하여 y 길이에 해당하는 부분을 반환합니다. 문자열의 첫 번째 위치는 1입니다.
SUBSTR('MySQL', 3, 3) = SQL
SUBSTR SUBSTR('MySQL', 3, 3) = SQL
INSTR 제공된 문자열에서 특정 문자열의 위치(색인)를 반환합니다.
INSTR('MySQL', 'y') = 2
INSTR INSTR('MySQL', 'y') = 2
REPLACE 검색어로 발견된 모든 문자열을 대체 문자열로 바꿔서 반환합니다.
REPLACE('ORADB', 'ORA', 'MySQL') = MySQLDB
REPLACE REPLACE('ORADB', 'ORA', 'MySQL') = MySQLDB
TRIM 문자열에서 선행 또는 후행 문자(또는 둘 다)를 자릅니다.
TRIM(both '-' FROM '-MySQL-') = MySQL TRIM(' MySQL ') = MySQL
TRIM TRIM(both '-' FROM '-MySQL-') = MySQL TRIM(' MySQL ') = MySQL
LTRIM/RTRIM 문자열의 왼쪽 또는 오른쪽에서 검색에 표시된 모든 문자를 삭제합니다.
LTRIM(' MySQL', ' ') = MySQL
일부만 LTRIM or RTRIM Oracle LTRIMRTRIM 함수에는 문자열에서 삭제할 선행 또는 후행 문자를 지정하는 두 번째 매개변수가 사용됩니다. MySQL용 Cloud SQL 함수는 제공된 문자열에서 선행 및 후행 공백만 삭제합니다.
LTRIM(' MySQL') = MySQL
ASCII 단일 문자를 입력해서 해당 숫자 ASCII 코드를 반환합니다.
ASCII('A') = 65
ASCII ASCII('A') = 65
CHR 0~225 사이의 숫자 값인 ASCII 코드 값을 해당 문자로 반환합니다.
CHR(65) = A
다른 함수 이름 필요 CHAR MySQL용 Cloud SQL에서는 동일 기능으로 CHAR 함수가 사용되므로, 함수 이름을 변경해야 합니다.
CHAR(65) = A
LENGTH 제공된 문자열의 길이를 반환합니다.
LENGTH('MySQL') = 5
LENGTH LENGTH('MySQL') = 5
REGEXP_REPLACE 정규 표현식 패턴의 문자열을 검색합니다.
REGEXP_REPLACE('John', '[hn].', 'e') = Joe
아니요 해당 없음 MySQL 버전 8부터 지원됩니다. 이를 해결하기 위해서는 가능한 경우 REPLACE 함수를 사용하고, 아니면 논리를 애플리케이션 레이어로 이동합니다.
REGEXP_SUBSTR 정규 표현식 패턴에 대해 문자열을 검색하여 SUBSTR 함수의 기능을 확장합니다.
REGEXP_SUBSTR('https://console.cloud.google.com/sql/instances','https://([[:alnum:]]+\.?){3,4}/?') = https://console.cloud.google.com/
아니요 해당 없음 MySQL 버전 8부터 지원됩니다. 이를 해결하기 위해서는 가능한 경우 SUBSTR 함수를 사용하고, 아니면 논리를 애플리케이션 레이어로 이동합니다.
REGEXP_COUNT 패턴이 소스 문자열에 있는 횟수를 반환합니다. 아니요 해당 없음 MySQL용 Cloud SQL에는 해당 함수가 없습니다. 이 논리를 애플리케이션 레이어로 이동하세요.
REGEXP_INSTR 정규 표현식 패턴에 대해 문자열 위치(색인)를 검색합니다. 아니요 해당 없음 MySQL 버전 8부터 지원됩니다. 이전 버전에서는 이 논리를 애플리케이션 레이어로 이동하세요.
REVERSE 제공된 문자열에 대해 예약된 문자열을 반환합니다.
REVERSE('MySQL') = LQSyM
REVERSE REVERSE('MySQL') = LQSyM

다음 표에서는 Oracle 및 MySQL용 Cloud SQL 숫자 함수의 이름 및 기능이 동일한 경우와 변환이 권장되는 경우를 보여줍니다.

Oracle 함수 Oracle 구현 MySQL용 Cloud SQL 상응 MySQL용 Cloud SQL 함수 MySQL용 Cloud SQL 구현
ABS 제공된 숫자의 절댓값을 반환합니다.
ABS(-4.6) = 4.6
ABS ABS(-4.6) = 4.6
CEIL 제공된 숫자보다 크거나 같은 가장 작은 정수를 반환합니다.
CEIL(21.4) = 22
CEIL CEIL(21.4) = 22
FLOOR 제공된 숫자보다 작거나 같은 가장 큰 정수를 반환합니다.
FLOOR(-23.7) = -24
FLOOR FLOOR(-23.7) = -24
MOD mn으로 나눈 나머지를 반환합니다.
MOD(10, 3) = 1
MOD MOD(10, 3) = 1
ROUND n을 소수점 오른쪽 정수 자릿수로 반올림하여 반환합니다.
ROUND(1.39, 1) = 1.4
ROUND ROUND(1.39, 1) = 1.4
TRUNC(숫자) n1n2 소수점 자릿수로 잘라서 반환합니다. 두 번째 매개변수는 선택사항입니다.
TRUNC(99.999) = 99 TRUNC(99.999, 0) = 99
다른 함수 이름 필요 TRUNCATE(숫자) MySQL용 Cloud SQL 함수는 이름이 다르며, 두 번째 매개변수가 필수입니다.
TRUNCATE(99.999, 0) = 99

다음 표에서는 Oracle 및 MySQL용 Cloud SQL datetime 함수의 이름 및 기능이 동일한 경우와 변환이 권장되는 경우를 보여줍니다.

Oracle 함수 Oracle 구현 MySQL용 Cloud SQL 상응 MySQL용 Cloud SQL 함수 MySQL용 Cloud SQL 구현
SYSDATE 데이터베이스 서버가 있는 운영체제에 설정된 현재 날짜 및 시간을 반환합니다.
SELECT SYSDATE FROM DUAL; = 31-JUL-2019
SYSDATE()

MySQL용 Cloud SQL SYSDATE()는 괄호를 포함해야 하며, 기본적으로 Oracle SYSDATE 함수와 다른 datetime 형식을 반환합니다.

SELECT SYSDATE() FROM DUAL; = 2019-01-31 10:01:01.0

datetime 형식은 세션 수준에서 변경할 수 있습니다.

SYSTIMESTAMP 소수점 이하 초와 시간대를 포함하여 시스템 날짜를 반환합니다.
SELECT SYSTIMESTAMP FROM DUAL = 01-JAN-19 07.37.11.622187000 AM +00:00
다른 함수 이름 필요 CURRENT_ TIMESTAMP MySQL용 Cloud SQL은 기본적으로 다른 datetime 형식을 반환합니다. 출력 형식을 다시 지정하려면 DATE_FORMAT() 함수를 사용합니다.
SELECT CURRENT_TIMESTAMP FROM DUAL; = 2019-01-31 06:55:07
LOCAL_ TIMESTAMP 현재 날짜 및 시간을 TIMESTAMP 형식으로 반환합니다.
SELECT LOCALTIMESTAMP FROM DUAL = 01-JAN-19 10.01.10.123456 PM
다른 datetime 형식 반환 LOCAL_ TIMESTAMP MySQL용 Cloud SQL은 Oracle 기본 형식과 다른 datetime 형식을 반환합니다. 출력 형식을 다시 지정하려면 DATE_FORMAT() 함수를 사용합니다.
SELECT LOCAL_TIMESTAMP FROM DUAL = 2019-01-01 10:01:01.0
CURRENT_DATE 현재 날짜를 반환합니다.
SELECT CURRENT_DATE FROM DUAL = 31-JAN-19
다른 datetime 형식 반환 CURRENT_ DATE MySQL용 Cloud SQL 함수는 다른 datetime 형식을 반환합니다. 출력 형식을 다시 지정하려면 DATE_FORMAT() 함수를 사용합니다.
SELECT CURRENT_DATE FROM DUAL = 2019-01-31
CURRENT_ TIMESTAMP 현재 날짜 및 시간을 반환합니다.
SELECT CURRENT_TIMESTAMP FROM DUAL = 31-JAN-19 06.54.35.543146 AM +00:00
다른 datetime 형식 반환 CURRENT_ TIMESTAMP MySQL용 Cloud SQL 함수는 다른 datetime 형식을 반환합니다. 출력 형식을 다시 지정하려면 DATE_FORMAT() 함수를 사용합니다.
SELECT CURRENT_TIMESTAMP FROM DUAL = 2019-01-31 06:55:07
ADD_MONTHS 날짜와 정수 월을 반환합니다.
ADD_MONTHS(SYSDATE, 1) = 31-JAN-19
다른 함수 이름 필요 ADDDATE MySQL용 Cloud SQL 함수는 다른 datetime 형식을 반환합니다. 출력 형식을 다시 지정하려면 DATE_FORMAT() 함수를 사용합니다.
ADDDATE(SYSDATE(), 1) = 2019-08-01 06:42:49.0
EXTRACT(날짜 부분) 간격 표현식을 기준으로 datetime 필드의 값을 반환합니다.
EXTRACT(YEAR FROM DATE '2019-01-31') = 2019
EXTRACT(날짜 부분) EXTRACT(YEAR FROM DATE '2019-01-31') = 2019
LAST_DAY 제공된 날짜의 월 중 마지막 일자를 반환합니다.
LAST_DAY('01-JAN-2019') = 31-JAN-19
일부만 LAST_DAY MySQL용 Cloud SQL은 Oracle 기본 형식과 다른 datetime 형식을 반환합니다. 출력 형식을 다시 지정하려면 DATE_FORMAT() 함수를 사용합니다.
LAST_DAY('2019-01-01') = 2019-01-31
MONTH_ BETWEEN 제공된 날짜 date1date2:
MONTHS_BETWEEN( SYSDATE, SYSDATE-60) = 1.96 사이의 개월 수를 반환합니다.
일부만 PERIOD_DIFF MySQL용 Cloud SQL PERIOD_DIFF 함수는 두 기간(YYMM 또는 YYYYMM 형식) 사이의 개월 수 차이를 정수 숫자로 반환합니다.
PERIOD_DIFF( '201903', '201901') = 2
TO_CHAR (Datetime) 숫자, datetime, 타임스탬프 형식을 문자열 형식으로 변환합니다.
TO_CHAR( SYSDATE,'DD-MM-YYYY HH24:MI:SS') = 01-01-2019 10:01:01
다른 함수 이름 필요 DATE_FORMAT MySQL용 Cloud SQL DATE_FORMAT 함수는 형식 문자열에 따라 날짜 값의 형식을 지정합니다.
DATE_FORMAT( SYSDATE(),'%d-%m-%Y %H:%i:%s') 01-01-2019 10:01:01

다음 표에서는 Oracle 및 MySQL용 Cloud SQL 인코딩 및 디코딩 함수의 이름 및 기능이 동일한 경우와 변환이 권장되는 경우를 보여줍니다.

Oracle 함수 Oracle 구현 MySQL용 Cloud SQL 상응 MySQL용 Cloud SQL 함수 MySQL용 Cloud SQL 구현
DECODE IF-THEN-ELSE 문의 기능을 사용하여 표현식을 각 검색 값과 하나씩 비교합니다. 아니요 CASE 비슷한 기능에 MySQL용 Cloud SQL CASE 문을 사용합니다.
DUMP 데이터 유형 코드, 바이트 길이, 내부 표현식 표현이 포함된 VARCHAR2 값을 반환합니다. 아니요 해당 없음 지원되지 않음
ORA_HASH 제공된 표현식의 해시 값을 계산합니다. 아니요 MD5 or SHA 128비트 체크섬에는 MD5 함수를 사용하고 160비트 체크섬에는 SHA 함수를 사용합니다.

다음 표에서는 Oracle 및 MySQL용 Cloud SQL 변환 함수의 이름 및 기능이 동일한 경우와 변환이 권장되는 경우를 보여줍니다.

Oracle 함수 Oracle 구현 MySQL용 Cloud SQL 상응 MySQL용 Cloud SQL 함수 MySQL용 Cloud SQL 구현
CAST 기본 제공되는 한 가지 데이터 유형 또는 컬렉션 유형의 값을 다른 기본 제공되는 데이터 유형 또는 컬렉션 유형의 값으로 변환합니다.
CAST('1' as int) + 1 = 2
일부만 CAST 명시적 또는 암시적 변환이 필요한지에 따라 조정합니다.
CAST('1' AS SIGNED) + 1 = 2
CONVERT 한 가지 문자 집합에서 다른 문자 집합으로 문자 문자열을 변환합니다.
CONVERT ( 'Ä Ê Í Õ Ø A B C D E ', 'US7ASCII', 'WE8ISO8859P1') = ?? ?? ?? A B C
일부만 CONVERT MySQL용 Cloud SQL CONVERT 함수는 구문 및 매개변수에 따라 몇 가지 조정이 필요합니다.
CONVERT( 'Ä Ê Í A B C ' USING utf8) = Ä Ê Í A B C
TO_CHAR(문자열/숫자) 이 함수는 숫자 및 날짜를 문자열로 변환합니다.
TO_CHAR(22.73,'$99.9') = $22.7
아니요 FORMAT MySQL용 Cloud SQL FORMAT 함수는 숫자를 #,###,###.##과 같은 형식으로 변환하고, 소수점 자릿수로 반올림한 후 결과를 문자열로 반환합니다.
CONCAT('$', FORMAT(22.73, 1)) = $22.7
TO_DATE Oracle의 TO_DATE 함수는 datetimecode 형식을 기준으로 문자열을 날짜로 변환합니다.
TO_DATE( '2019/01/01', 'yyyy-mm-dd') = 01-JAN-2019
다른 함수 이름 필요 STR_TO_DATE MySQL용 Cloud SQL STR_TO_DATE 함수는 문자열을 입력해서 datetime 형식을 기준으로 날짜를 반환합니다.
STR_TO_DATE( '2019/01/01', '%Y/%m/%d') = 2019-01-01
TO_NUMBER 표현식을 NUMBER 데이터 유형의 값으로 변환합니다.
TO_NUMBER('01234') = 1234
다른 함수 이름 필요 CAST Oracle TO_NUMBER 함수와 동일한 결과를 반환하려면 MySQL용 Cloud SQL CAST 함수를 사용합니다.
CAST('01234' as SIGNED) = 1234

다음 표에서는 Oracle 및 MySQL용 Cloud SQL 조건부 SELECT 함수의 이름 및 기능이 동일한 경우와 변환이 권장되는 경우를 보여줍니다.

Oracle 함수 Oracle 구현 MySQL용 Cloud SQL 상응 MySQL용 Cloud SQL 함수 MySQL용 Cloud SQL 구현
CASE CASE 문은 일련의 조건을 선택하여 다음 구문으로 해당 문을 실행합니다.
CASE WHEN condition THEN result [WHEN ...] [ELSE result] END
CASE CASE 함수 외에도 MySQL용 Cloud SQL는 SELECT 문 내에서 IF/ELSE 조건 처리 사용을 지원합니다.
CASE WHEN condition THEN result [WHEN ...] [ELSE result] END

다음 표에서는 Oracle 및 MySQL용 Cloud SQL null 함수의 이름 및 기능이 동일한 경우와 변환이 권장되는 경우를 보여줍니다.

Oracle 함수 Oracle 구현 MySQL용 Cloud SQL 상응 MySQL용 Cloud SQL 함수 MySQL용 Cloud SQL 구현
COALESCE 표현식 목록에서 null 아닌 첫 번째 표현식을 반환합니다.
COALESCE( null, '1', 'a') = a
COALESCE COALESCE( null, '1', 'a') = 1
NULLIF expression1expression2 사이의 비교를 수행합니다. 두 표현식이 동일하면 함수가 null을 반환합니다. 서로 다르면 함수가 expression1을 반환합니다.
NULLIF('1', '2') = a
NULLIF NULLIF('1', '2') = a
NVL null 값을 쿼리 결과의 문자열로 바꿉니다.
NVL(null, 'a') = a
아니요 IFNULL IFNULL(null, 'a') = a
NVL2 표현식이 null인지 아니면 null이 아닌지에 따라 쿼리로 반환되는 값을 결정합니다. 아니요 CASE CASE 문은 일련의 조건을 선택하여 해당 문을 실행합니다.
CASE WHEN condition THEN result [WHEN ...] [ELSE result] END

다음 표에서는 Oracle 및 MySQL용 Cloud SQL 환경 및 식별자 함수의 이름 및 기능이 동일한 경우와 변환이 권장되는 경우를 보여줍니다.

Oracle 함수 Oracle 구현 MySQL용 Cloud SQL 상응 MySQL용 Cloud SQL 함수 MySQL용 Cloud SQL 구현
SYS_GUID 최대 16바이트로 구성된 전역 고유 식별자(RAW 값)를 생성하고 반환합니다.
SELECT SYS_GUID() FROM DUAL = 8EFA4A31468B4C6DE05011AC0200009E
아니요 REPLACEUUID 이 문제를 해결하려면 REPLACEUUID 함수를 사용하여 SYS_GUID 함수를 시뮬레이션합니다.
REPLACE( UUID(), '-', '')
UID 세션 사용자(로그온된 사용자)를 고유하게 식별하는 정수를 반환합니다.
SELECT UID FROM DUAL = 43
아니요 해당 사항 없음 해당 없음
USER 현재 세션에 연결된 사용자의 사용자 이름을 반환합니다.
SELECT USER FROM DUAL = username
USER + INSTR + SUBSTR MySQL용 Cloud SQL USER 함수는 해당 연결에 대한 사용자 이름 및 호스트 이름(root@IP_ADDRESS)을 반환합니다. 사용자 이름만 검색하려면 추가적인 지원 함수를 사용합니다.
SELECT SUBSTR(USER(), 1, INSTR(USER(), '@') -1) FROM DUAL = root
USERENV 세션 언어와 같은 현재 Oracle 세션에 대한 정보를 반환합니다.
SELECT USERENV('LANGUAGE') FROM DUAL = ENGLISH_AMERICA. AL32UTF8
아니요 SHOW SESSION VARIABLES MySQL용 Cloud SQL SHOW SESSION VARIABLES 문은 현재 세션에 대한 문자열을 반환합니다.
SHOW SESSION VARIABLES LIKE '%collation%'; = utf8_general_ci
ROWID Oracle은 테이블에 있는 행을 식별하기 위해 테이블의 각 행에 고유한 ROWID를 할당합니다. ROWID는 데이터 객체 번호, 행의 데이터 블록, 행 위치, 데이터 파일이 포함된 행의 주소입니다. 일부만 해당 없음 ROW_NUMBER()는 MySQL 8.0부터 사용할 수 있습니다. 이전 버전을 사용 중이면 세션 변수 @row_number를 사용하여 동일한 기능을 에뮬레이션합니다.
ROWNUM Oracle 테이블에서 행이 반환되는 순서를 나타내는 숫자를 반환합니다. 일부만 해당 없음 ROW_NUMBER()는 MySQL 8.0부터 사용할 수 있습니다. 이전 버전을 사용 중이면 세션 변수 @row_number를 사용하여 동일한 기능을 에뮬레이션합니다.

다음 표에서는 Oracle 및 MySQL용 Cloud SQL 집계(그룹) 함수의 이름 및 기능이 동일한 경우와 변환이 권장되는 경우를 보여줍니다.

Oracle 함수 Oracle 구현 MySQL용 Cloud SQL 상응 MySQL용 Cloud SQL 함수 MySQL용 Cloud SQL 구현
AVG 열 또는 표현식의 평균 값을 반환합니다. AVG Oracle과 동일
COUNT 쿼리로 반환된 행 수를 반환합니다. COUNT Oracle과 동일
COUNT (DISTINCT) 열 또는 표현식에 있는 고유 값 수를 반환합니다. COUNT (DISTINCT) Oracle과 동일
MAX 열 또는 표현식의 최댓값을 반환합니다. MAX Oracle과 동일
MIN 열 또는 표현식의 최솟값을 반환합니다. MIN Oracle과 동일
SUM 열 또는 표현식의 값 합계를 반환합니다. SUM Oracle과 동일
LISTAGG ORDER BY 절에 지정된 각 값으로 데이터 순서를 지정하고 측정 열의 값을 연결합니다.
SELECT LISTAGG( DEPARTMENT_NAME, ', ') WITHIN GROUP (ORDER BY DEPARTMENT_NAME) DEPT FROM DEPARTMENTS; -- Single line results = Accounting, Administration, Benefits, Construction
다른 함수 이름 및 구문 필요 GROUP_ CONCAT 동일한 결과를 반환하려면 MySQL용 Cloud SQL GROUP_CONCAT 함수를 사용합니다.
SELECT GROUP_CONCAT( DEPARTMENT_NAME ORDER BY DEPARTMENT_NAME SEPARATOR ', ') DEPT FROM DEPARTMENTS; -- Single line results = Accounting, Administration, Benefits, Construction

다음 표에서는 Oracle 및 MySQL용 Cloud SQL FETCH 함수의 이름 및 기능이 동일한 경우를 보여줍니다.

Oracle 함수 Oracle 구현 MySQL용 Cloud SQL 상응 MySQL용 Cloud SQL 함수 MySQL용 Cloud SQL 구현
FETCH 다중 행 쿼리의 결과 집합에서 지정된 행 수를 검색합니다.
SELECT * FROM EMPLOYEES FETCH FIRST 10 ROWS ONLY;
LIMIT 쿼리에서 행을 검색하려면 MySQL LIMIT 절을 사용합니다.
SELECT * FROM EMPLOYEES LIMIT 10;

기본 필터링, 연산자, 서브 쿼리

기본 필터링, 연산자 함수, 서브 쿼리는 기본적인 작업만 수행해서 비교적 직관적으로 변환할 수 있습니다. Oracle 및 MySQL용 Cloud SQL에 사용되는 기본 날짜 형식이 다르기 때문에 대부분의 작업은 날짜 형식 변환과 관련됩니다.

  • Oracle SYSDATE 함수는 기본적으로 01-AUG-19 형식을 반환합니다.
  • MySQL용 Cloud SQL SYSDATE() 함수는 기본적으로 2019-08-01 12:04:05 형식을 반환합니다.

날짜 및 시간 형식을 설정하려면 MySQL DATE_FORMAT 또는 STR_TO_DATE 함수를 사용합니다.

다음 표에서는 Oracle 및 MySQL용 Cloud SQL 기본 필터링, 연산자 및 서브 쿼리 함수의 이름 및 기능이 동일한 경우와 변환이 권장되는 경우를 보여줍니다.

Oracle 함수 Oracle 구현 MySQL용 Cloud SQL 상응 MySQL용 Cloud SQL 함수
EXISTS/ NOT EXISTS EXISTS/ NOT EXISTS SELECT * FROM DEPARTMENTS D WHERE EXISTS (SELECT 1 FROM EMPLOYEES E WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID);
IN/NOT IN IN/NOT IN SELECT * FROM DEPARTMENTS D WHERE DEPARTMENT_ID IN (SELECT DEPARTMENT_ID FROM EMPLOYEES E); -- OR SELECT * FROM EMPLOYEES WHERE (EMPLOYEE_ID, DEPARTMENT_ID) IN((100, 90));
LIKE/NOT LIKE LIKE/NOT LIKE SELECT * FROM EMPLOYEES WHERE FIRST_NAME LIKE '_e_n%';
BETWEEN/ NOT BETWEEN BETWEEN/ NOT BETWEEN SELECT * FROM EMPLOYEES WHERE EXTRACT(YEAR FROM HIRE_DATE) NOT BETWEEN 2001 and 2004;
AND/OR AND/OR SELECT * FROM EMPLOYEES WHERE DEPARTMENT_ID IN(100, 101) AND (SALARY >= 1000 OR HIRE_DATE <= '2006-02-05');
SubQuery SubQuery MySQL용 Cloud SQL은 SELECT 절과 JOIN 절에서 그리고 WHERE/AND 절에서의 필터링에 대해 서브 쿼리를 지원합니다.
-- SELECT Subquery SELECT D.DEPARTMENT_NAME, (SELECT AVG(SALARY) AS AVG_SAL FROM EMPLOYEES E WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID) AVG_SAL FROM DEPARTMENTS D; -- JOIN Subquery SELECT FIRST_NAME, LAST_NAME, SALARY FROM EMPLOYEES E JOIN (SELECT * FROM DEPARTMENTS WHERE LOCATION_ID = 2700) D ON E.DEPARTMENT_ID = D.DEPARTMENT_ID; -- Filtering Subquery SELECT FIRST_NAME, LAST_NAME, SALARY FROM EMPLOYEES WHERE SALARY < (SELECT AVG(SALARY) FROM EMPLOYEES);
연산자 연산자 MySQL용 Cloud SQL은 모든 기본 연산자를 지원합니다.
> | >= | < | <= | = | <> | !=

MySQL용 Cloud SQL 쿼리 권장사항

MySQL용 Cloud SQL과 Oracle 사이의 성능을 비슷한 수준으로 유지하기 위해서는 쿼리를 최적화해야 할 수 있습니다. 이러한 최적화에는 색인 구조 변경과 데이터베이스 스키마 조정이 포함됩니다. 이 섹션에서는 MySQL용 Cloud SQL에서 비슷한 쿼리 성능을 얻는 데 도움이 되는 몇 가지 가이드라인을 제공합니다.

클러스터링된 인덱스 만들기

InnoDB 스토리지 엔진을 사용할 때 권장사항은 기본 키로 테이블을 정의하는 것입니다. 이 키가 해당 테이블에 클러스터링된 색인을 만들기 때문입니다. 이렇게 하면 쿼리 성능이 향상될 뿐만 아니라 추가적인 보조 색인도 만들 수 있습니다. 물론 색인이 너무 많아지는 것은 피하는 것이 좋습니다. 중복 색인이 있어도 성능은 향상되지 않고 DML 실행이 느려질 수 있습니다. 이 권장사항은 중복 색인을 정기적으로 모니터링해야 하는 두 번째 권장사항으로 이어집니다. 중복 항목이 있으면 데이터베이스에서 이를 삭제해야 합니다.

기본 키를 만들 수 있도록 다음 쿼리를 사용해서 기본 키가 없는 테이블을 식별합니다.

mysql> SELECT t.table_schema, t.table_name
       FROM information_schema.tables t LEFT JOIN
       information_schema.statistics s
       ON t.table_schema=s.table_schema AND t.table_name=s.table_name
       AND s.non_unique=0
       WHERE s.table_name IS NULL
       AND t.table_schema NOT IN('sys', 'information_schema', 'mysql',
       'performance_schema')
       AND t.`TABLE_TYPE` <> 'VIEW';

색인을 만들 수 있도록 다음 쿼리를 사용해서 색인이 없는 테이블을 찾습니다.

mysql> SELECT t.table_schema, t.table_name FROM INFORMATION_SCHEMA.tables t
       WHERE table_name NOT IN
             (SELECT  table_name FROM (
                      SELECT  table_name, index_name
                      FROM information_schema.statistics
                  GROUP BY  table_name, index_name) tab_ind_cols
           GROUP BY table_name)
AND table_schema NOT IN('sys', 'information_schema', 'mysql', 'performance_schema')
AND TABLE_TYPE <> 'VIEW';

중복 항목을 삭제할 수 있도록 다음 쿼리를 사용하여 중복 색인을 확인합니다.

mysql> SELECT * FROM sys.schema_redundant_indexes;

쿼리 매개변수 조정

쿼리 성능을 조정하려면 세션 매개변수를 조정해야 할 수 있습니다. MySQL용 Cloud SQL에는 다음 플래그를 포함하여 이 목적으로 필터링할 수 있는 플래그 집합이 있습니다.

  • InnoDB 관련 매개변수
  • SORT 매개변수
  • JOIN 매개변수
  • 캐시 처리 매개변수

쿼리 모니터링

실행 속도가 느린 쿼리로 인해 시스템이 응답하지 않거나 다른 병목 현상이 발생할 수 있으므로 쿼리를 정기적으로 모니터링하는 것이 중요합니다.

실행이 느린 SQL 문은 여러 방법으로 진단할 수 있습니다.

  • MySQL용 Cloud SQL 대시보드를 사용하여 실행이 느린 쿼리에 대한 실시간 및 이전 정보를 확인합니다.
  • Cloud Monitoring을 사용하여 MySQL용 Cloud SQL에서 느린 쿼리 로그를 모니터링합니다.
  • MySQL용 Cloud SQL statement_analysis 뷰를 사용하여 SQL 문에 대한 런타임 통계를 확인합니다.

    mysql> SELECT * FROM sys.statement_analysis;
    

MySQL용 Cloud SQL 쿼리 분석

MySQL용 Cloud SQL의 쿼리 옵티마이저는 SELECT, INSERT, UPDATE, DELETE 문의 실행 계획을 생성합니다. 이러한 계획은 실행이 느린 쿼리를 조정할 때 유용합니다. 다음 몇 가지 사항에 유의해야 합니다.

  • 실행 계획은 마이그레이션이 필요한 데이터베이스 객체가 아닙니다. 오히려 동일 데이터베이스에서 동일 문을 실행하여 Oracle과 MySQL용 Cloud SQL 사이의 성능 차이를 분석하기 위한 도구입니다.
  • MySQL용 Cloud SQL은 Oracle과 동일한 실행 계획 구문, 기능, 출력을 지원하지 않습니다.

다음은 Oracle 실행 계획과 MySQL용 Cloud SQL 실행 계획 사이의 차이를 보여주는 예시 계획입니다.

SQL> EXPLAIN PLAN FOR
     SELECT * FROM EMPLOYEES WHERE EMPLOYEE_ID = 105;

SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY (FORMAT=>'ALL +OUTLINE'));

Plan hash value: 1833546154

---------------------------------------------------------------------------------------------
| Id  | Operation                   | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |               |     1 |    69 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMPLOYEES     |     1 |    69 |     1   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | EMP_EMP_ID_PK |     1 |       |     0   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------

mysql> EXPLAIN SELECT * FROM EMPLOYEES WHERE EMPLOYEE_ID = 105;

+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table     | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra |
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | EMPLOYEES | NULL       | const | PRIMARY       | PRIMARY | 3       | const |    1 |   100.00 | NULL  |
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+

저장 프로시져와 트리거 최적화

Oracle과 달리 MySQL용 Cloud SQL 저장 프로시져와 함수는 각각 실행될 때 구문 분석됩니다. 저장 프로시져와 함수 성능을 벤치마크하기 위한 유용한 도구는 MySQL BENCHMARK() 유틸리티입니다. 이 도구는 두 매개변수인 반복 횟수와 표현식을 사용해서 제공된 표현식의 런타임을 예상합니다(예: 저장 프로시져, 함수, SELECT 문). 출력은 모든 반복에 대한 대략적인 런타임 합계를 나타냅니다.

다음은 BENCHMARK() 유틸리티를 설명하는 예시입니다.

-- SELECT Expression Example

mysql> select benchmark(10000000, 'select sysdate()');
+-----------------------------------------+
| benchmark(10000000, 'select sysdate()') |
+-----------------------------------------+
|                                       0 |
+-----------------------------------------+
1 row in set (0.12 sec)

-- Result: Run time of 0.12 sec for 1,0000,000 iterations

-- FUNCTION Example
mysql> select benchmark(1000000, func1());
+-----------------------------+
| benchmark(1000000, func1()) |
+-----------------------------+
|                           0 |
+-----------------------------+
1 row in set (2.54 sec)

-- Result: Run time of 2.54 sec for 1,000,000 iterations

변환 중 성능 저하가 눈에 띄면 MySQL EXPLAIN 명령어를 사용하여 성능 저하에 영향을 줄 수 있는 가능한 요소들을 식별합니다. 느린 성능에 대한 일반적인 해결 방법 중 하나는 MySQL 옵티마이저를 사용하도록 테이블 색인 구조를 변경하는 것입니다. 또 다른 일반적인 방법은 불필요한 데이터 검색을 줄이거나 프로시져 MySQL 코드 내에서 임시 테이블을 사용하여 변환된 PL/SQL 코드를 최적화하는 것입니다.

다음 단계

  • MySQL 사용자 계정에 대해 알아보기
  • Google Cloud에 대한 참조 아키텍처, 다이어그램, 권장사항을 살펴봅니다. Cloud 아키텍처 센터 살펴보기