このドキュメントでは、Oracle® と Cloud SQL for MySQL の基本的なクエリの違いと、Oracle の機能がどのように Cloud SQL for MySQL の機能に対応するかについて説明します。また、Cloud SQL for MySQL のパフォーマンスに関する考慮事項と、Google Cloudでクエリのパフォーマンスを分析して最適化する方法についても説明します。このドキュメントでは、Cloud SQL for MySQL のストアド プロシージャとトリガーを最適化する手法に触れますが、PL/SQL コードを MySQL のストアド プロシージャと関数に変換する方法については説明しません。
クエリを Oracle Database から Cloud SQL for MySQL に変換する場合は、SQL 言語上の違いについていくつか考慮する必要があります。また、2 つのデータベース プラットフォーム間で異なるか、互換性のない組み込み関数もいくつかあります。
基本的なクエリの違い
Oracle と Cloud SQL for MySQL はどちらも ANSI SQL をサポートしていますが、データのクエリを行う際には、主にシステム関数の使用に関していくつかの基本的な違いがあります。
次の表に、Oracle と Cloud SQL for MySQL の SELECT 構文と FROM 構文の違いを示しています。
| Oracle の機能名 | Oracle の実装 | Cloud SQL for MySQL のサポート | Cloud SQL for MySQL の同等機能 | 
|---|---|---|---|
| データ取得のための SQL 基本構文 | SELECTFROMWHEREGROUP BYHAVINGORDER BY | ○ | SELECTFROMWHEREGROUP BYHAVINGORDER BY | 
| 出力用の SELECT | 
SELECT 1 FROM DUAL
 | ○ | SELECT 1または SELECT 1 FROM DUAL | 
| 列のエイリアス | SELECT COL1 AS C1 | ○ | SELECT COL1 AS C1または SELECT COL1 C1 | 
| テーブル名での大文字と小文字の区別 | 大文字と小文字は区別しない(例: テーブル名として ordersとORDERSのどちらも使用可能) | × | 定義済みのテーブル名に応じて大文字と小文字を区別する(例: テーブル名として ordersかORDERSのいずれかを使用可能)。 | 
インライン ビュー
インライン ビュー(別名、派生テーブル)は FROM 句に指定される SELECT ステートメントであり、サブクエリとして使用されます。インライン ビューを利用して複合計算を削除したり、結合オペレーションを排除したりすると、複雑なクエリをシンプルにできます。また、複数の個別クエリを 1 つの簡素化されたクエリに要約することもできます。
次の例では、インライン ビューでの Oracle 11g/12c から Cloud SQL for MySQL への変換例を示しています。
Oracle 11g/12c のインライン ビュー:
 SELECT FIRST_NAME,
            DEPARTMENT_ID,
            SALARY,
            DATE_COL
     FROM EMPLOYEES,
          (SELECT SYSDATE AS DATE_COL FROM DUAL);
Cloud SQL for MySQL 5.7 のエイリアスを使用した作業ビュー:
SELECT FIRST_NAME,
              DEPARTMENT_ID,
              SALARY,
              DATE_COL
       FROM EMPLOYEES, (SELECT SYSDATE() AS DATE_COL FROM DUAL) AS A1;
結合
Oracle の結合タイプは、FULL JOIN を除いて Cloud SQL for MySQL でサポートされています。Cloud SQL for MySQL の結合では、ON 句、JOIN ステートメントの SUBQUERY 句の代わりに USING 句、WHERE 句などの代替構文が使用できます。
次の表に、JOIN 変換の例を示します。
| Oracle JOINタイプ | Cloud SQL for MySQL のサポート | Cloud SQL for MySQL の 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 | × | UNIONとLEFTの使用およびRIGHT JOINS:
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;
 | 
Cloud SQL for MySQL では UNION 関数と UNION ALL 関数の両方をサポートしていますが、Oracle の INTERSECT 関数と MINUS 関数はサポートしていません。
- UNIONは、重複するレコードを除外してから、2 つの- SELECTステートメントの結果セットをアタッチします。
- UNION ALLは、重複するレコードを除外せずに、2 つの- SELECTステートメントの結果セットをアタッチします。
- INTERSECTは、両方のクエリの結果セットにレコードが存在する場合にのみ、2 つの- SELECTステートメントの共通する部分を返します。
- MINUSは、2 つ以上の- SELECTステートメントを比較し、最初のクエリで 2 番目のクエリから返されない個別の行のみを返します。
次の表に、Oracle から Cloud SQL for MySQL への変換の例をいくつか示します。
| Oracle の関数 | Oracle の実装 | Cloud SQL for MySQL のサポート | Cloud SQL for MySQL の同等機能 | 
|---|---|---|---|
| UNION | SELECT COL1 FROM TBL1UNIONSELECT COL1 FROM TBL2 | ○ | SELECT COL1 FROM TBL1UNIONSELECT COL1 FROM TBL2 | 
| UNION ALL | SELECT COL1 FROM TBL1UNION ALLSELECT COL1 FROM TBL2 | はい | SELECT COL1 FROM TBL1UNION ALLSELECT COL1 FROM TBL2 | 
| INTERSECT | SELECT COL1 FROM TBL1INTERSECTSELECT COL1 FROM TBL2 | いいえ | SELECT COL1 FROM TBL1WHERE COL1 IN(SELECT COL1 FROM TBL2) | 
| MINUS | SELECT COL1 FROM TBL1MINUSSELECT COL1 FROM TBL2 | × | SELECT A.COL1
FROM TBL1 A LEFT JOIN TBL2 B
ON USING(COL1)
WHERE B.COL1 IS NULL
 | 
スカラー関数とグループ関数
Cloud SQL for MySQL には、さまざまなスカラー(単一行)関数と集計関数が用意されています。一部の Cloud SQL for MySQL 関数は、対応する Oracle 関数に非常によく似ています(名前と機能が似ている関数や、名前は異なっていても機能が似ている関数などがあります)。Cloud SQL for MySQL の関数によっては、Oracle での対応する関数名と同じ名前が使用されていても、機能がそれぞれ異なる場合もあります。
次の表に、Oracle と Cloud SQL for MySQL の文字関数で名前と機能が同じ関数と、変換が推奨される関数を記載します。
| Oracle の関数 | Oracle の実装 | Cloud SQL for MySQL の同等機能 | Cloud SQL for MySQL の関数 | Cloud SQL for MySQL の実装 | 
|---|---|---|---|---|
| CONCAT | 最初の文字列を 2 番目の文字列と連結して返します。 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 | expression1の左側または右側に、expression2で指定した文字を連続的に埋め込んでn桁にして返します。LPAD('A',3,'*') = **A | ○ | LPADまたはRPAD | LPAD('A',3,'*') = **A | 
| SUBSTR | 位置 xから始まり(この例では 3)、長さが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 の LTRIM関数とRTRIM関数では、2 番目のパラメータで文字列から削除する先頭または末尾の文字を指定します。Cloud SQL for MySQL 関数では、指定された文字列から先頭と末尾の空白のみを削除します。
LTRIM('  MySQL')
= MySQL
 | 
| ASCII | 1 文字を受け取り、その ASCII コードを数値で返します。 ASCII('A') = 65 | ○ | ASCII | ASCII('A') = 65 | 
| CHR | ASCII コード値(0~225 の数値)を文字に戻します。 CHR(65) = A | 関数名が異なります | CHAR | Cloud SQL for MySQL は同じ機能に 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 | ソース文字列でのパターン出現回数を返します。 | × | なし | Cloud SQL for MySQL で使用できる同等の関数はありません。このロジックはアプリケーション層に移動してください。 | 
| REGEXP_INSTR | 正規表現パターンに一致する文字列の位置(インデックス)を検索します。 | × | なし | MySQL バージョン 8 以降でサポートされます。古いバージョンの場合は、このロジックはアプリケーション層に移動してください。 | 
| REVERSE | 指定された文字列の逆の文字列を返します。 
REVERSE('MySQL')
= LQSyM
 | ○ | REVERSE | 
REVERSE('MySQL')
= LQSyM
 | 
次の表に、Oracle と Cloud SQL for MySQL の数値関数で名前と機能が同じ関数と、変換が推奨される関数を記載します。
| Oracle の関数 | Oracle の実装 | Cloud SQL for MySQL の同等機能 | Cloud SQL for MySQL の関数 | Cloud SQL for MySQL の実装 | 
|---|---|---|---|---|
| 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 | mをnで割った余りを返します。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(number) | n1を小数点以下n2桁に切り捨てて返します。2 番目のパラメータは省略可能です。
TRUNC(99.999) = 99
TRUNC(99.999, 0) = 99
 | 関数名が異なります | TRUNCATE(number) | Cloud SQL for MySQL 関数には別の名前があり、2 番目のパラメータは必須です。 TRUNCATE(99.999, 0) = 99 | 
次の表に、Oracle と Cloud SQL for MySQL の datetime 関数で名前と機能が同じ関数と、変換が推奨される関数を記載します。
| Oracle の関数 | Oracle の実装 | Cloud SQL for MySQL の同等機能 | Cloud SQL for MySQL の関数 | Cloud SQL for MySQL の実装 | 
|---|---|---|---|---|
| SYSDATE | データベース サーバーが存在するオペレーティング システムに設定されている現在の日付と時刻を返します。 
SELECT SYSDATE
FROM DUAL;
= 31-JUL-2019
 | ○ | SYSDATE() | Cloud SQL for MySQL の  
SELECT SYSDATE()
FROM DUAL;
= 2019-01-31 10:01:01.0
 | 
| SYSTIMESTAMP | 小数点以下の秒とタイムゾーンを含む、システムの日付を返します。 
SELECT SYSTIMESTAMP FROM DUAL
= 01-JAN-19 07.37.11.622187000 AM +00:00
 | 関数名が異なります | 
CURRENT_
TIMESTAMP
 | Cloud SQL for MySQL 関数では、デフォルトで異なる 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
 | Cloud SQL for MySQL 関数では、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
 | Cloud SQL for MySQL 関数では、異なる 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
 | Cloud SQL for MySQL 関数では、異なる datetime形式を返します。出力の形式を変更する場合は、DATE_FORMAT()関数を使用します。
SELECT CURRENT_TIMESTAMP
FROM DUAL
= 2019-01-31 06:55:07
 | 
| ADD_MONTHS | 日付と、月を表す整数を返します。 
ADD_MONTHS(SYSDATE, 1)
= 31-JAN-19
 | 関数名が異なります | ADDDATE | Cloud SQL for MySQL 関数では、異なる datetime形式を返します。出力の形式を変更する場合は、DATE_FORMAT()関数を使用します。
ADDDATE(SYSDATE(), 1)
= 2019-08-01 06:42:49.0
 | 
| EXTRACT(date part) | 期間の式に基づいて datetimeフィールドの値を返します。
EXTRACT(YEAR FROM DATE '2019-01-31')
= 2019
 | ○ | EXTRACT(date part) | 
EXTRACT(YEAR FROM DATE '2019-01-31')
= 2019
 | 
| LAST_DAY | 指定された日付の月の最終日を返します。 
LAST_DAY('01-JAN-2019')
= 31-JAN-19
 | 部分的 | LAST_DAY | Cloud SQL for MySQL 関数では、Oracle のデフォルト形式とは異なる datetime形式を返します。出力の形式を変更する場合は、DATE_FORMAT()関数を使用します。
LAST_DAY('2019-01-01')
= 2019-01-31
 | 
| 
MONTH_
BETWEEN
 | 指定された日付 date1とdate2の間の月数を返します。
MONTHS_BETWEEN(
SYSDATE, SYSDATE-60)
= 1.96
 | 部分的 | 
PERIOD_DIFF
 | Cloud SQL for MySQL の PERIOD_DIFF関数は、2 つの日付期間(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 | Cloud SQL for MySQL の DATE_FORMAT関数では、フォーマット文字列に従って日付値をフォーマットします。
DATE_FORMAT(
SYSDATE(),'%d-%m-%Y %H:%i:%s')
01-01-2019 10:01:01
 | 
次の表に、Oracle と Cloud SQL for MySQL のエンコード関数とデコード関数で、名前と機能が同じ関数と、変換が推奨される関数を記載します。
| Oracle の関数 | Oracle の実装 | Cloud SQL for MySQL の同等機能 | Cloud SQL for MySQL の関数 | Cloud SQL for MySQL の実装 | 
|---|---|---|---|---|
| DECODE | IF-THEN-ELSEステートメントの機能を使用して、各検索値を 1 つずつ式と比較します。 | × | CASE | Cloud SQL for MySQL の CASEステートメントを使用して同様の機能を実現します | 
| DUMP | データ型のコード、長さ(バイト数)、式の内部表現を含む VARCHAR2値を返します。 | × | なし | 非対応 | 
| ORA_HASH | 指定した式のハッシュ値を計算します。 | × | MD5 or SHA | 128 ビット チェックサムには MD5関数を使用し、160 ビット チェックサムにはSHA関数を使用します。 | 
次の表に、Oracle と Cloud SQL for MySQL の変換関数で名前と機能が同じ関数と、変換が推奨される関数を記載します。
| Oracle の関数 | Oracle の実装 | Cloud SQL for MySQL の同等機能 | Cloud SQL for MySQL の関数 | Cloud SQL for MySQL の実装 | 
|---|---|---|---|---|
| CAST | 1 つの組み込みデータ型または集合型の値を別の組み込みデータ型または集合型の値に変換します。 
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 | Cloud SQL for MySQL CONVERT関数では、構文とパラメータを調整する必要があります。
CONVERT(
'Ä Ê Í A B C ' USING utf8)
= Ä Ê Í A B C
 | 
| TO_CHAR(string/numeric) | この関数は数値または日付を文字列に変換します。 
TO_CHAR(22.73,'$99.9')
= $22.7
 | × | FORMAT | Cloud SQL for MySQL の 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 | Cloud SQL for MySQL の STR_TO_DATE関数は、文字列を受け取り、datetime形式に基づいて日付を返します。
STR_TO_DATE(
'2019/01/01', '%Y/%m/%d')
= 2019-01-01
 | 
| TO_NUMBER | 式を NUMBERデータ型の値に変換します。
TO_NUMBER('01234')
= 1234
 | 関数名が異なります | CAST | Cloud SQL for MySQL の CAST関数を使用して、Oracle のTO_NUMBER関数と同じ結果を返します。
CAST('01234' as SIGNED)
= 1234
 | 
次の表に、Oracle と Cloud SQL for MySQL の条件付き SELECT 関数で名前と機能が同じ関数と、変換が推奨される関数を記載します。
| Oracle の関数 | Oracle の実装 | Cloud SQL for MySQL の同等機能 | Cloud SQL for MySQL の関数 | Cloud SQL for MySQL の実装 | 
|---|---|---|---|---|
| CASE | CASEステートメントは、一連の条件に基づいて対応するステートメントを選択して実行します。構文は次のとおりです。
CASE WHEN condition THEN result
[WHEN ...] [ELSE result]
END
 | ○ | CASE | Cloud SQL for MySQL では、 CASE関数だけでなく、SELECTステートメント内でIF/ELSEを使用して条件付きの処理を行うこともできます。
CASE WHEN condition THEN result
[WHEN ...] [ELSE result]
END
 | 
次の表に、Oracle と Cloud SQL for MySQL の null 関数で名前と機能が同じ関数と、変換が推奨される関数を記載します。
| Oracle の関数 | Oracle の実装 | Cloud SQL for MySQL の同等機能 | Cloud SQL for MySQL の関数 | Cloud SQL for MySQL の実装 | 
|---|---|---|---|---|
| COALESCE | 式のリスト内の最初の null 以外の式を返します。 
COALESCE(
null, '1', 'a')
= a
 | ○ | COALESCE | 
COALESCE(
null, '1', 'a')
= 1
 | 
| NULLIF | expression1とexpression2を比較します。等しい場合、この関数は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 と Cloud SQL for MySQL の環境関数と ID 関数で、名前と機能が同じ関数と、変換が推奨される関数を記載します。
| Oracle の関数 | Oracle の実装 | Cloud SQL for MySQL の同等機能 | Cloud SQL for MySQL の関数 | Cloud SQL for MySQL の実装 | 
|---|---|---|---|---|
| SYS_GUID | 16 バイトからなる、グローバルに一意の ID( RAW値)を生成して返します。
SELECT SYS_GUID()
FROM DUAL
=
8EFA4A31468B4C6DE05011AC0200009E
 | × | REPLACEとUUID | 代わりに、 REPLACE関数とUUID関数を使用してSYS_GUID関数をシミュレートします。
REPLACE(
UUID(), '-', '')
 | 
| UID | セッション ユーザー(ログオンしているユーザー)を一意に識別する整数を返します。 
SELECT UID FROM DUAL
= 43
 | × | なし | なし | 
| USER | 現在のセッションに接続しているユーザーのユーザー名を返します。 
SELECT USER FROM DUAL
= username
 | ○ | USER + INSTR + SUBSTR | Cloud SQL for MySQL の 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
 | Cloud SQL for MySQL の 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 と Cloud SQL for MySQL の集計(グループ)関数で名前と機能が同じ関数と、変換が推奨される関数を記載します。
| Oracle の関数 | Oracle の実装 | Cloud SQL for MySQL の同等機能 | Cloud SQL for MySQL の関数 | Cloud SQL for MySQL の実装 | 
|---|---|---|---|---|
| AVG | 列または式の平均値を返します | ○ | AVG | Oracle と同等 | 
| COUNT | クエリによって返される行数を返します | ○ | COUNT | Oracle と同等 | 
| 
COUNT
(DISTINCT)
 | 列または式に含まれる固有の値の数を返します | ○ | 
COUNT
(DISTINCT)
 | Oracle と同等 | 
| 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
 | Cloud SQL for MySQL の GROUP_CONCAT関数を使用して、同等の結果を返します。
SELECT GROUP_CONCAT(
DEPARTMENT_NAME ORDER BY DEPARTMENT_NAME SEPARATOR ', ') DEPT
FROM DEPARTMENTS;
-- Single line results
= Accounting, Administration, Benefits, Construction
 | 
次の表に、Oracle と Cloud SQL for MySQL の FETCH 関数で名前と機能が同じ関数を記載します。
| Oracle の関数 | Oracle の実装 | Cloud SQL for MySQL の同等機能 | Cloud SQL for MySQL の関数 | Cloud SQL for MySQL の実装 | 
|---|---|---|---|---|
| FETCH | 複数行クエリの結果セットから指定した数の行を取得します。 
SELECT * FROM
EMPLOYEES
FETCH FIRST 10 ROWS ONLY;
 | ○ | LIMIT | MySQL の LIMIT句を使用して、クエリから行を取得します。
SELECT * FROM
EMPLOYEES
LIMIT 10;
 | 
基本的なフィルタリング、演算子、サブクエリ
基本的なフィルタリング、演算子関数、サブクエリは、わずかな作業で比較的簡単に変換できます。Oracle と Cloud SQL for MySQL ではデフォルトの日付形式が異なるため、ほとんどは日付形式の変換に関連する作業です。
- Oracle の SYSDATE関数は、01-AUG-19というデフォルトの形式で返します。
- Cloud SQL for MySQL の SYSDATE()関数は、2019-08-01 12:04:05というデフォルトの形式で返します。
日付と時刻の形式を設定するには、MySQL の DATE_FORMAT 関数または STR_TO_DATE 関数を使用します。
次の表に、Oracle と Cloud SQL for MySQL の基本的なフィルタリング、演算子、サブクエリの関数で名前と機能が同じ関数と、変換が推奨される関数を記載します。
| Oracle の関数 | Oracle の実装 | Cloud SQL for MySQL の同等機能 | Cloud SQL for MySQL の関数 | 
|---|---|---|---|
| 
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 | Cloud SQL for MySQL では、 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);
 | 
| 演算子 | ○ | 演算子 | Cloud SQL for MySQL はすべての基本的な演算子をサポートしています。 > | >= | < | <= | = | <> | != | 
Cloud SQL for MySQL クエリのベスト プラクティス
Cloud SQL for MySQL と Oracle の間で同程度のパフォーマンスを維持するには、クエリを最適化する必要があります。これらの最適化には、インデックス構造の変更とデータベース スキーマの調整が含まれます。このセクションでは、Cloud SQL for MySQL で同等のクエリ パフォーマンスを実現するためのガイドラインをいくつか紹介します。
クラスタ化インデックスの作成
InnoDB ストレージ エンジンを使用する場合は、主キーを持つテーブルを定義することをおすすめします。このキーにより、そのテーブルのクラスタ化インデックスが作成されるためです。この方法を使用すると、クエリのパフォーマンスが向上するだけでなく、追加のセカンダリ インデックスを作成することもできます。ただし、インデックスを作成しすぎないようにしてください。冗長なインデックスがあるとパフォーマンスは向上せず、DML の実行速度が低下する可能性があります。このベスト プラクティスは 2 番目のベスト プラクティスにつながります。冗長なインデックスを定期的にモニタリングし、冗長なインデックスがある場合はデータベースから削除します。
次のクエリを使用すると、主キーのないテーブルを特定して、そのテーブルの主キーを作成できます。
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;
クエリ パラメータの調整
クエリのパフォーマンスを調整するには、セッション パラメータを調整することが必要な場合があります。Cloud SQL for MySQL には、この目的のために変更できる一連のフラグがあります。次のようなフラグが含まれます。
- InnoDB 関連のパラメータ
- SORTパラメータ
- JOINパラメータ
- キャッシュ処理パラメータ
クエリのモニタリング
実行速度が遅いクエリは、システムが応答を停止する原因となる、または他のボトルネックの要因となる可能性があります。そのため、定期的にクエリをモニタリングすることが重要です。
実行速度が遅い SQL ステートメントを診断するには、いくつかの方法があります。
- Cloud SQL for MySQL ダッシュボードを使用すると、実行速度が遅いクエリに関するリアルタイムの、および過去に遡った分析情報を取得できます。
- Cloud Monitoring を使用して、Cloud SQL for MySQL のスロークエリ ログをモニタリングします。
- Cloud SQL for MySQL の - statement_analysisビューを使用して、SQL ステートメントに関するランタイム統計情報を表示します。- mysql> SELECT * FROM sys.statement_analysis;
Cloud SQL for MySQL クエリの分析
Cloud SQL for MySQL のクエリ オプティマイザーは、SELECT、INSERT、UPDATE、DELETE の各ステートメントの実行プランを生成します。これらのプランは、実行速度の遅いクエリを調整する場合に役立ちます。使用する場合は以下のことについてご理解ください。
- 実行プランは移行の必要があるデータベース オブジェクトではありません。これは、同じデータセットに対して同じステートメントを実行する場合に、Oracle と Cloud SQL for MySQL の間のパフォーマンスの違いを分析するためのツールです。
- Cloud SQL for MySQL でサポートしている実行プランの構文、機能、出力は、Oracle とは異なります。
次に、Oracle の実行プランと Cloud SQL for MySQL の実行プランの違いを説明するためのプランの例を示します。
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 とは異なり、Cloud SQL for MySQL のストアド プロシージャと関数は実行のたびに解析されます。MySQL BENCHMARK() ユーティリティは、ストアド プロシージャと関数のパフォーマンスのベンチマーキングに役立つツールです。このツールは、反復回数と式の 2 つのパラメータを取り、指定された式(ストアド プロシージャ、関数、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 コマンドを使用して、考えられるパフォーマンス低下の原因を特定します。パフォーマンス低下の一般的な解決策の 1 つは、MySQL オプティマイザーに対応するためにテーブルのインデックス構造を変更することです。もう 1 つの一般的な方法は、不要なデータ検索を減らしたり、手続き型 MySQL コード内の一時テーブルを使用したりすることです。
次のステップ
- MySQL のユーザー アカウントの詳細を確認する。
- Google Cloud に関するリファレンス アーキテクチャ、図、ベスト プラクティスを確認する。Cloud アーキテクチャ センターをご覧ください。