Oracle Database から Cloud SQL for MySQL へのクエリの変換と最適化

このドキュメントでは、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 基本構文 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 のどちらも使用可能) × 定義済みのテーブル名に応じて大文字と小文字を区別する(例: テーブル名として ordersORDERS のいずれかを使用可能)。

インライン ビュー

インライン ビュー(別名、派生テーブル)は 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 × UNIONLEFT の使用および 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 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

スカラー関数とグループ関数

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 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(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 の 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 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 指定された日付 date1date2 の間の月数を返します。
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 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 と 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
× REPLACEUUID 代わりに、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 列または式の最大値を返します 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 のクエリ オプティマイザーは、SELECTINSERTUPDATEDELETE の各ステートメントの実行プランを生成します。これらのプランは、実行速度の遅いクエリを調整する場合に役立ちます。使用する場合は以下のことについてご理解ください。

  • 実行プランは移行の必要があるデータベース オブジェクトではありません。これは、同じデータセットに対して同じステートメントを実行する場合に、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 アーキテクチャ センターをご覧ください。