Todos los productos
Search
Centro de documentos

ApsaraDB RDS:Statement outline

Última actualización: Sep 03, 2026

El esquema de sentencias permite vincular hints del optimizador o hints de índice a sentencias SQL específicas. Esto evita la variación en los planes de ejecución sin necesidad de modificar el código de la aplicación. Utilícelo de forma proactiva para fijar los planes de consultas críticas antes de que presenten regresiones, o de forma reactiva para corregir consultas cuyo comportamiento cambió tras una actualización de estadísticas o del motor.

Con el esquema de sentencias, usted puede:

  • Fijar los planes de ejecución de consultas críticas para evitar cambios durante las actualizaciones de estadísticas o del motor.

  • Aplicar hints del optimizador o de índice a cualquier sentencia SQL mediante la coincidencia de su digest, sin reescribir la consulta.

  • Previsualizar, inspeccionar y eliminar esquemas sin reiniciar la instancia.

Tip: Para confirmar que un esquema está activo, ejecute EXPLAIN en la consulta objetivo y revise SHOW WARNINGS para verificar el hint aplicado. También puede llamar a CALL dbms_outln.preview_outline() para comprobar qué esquemas coinciden con una consulta antes de aplicarla.

Requisitos previos

Antes de empezar, asegúrese de que su instancia RDS ejecute una de las siguientes versiones del motor MySQL:

  • MySQL 8.0

  • MySQL 5.7

Funcionamiento

Cuando AliSQL recibe una consulta, calcula su digest y busca una entrada coincidente en la tabla mysql.outline. Si encuentra una coincidencia y el esquema está habilitado, AliSQL inyecta el hint almacenado en el plan de ejecución. La tabla de esquemas se crea automáticamente al iniciar la instancia.

El esquema de sentencias admite dos tipos de hints:

Tipo de hint

Ámbitos aplicables

Referencia

Hint del optimizador

Nivel global, nivel de tabla, nivel de índice y orden de unión

Optimizer Hints

Hint de índice

Nivel de tabla, con ámbito opcional FOR JOIN, FOR ORDER BY o FOR GROUP BY

Index Hints

Esquema de la tabla de outlines

AliSQL almacena todos los esquemas en la tabla mysql.outline. La definición DDL es la siguiente:

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='Statement outline'

Descripción de columnas:

Columna

Descripción

Id

Identificador autoincrementable para cada entrada del esquema.

Schema_name

Nombre de la base de datos.

Digest

Cadena hash de 64 bytes derivada de Digest_text.

Digest_text

Forma normalizada de la sentencia SQL.

Type

Tipo de hint: OPTIMIZER para hints del optimizador; USE INDEX, FORCE INDEX o IGNORE INDEX para hints de índice.

Scope

Aplica solo a hints de índice. Valores válidos: FOR JOIN, FOR ORDER BY, FOR GROUP BY. Una cadena vacía indica que el hint aplica a todos los contextos.

State

Y para habilitar el esquema; N para deshabilitarlo.

Position

Para hints del optimizador: número secuencial de la palabra clave del bloque de consulta (comienza en 1). Para hints de índice: número secuencial de la tabla en la consulta (comienza en 1).

Hint

Para hints del optimizador: la cadena completa del hint, por ejemplo /*+ MAX_EXECUTION_TIME(1000) */. Para hints de índice: una lista de nombres de índice separados por comas, por ejemplo ind_1,ind_2.

Gestión de esquemas de sentencias

DBMS_OUTLN proporciona cinco procedimientos almacenados para gestionar los esquemas. Llame a cada procedimiento con CALL dbms_outln.<procedure>().

Agregar un hint del optimizador

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

Proporcione Digest o query y deje el otro campo vacío. Si proporciona una cadena de consulta, DBMS_OUTLN calcula Digest y Digest_text automáticamente.

Ejemplo: Aplicar un límite de tiempo de ejecución de 1 segundo a una consulta específica.

CALL dbms_outln.add_optimizer_outline("outline_db", '', 1, '/*+ MAX_EXECUTION_TIME(1000) */',
                                      "select * from t1 where id = 1");

Agregar un hint de índice

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

Proporcione Digest o Query y deje el otro campo vacío. Si proporciona una cadena de consulta, DBMS_OUTLN calcula Digest y Digest_text automáticamente.

Ejemplo: Forzar a la consulta a usar ind_1 en t1.

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

Previsualizar esquemas coincidentes

Compruebe qué esquemas coinciden con una consulta antes de ejecutarla. Esta función resulta útil para la validación manual.

CALL dbms_outln.preview_outline('<Schema_name>', '<Query>');
Note: El parámetro max_digest_length controla qué parte de la sentencia SQL se procesa como hash. Si una consulta coincide con un esquema incorrecto, aumente el valor de max_digest_length .

Ejemplo:

CALL dbms_outln.preview_outline('outline_db', "select * from t1 where t1.col1 = 1 and t1.col2 = 'xpchild'");

Salida esperada:

+------------+------------------------------------------------------------------+------------+------------+-------+---------------------+
| 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)

Mostrar esquemas activos

Liste todos los esquemas cargados actualmente en memoria, junto con los conteos de aciertos y desbordamientos.

CALL dbms_outln.show_outline();

Ejemplo de salida:

+------+------------+------------------------------------------------------------------+-----------+-------+------+-------------------------------------------------------+------+----------+-------------------------------------------------------------------------------------+
| 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)

La columna HIT muestra cuántas veces el esquema coincidió con su bloque de consulta o tabla objetivo. La columna OVERFLOW indica cuántas veces no se encontró el objetivo.

Eliminar un esquema

Elimine un esquema de la memoria o de la tabla de esquemas mediante su Id.

CALL dbms_outln.del_outline(<Id>);

Ejemplo:

CALL dbms_outln.del_outline(32);

Si el esquema no existe, el sistema genera una advertencia. Ejecute SHOW WARNINGS para ver los detalles.

CALL dbms_outln.del_outline(1000);
-- Query OK, 0 rows affected, 2 warnings (0.00 sec)

SHOW WARNINGS;

Salida esperada:

+---------+------+----------------------------------------------+
| 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)

Recargar esquemas tras una edición manual

Si modifica la tabla mysql.outline directamente, llame a flush_outline para recargar los cambios en la memoria.

CALL dbms_outln.flush_outline();

Ejemplo: Actualice la posición del esquema 18 y luego ejecute flush.

UPDATE mysql.outline SET Position = 1 WHERE Id = 18;
-- Query OK, 1 row affected (0.00 sec)

CALL dbms_outln.flush_outline();
-- Query OK, 0 rows affected (0.01 sec)

Verificar que un esquema está activo

Utilice cualquiera de los siguientes métodos para confirmar que el esquema se aplicó correctamente.

Método 1: preview_outline

CALL dbms_outln.preview_outline('outline_db', "select * from t1 where t1.col1 = 1 and t1.col2 = 'xpchild'");

Un resultado no vacío indica que la consulta coincide con un esquema activo:

+------------+------------------------------------------------------------------+------------+------------+-------+---------------------+
| 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)

Método 2: EXPLAIN + SHOW WARNINGS

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)

A continuación, revise la consulta reescrita en SHOW WARNINGS para confirmar que se inyectó el hint:

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)

La presencia de USE INDEX ( ind_1 ) en la consulta reescrita confirma que el esquema está activo.