すべてのプロダクト
Search
ドキュメントセンター

ApsaraDB RDS:ステートメントの概要

最終更新日:May 21, 2025

本番環境では、SQL ステートメントの実行計画が頻繁に変更される可能性があり、データベースが不安定になることがあります。AliSQL はステートメントアウトライン機能を提供しており、オプティマイザヒントまたはインデックスヒントを使用して SQL ステートメントの実行計画を安定させることができます。AliSQL は、ステートメントアウトラインを効率的に管理するための DBMS_OUTLN ツールキットも提供しています。

前提条件

RDS インスタンスは、次のメジャーエンジンバージョンのいずれかを実行しています。

  • MySQL 8.0

  • MySQL 5.7

機能の説明

ステートメントアウトライン機能は、MySQL 8.0 および MySQL 5.7 で提供される次の種類のヒントをサポートしています。

  • オプティマイザヒント

    オプティマイザヒントは、適用可能なスコープとヒントオブジェクトに基づいて、グローバルレベルのオプティマイザヒント、テーブルレベルのオプティマイザヒント、インデックスレベルのオプティマイザヒント、および結合順序オプティマイザヒントに分類されます。詳細については、「Optimizer Hints」をご参照ください。

  • インデックスヒント

    インデックスヒントは、種類とスコープに基づいて分類されます。詳細については、「Index Hints」をご参照ください。

アウトラインテーブル

AliSQL は、ヒントを格納するために outline という名前の組み込みシステムテーブルを使用します。システムは起動時に outline テーブルを自動的に作成します。 outline テーブルを作成するには、次のステートメントを使用します。

CREATE TABLE 'mysql'.'outline' (
  `Id` bigint(20) NOT NULL AUTO_INCREMENT,
  `Schema_name` varchar(64) COLLATE utf8_bin DEFAULT NULL,
  `Digest` varchar(64) COLLATE utf8_bin NOT NULL,
  `Digest_text` longtext COLLATE utf8_bin,
  `Type` enum('IGNORE INDEX','USE INDEX','FORCE INDEX','OPTIMIZER') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `Scope` enum('','FOR JOIN','FOR ORDER BY','FOR GROUP BY') CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '',
  `State` enum('N','Y') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'Y',
  `Position` bigint(20) NOT NULL,
  `Hint` text COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`Id`)
) /*!50100 TABLESPACE `mysql` */ ENGINE=InnoDB
DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0 COMMENT='ステートメントアウトライン'

次の表に、ステートメントのパラメーターを示します。

パラメーター

説明

Id

各ステートメントアウトラインの ID。

Schema_name

データベースの名前。

Digest

[Digest_text] パラメーターから取得した 64 バイトのハッシュ文字列。

Digest_text

SQL ステートメントのダイジェスト。

Type

  • オプティマイザヒントの場合、ヒントの種類は OPTIMIZER です。

  • インデックスヒントの場合、ヒントの種類は USE INDEX、FORCE INDEX、または IGNORE INDEX です。

Scope

ヒントが適用されるコンテキスト。このパラメーターは、インデックスヒントの場合にのみ必須です。有効な値:

  • FOR GROUP BY

  • FOR ORDER BY

  • FOR JOIN

空の文字列は、ヒントがすべてのコンテキストに適用されることを指定します。

State

ヒントを有効にするかどうかを指定します。

Position

  • オプティマイザヒントの場合、Position パラメーターは、すべてのオプティマイザヒントがクエリブロックに適用されるため、クエリブロック内のキーワードの位置です。Position パラメーターは、ヒントが適用されるキーワードのシーケンス番号を指定します。Position パラメーターの値は 1 から始まります。

  • インデックスヒントの場合、Position パラメーターはテーブルの位置です。Position パラメーターは、ヒントが適用されるテーブルのシーケンス番号を指定します。値は 1 から始まります。

Hint

  • オプティマイザヒントの場合、Hint パラメーターは統合ヒント文字列を指定します。例:/*+ MAX_EXECUTION_TIME(1000) */

  • インデックスヒントの場合、Hint パラメーターはインデックス名のリストを指定します。例:ind_1,ind_2

ステートメントアウトラインの管理

ステートメントアウトラインを効率的に管理するために、AliSQL は DBMS_OUTLN ツールキット内に定義済みプロシージャのセットを提供しています。

  • add_optimizer_outline

    オプティマイザヒントを追加します。コマンドの例:

    dbms_outln.add_optimizer_outline('<Schema_name>','<Digest>','<query_block>','<hint>','<query>');
    説明

    ステートメントの Digest パラメーターまたは query パラメーターのいずれかを構成できます。 query パラメーターにクエリステートメントを入力すると、DBMS_OUTLN は Digest パラメーターと Digest_text パラメーターの値を計算します。

    例:

    mysql> call dbms_outln.add_optimizer_outline("outline_db", '', 1, '/*+ MAX_EXECUTION_TIME(1000) */',
                                          "select * from t1 where id = 1");
  • add_index_outline

    インデックスヒントを追加します。コマンドの例:

    dbms_outln.add_index_outline('<Schema_name>','<Digest>',<Position>,'<Type>','<Hint>','<Scope>','<Query>');
    説明

    ステートメントの Digest パラメーターまたは query パラメーターのいずれかを構成できます。 Query パラメーターにクエリステートメントを入力すると、DBMS_OUTLN は Digest パラメーターと Digest_text パラメーターの値を計算します。

    例:

    mysql> call dbms_outln.add_index_outline('outline_db', '', 1, 'USE INDEX', 'ind_1', '',
                                    "select * from t1 where t1.col1 =1 and t1.col2 ='xpchild'");
  • preview_outline

    SQL ステートメントが既存のアウトラインと一致するかどうかを確認します。これは手動検証に役立ちます。コマンドの例:

    dbms_outln.preview_outline('<Schema_name>','<Query>');
    説明

    max_digest_length パラメーターの値は、SQL ステートメントとアウトラインの一致に影響を与える可能性があります。 SQL ステートメントが間違ったアウトラインと一致する場合は、このパラメーターの値を増やしてください。

    例:

    mysql> call dbms_outln.preview_outline('outline_db', ''select * from t1 where t1.col1 =1 and t1.col2 ='xpchild''');
    +------------+------------------------------------------------------------------+------------+------------+-------+---------------------+
    | SCHEMA     | DIGEST                                                           | BLOCK_TYPE | BLOCK_NAME | BLOCK | HINT                |
    +------------+------------------------------------------------------------------+------------+------------+-------+---------------------+
    | outline_db | b4369611be7ab2d27c85897632576a04bc08f50b928a1d735b62d0a140628c4c | TABLE      | t1         |     1 | USE INDEX (`ind_1`) |
    +------------+------------------------------------------------------------------+------------+------------+-------+---------------------+
    1 row in set (0.00 sec)
  • show_outline

    メモリ内でヒットしたステートメントアウトラインを表示します。コマンドの例:

    dbms_outln.show_outline();

    例:

    mysql> call dbms_outln.show_outline();
    +------+------------+------------------------------------------------------------------+-----------+-------+------+-------------------------------------------------------+------+----------+-------------------------------------------------------------------------------------+
    | ID   | SCHEMA     | DIGEST                                                           | TYPE      | SCOPE | POS  | HINT                                                  | HIT  | OVERFLOW | DIGEST_TEXT                                                                         |
    +------+------------+------------------------------------------------------------------+-----------+-------+------+-------------------------------------------------------+------+----------+-------------------------------------------------------------------------------------+
    |   33 | outline_db | 36bebc61fce7e32b93926aec3fdd790dad5d895107e2d8d3848d1c60b74bcde6 | OPTIMIZER |       |    1 | /*+ SET_VAR(foreign_key_checks=OFF) */                |    1 |        0 | SELECT * FROM `t1` WHERE `id` = ?                                                   |
    |   32 | outline_db | 36bebc61fce7e32b93926aec3fdd790dad5d895107e2d8d3848d1c60b74bcde6 | OPTIMIZER |       |    1 | /*+ MAX_EXECUTION_TIME(1000) */                       |    2 |        0 | SELECT * FROM `t1` WHERE `id` = ?                                                   |
    |   34 | outline_db | d4dcef634a4a664518e5fb8a21c6ce9b79fccb44b773e86431eb67840975b649 | OPTIMIZER |       |    1 | /*+ BNL(t1,t2) */                                     |    1 |        0 | SELECT `t1` . `id` , `t2` . `id` FROM `t1` , `t2`                                   |
    |   35 | outline_db | 5a726a609b6fbfb76bb8f9d2a24af913a2b9d07f015f2ee1f6f2d12dfad72e6f | OPTIMIZER |       |    2 |  /*+ QB_NAME(subq1) */                                |    2 |        0 | SELECT * FROM `t1` WHERE `t1` . `col1` IN ( SELECT `col1` FROM `t2` )               |
    |   36 | outline_db | 5a726a609b6fbfb76bb8f9d2a24af913a2b9d07f015f2ee1f6f2d12dfad72e6f | OPTIMIZER |       |    1 | /*+ SEMIJOIN(@subq1 MATERIALIZATION, DUPSWEEDOUT) */  |    2 |        0 | SELECT * FROM `t1` WHERE `t1` . `col1` IN ( SELECT `col1` FROM `t2` )               |
    |   30 | outline_db | b4369611be7ab2d27c85897632576a04bc08f50b928a1d735b62d0a140628c4c | USE INDEX |       |    1 | ind_1                                                 |    3 |        0 | SELECT * FROM `t1` WHERE `t1` . `col1` = ?  AND `t1` . `col2` = ?                    |
    |   31 | outline_db | 33c71541754093f78a1f2108795cfb45f8b15ec5d6bff76884f4461fb7f33419 | USE INDEX |       |    2 | ind_2                                                 |    1 |        0 | SELECT * FROM `t1` , `t2` WHERE `t1` . `col1` = `t2` . `col1` AND `t2` . `col2` = ?  |
    +------+------------+------------------------------------------------------------------+-----------+-------+------+-------------------------------------------------------+------+----------+-------------------------------------------------------------------------------------+
    7 rows in set (0.00 sec)

    次の表に、HIT パラメーターと OVERFLOW パラメーターを示します。

    パラメーター

    説明

    HIT

    ステートメントアウトラインが目的のクエリブロックまたはテーブルを見つけた回数。

    OVERFLOW

    ステートメントアウトラインが目的のクエリブロックまたはテーブルを見つけられなかった回数。

  • del_outline

    メモリまたはテーブルからステートメントアウトラインを削除します。コマンドの例:

    dbms_outln.del_outline(<Id>);

    例:

    mysql> call dbms_outln.del_outline(32);
    説明

    削除するアウトラインが存在しない場合、システムはエラーを報告します。 SHOW WARNINGS; ステートメントを実行して、エラーメッセージを表示できます。

    mysql> call dbms_outln.del_outline(1000);
    Query OK, 0 rows affected, 2 warnings (0.00 sec)
    
    mysql> show warnings;
    +---------+------+----------------------------------------------+
    | Level   | Code | Message                                      |
    +---------+------+----------------------------------------------+
    | Warning | 7521 | Statement outline 1000 is not found in table |
    | Warning | 7521 | Statement outline 1000 is not found in cache |
    +---------+------+----------------------------------------------+
    2 rows in set (0.00 sec)
  • flush_outline

    outline テーブルのステートメントアウトラインを変更した場合は、新しいステートメントアウトラインを有効にするために次のステートメントを実行する必要があります。コマンドの例:

    dbms_outln.flush_outline(); 

    例:

    mysql> update mysql.outline set Position = 1 where Id = 18;
    Query OK, 1 row affected (0.00 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    mysql> call dbms_outln.flush_outline(); 
    Query OK, 0 rows affected (0.01 sec)

機能テスト

次のいずれかの方法を使用して、ステートメントアウトラインが有効になっているかどうかを確認できます。

  • preview_outline ステートメントを実行します。

    mysql> call dbms_outln.preview_outline('outline_db', "select * from t1 where t1.col1 =1 and t1.col2 ='xpchild'");
    +------------+------------------------------------------------------------------+------------+------------+-------+---------------------+
    | SCHEMA     | DIGEST                                                           | BLOCK_TYPE | BLOCK_NAME | BLOCK | HINT                |
    +------------+------------------------------------------------------------------+------------+------------+-------+---------------------+
    | outline_db | b4369611be7ab2d27c85897632576a04bc08f50b928a1d735b62d0a140628c4c | TABLE      | t1         |     1 | USE INDEX (`ind_1`) |
    +------------+------------------------------------------------------------------+------------+------------+-------+---------------------+
    1 row in set (0.01 sec)
  • EXPLAIN ステートメントを実行します。

    mysql> explain select * from t1 where t1.col1 =1 and t1.col2 ='xpchild';
    +----+-------------+-------+------------+------+---------------+-------+---------+-------+------+----------+-------------+
    | id | select_type | table | partitions | type | possible_keys | key   | key_len | ref   | rows | filtered | Extra       |
    +----+-------------+-------+------------+------+---------------+-------+---------+-------+------+----------+-------------+
    |  1 | SIMPLE      | t1    | NULL       | ref  | ind_1         | ind_1 | 5       | const |    1 |   100.00 | Using where |
    +----+-------------+-------+------------+------+---------------+-------+---------+-------+------+----------+-------------+
    1 row in set, 1 warning (0.00 sec)
    
    mysql> show warnings;
    +-------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Level | Code | Message                                                                                                                                                                                                                                                 |
    +-------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Note  | 1003 | /* select#1 */ select `outline_db`.`t1`.`id` AS `id`,`outline_db`.`t1`.`col1` AS `col1`,`outline_db`.`t1`.`col2` AS `col2` from `outline_db`.`t1` USE INDEX (`ind_1`) where ((`outline_db`.`t1`.`col1` = 1) and (`outline_db`.`t1`.`col2` = 'xpchild')) |
    +-------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)