Todos os produtos
Search
Central de documentação

PolarDB:Analisar o desempenho de consultas baseadas em IMCI

Última atualização: Jun 28, 2026

O PolarDB for MySQL coleta estatísticas de execução por operador para consultas processadas pelo mecanismo In-Memory Column Index (IMCI). Essas estatísticas — contagens reais de linhas, custos reais e tempo total por operador — são armazenadas junto com o plano EXPLAIN. Use esses dados para identificar quais operadores consomem mais tempo e mensurar o impacto das otimizações.

Pré-requisitos

Antes de começar, verifique se você tem:

Ativar profiling

Defina o parâmetro de sessão imci_analyze_query como ON para ativar o profiling. Após a execução de uma consulta, os dados de profiling correspondentes ficam disponíveis em information_schema.imci_sql_profiling.

Parâmetro

Nível

Padrão

Descrição

imci_analyze_query

Sessão

OFF

Captura estatísticas de execução por operador para a consulta IMCI mais recente. Defina como ON para ativar.

A tabela imci_sql_profiling armazena dados apenas da instrução SQL mais recente executada via IMCI. Consulte essa tabela imediatamente após a conclusão da consulta alvo.

Como funciona

Quando imci_analyze_query está definido como ON, o PolarDB registra as seguintes métricas para cada operador no plano de execução IMCI:

Coluna

Descrição

ID

ID do operador, correspondente à saída do EXPLAIN

Operator

Tipo de operador (por exemplo, Hash Join, Table Scan)

Name

Nome da tabela, quando aplicável

A-Rows

Número real de linhas produzidas pelo operador

A-Cost

Custo real

Execution Time(s)

Tempo total decorrido neste operador

Extra Info

Condições de junção, chaves de agrupamento e uso de recursos (CPU/memória)

Interpretar a saída de profiling

Use os padrões abaixo para diagnosticar problemas de desempenho:

Sinal

Causa provável

Ação

O valor de Execution Time(s) de um operador representa uma grande parcela do tempo total da consulta

Operador gargalo

Concentre a otimização neste operador

A-Rows é muito maior que E-Rows do EXPLAIN

Erro na estimativa de contagem de linhas; pode indicar uma junção explosiva (linhas de saída excedem muito as de entrada)

Revise as condições de junção; verifique se há filtros ou estatísticas ausentes

A linha 1 (Select Statement) exibe em Extra Info um valor de real_query_mem próximo ou superior a max_query_mem

Pressão de memória

Reduza o paralelismo ou processe os dados em lotes menores

Para ordenar os operadores por tempo de execução e localizar o gargalo diretamente:

/*ROUTE_TO_LAST_USED*/SELECT ID, Operator, Name, `A-Rows`, `Execution Time(s)`
FROM information_schema.imci_sql_profiling
ORDER BY `Execution Time(s)` DESC;

Exemplos

Exemplo de consulta simples

Este exemplo aplica profiling em uma consulta de junção e agregação sobre um conjunto de dados TPC-H (Transaction Processing Performance Council Benchmark H).

SELECT l_shipmode, COUNT(*) FROM lineitem, orders WHERE l_orderkey = o_orderkey GROUP BY l_shipmode;

Etapa 1: Revise o plano de execução.

EXPLAIN SELECT l_shipmode, COUNT(*) FROM lineitem, orders WHERE l_orderkey = o_orderkey GROUP BY l_shipmode;

Saída de exemplo:

+----+------------------------+----------+--------+----------+---------------------------------------------------------------+
| ID | Operator               | Name     | E-Rows | E-Cost   | Extra Info                                                    |
+----+------------------------+----------+--------+----------+---------------------------------------------------------------+
|  1 | Select Statement       |          |        |          | IMCI Execution Plan (max_dop = 1, max_query_mem = unlimited)  |
|  2 | └─Hash Groupby         |          | 6      | 51218.50 | Group Key: lineitem.l_shipmode                                |
|  3 |   └─Compute Scalar     |          | 1869   | 50191.00 |                                                               |
|  4 |     └─Hash Join        |          | 1869   | 31000.00 | Join Cond: lineitem.l_orderkey = orders.o_orderkey            |
|  5 |       ├─Table Scan     | lineitem | 2000   | 0.00     |                                                               |
|  6 |       └─Table Scan     | orders   | 2000   | 0.00     |                                                               |
+----+------------------------+----------+--------+----------+---------------------------------------------------------------+

Etapa 2: Ative o profiling e execute a consulta.

SET imci_analyze_query = ON;

SELECT l_shipmode, COUNT(*) FROM lineitem, orders WHERE l_orderkey = o_orderkey GROUP BY l_shipmode;

Saída de exemplo:

+------------+----------+
| l_shipmode | COUNT(*) |
+------------+----------+
| REG AIR    |      283 |
| SHIP       |      269 |
| FOB        |      299 |
| RAIL       |      289 |
| TRUCK      |      314 |
| MAIL       |      274 |
| AIR        |      272 |
+------------+----------+
7 rows in set (0.05 sec)

Etapa 3: Recupere os dados de profiling.

Use a dica /*ROUTE_TO_LAST_USED*/ para direcionar esta consulta ao mesmo nó onde a consulta IMCI foi executada. Sem ela, o PolarProxy pode rotear a solicitação para um nó diferente e não retornar resultados.

/*ROUTE_TO_LAST_USED*/SELECT * FROM information_schema.imci_sql_profiling;

Saída de exemplo:

+----+------------------------+----------+--------+----------+-------------------+--------------------------------------------------------------------------------------------------------+
| ID | Operator               | Name     | A-Rows | A-Cost   | Execution Time(s) | Extra Info                                                                                             |
+----+------------------------+----------+--------+----------+-------------------+--------------------------------------------------------------------------------------------------------+
|  1 | Select Statement       |          |      0 | 52609.51 |                 0 | IMCI Execution Plan (max_dop = 1, real_dop = 1, max_query_mem = unlimited, real_query_mem = unlimited) |
|  2 | └─Hash Groupby         |          |      7 |  52609.5 |             0.002 | Group Key: lineitem.l_shipmode                                                                         |
|  3 |   └─Compute Scalar     |          |   2000 |    51501 |                 0 |                                                                                                        |
|  4 |     └─Hash Join        |          |   2000 |    31000 |             0.007 | Join Cond: lineitem.l_orderkey = orders.o_orderkey                                                     |
|  5 |       ├─Table Scan     | lineitem |   2000 |        0 |             0.001 |                                                                                                        |
|  6 |       └─Table Scan     | orders   |   2000 |        0 |                 0 |                                                                                                        |
+----+------------------------+----------+--------+----------+-------------------+--------------------------------------------------------------------------------------------------------+

A coluna Extra Info exibe a condição de junção para o operador Hash Join e a chave de agrupamento para o operador Hash Groupby. Na primeira linha, a coluna Extra Info mostra o uso real de CPU e memória (real_dop, real_query_mem) ao lado dos valores estimados (max_dop, max_query_mem), permitindo comparar os dados para detectar pressão sobre os recursos.

Etapa 4: (Opcional) Agregar métricas de profiling.

Execute consultas de agregação diretamente em imci_sql_profiling. Por exemplo, para obter o tempo total de execução:

/*ROUTE_TO_LAST_USED*/SELECT SUM(`Execution Time(s)`) AS TOTAL_TIME FROM information_schema.imci_sql_profiling;

Saída de exemplo:

+----------------------+
| TOTAL_TIME           |
+----------------------+
| 0.010000000000000002 |
+----------------------+
1 row in set (0.00 sec)

A duração total de execução da instrução SQL é de 10 ms.

Exemplo de consulta complexa

Este exemplo demonstra como usar dados de profiling para identificar um gargalo, aplicar uma otimização e verificar a melhoria. A consulta é executada em um conjunto de dados TPC-H SF100 (fator de escala 100).

SELECT
    c_name,
    sum(l_quantity)
FROM
    customer,
    orders,
    lineitem
WHERE
    o_orderkey IN (
        SELECT
            l_orderkey
        FROM
            lineitem
        WHERE
            l_partkey > 18000000
    )
    AND c_custkey = o_custkey
    AND o_orderkey = l_orderkey
GROUP BY
    c_name
ORDER BY
    c_name
LIMIT 10;

Diagnosticar o gargalo

Etapa 1: Revise o plano de execução estimado.

EXPLAIN SELECT
    c_name,
    sum(l_quantity)
FROM
    customer,
    orders,
    lineitem
WHERE
    o_orderkey IN (
        SELECT
            l_orderkey
        FROM
            lineitem
        WHERE
            l_partkey > 18000000
    )
    AND c_custkey = o_custkey
    AND o_orderkey = l_orderkey
GROUP BY
    c_name
ORDER BY
    c_name
LIMIT 10;

Saída de exemplo:

+----+----------------------------------+----------+-----------+------------+---------------------------------------------------------------+
| ID | Operator                         | Name     | E-Rows    | E-Cost     | Extra Info                                                    |
+----+----------------------------------+----------+-----------+------------+---------------------------------------------------------------+
|  1 | Select Statement                 |          |           |            | IMCI Execution Plan (max_dop = 32, max_query_mem = unlimited) |
|  2 | └─Limit                          |          | 10        | 7935739.96 | Offset=0 Limit=10                                             |
|  3 |   └─Sort                         |          | 10        | 7935739.96 | Sort Key: c_name ASC                                          |
|  4 |     └─Hash Groupby               |          | 1503700   | 7933273.99 | Group Key: customer.C_NAME                                    |
|  5 |       └─Hash Right Semi Join     |          | 54010545  | 7865930.26 | Join Cond: lineitem.L_ORDERKEY = orders.O_ORDERKEY            |
|  6 |         ├─Table Scan             | lineitem | 59785766  | 24001.52   | Cond: (L_PARTKEY > 18000000)                                  |
|  7 |         └─Hash Join              |          | 538776190 | 5488090.33 | Join Cond: orders.O_ORDERKEY = lineitem.L_ORDERKEY            |
|  8 |           ├─Hash Join            |          | 181006430 | 668535.99  | Join Cond: customer.C_CUSTKEY = orders.O_CUSTKEY              |
|  9 |           │ ├─Table Scan         | customer | 15000000  | 600.00     |                                                               |
| 10 |           │ └─Table Scan         | orders   | 150000000 | 6000.00    |                                                               |
| 11 |           └─Table Scan           | lineitem | 600037902 | 24001.52   |                                                               |
+----+----------------------------------+----------+-----------+------------+---------------------------------------------------------------+

O Hash Join no ID 7 apresenta um custo estimado de 5.488.090 — aproximadamente 70% do custo total da consulta (7.935.739). Esse operador consome uma quantidade significativa de recursos de CPU, o que indica um grande conjunto de resultados intermediários. Ative o profiling para confirmar se este é realmente o gargalo.

Etapa 2: Ative o profiling e execute a consulta.

SET imci_analyze_query = ON;

SELECT
    c_name,
    sum(l_quantity)
FROM
    customer,
    orders,
    lineitem
WHERE
    o_orderkey IN (
        SELECT
            l_orderkey
        FROM
            lineitem
        WHERE
            l_partkey > 18000000
    )
    AND c_custkey = o_custkey
    AND o_orderkey = l_orderkey
GROUP BY
    c_name
ORDER BY
    c_name
LIMIT 10;

Saída de exemplo:

+--------------------+-----------------+
| c_name             | sum(l_quantity) |
+--------------------+-----------------+
| Customer#000000001 |          172.00 |
| Customer#000000002 |          663.00 |
| Customer#000000004 |          174.00 |
| Customer#000000005 |          488.00 |
| Customer#000000007 |         1135.00 |
| Customer#000000008 |          440.00 |
| Customer#000000010 |          625.00 |
| Customer#000000011 |          143.00 |
| Customer#000000013 |         1032.00 |
| Customer#000000014 |          564.00 |
+--------------------+-----------------+
10 rows in set (21.37 sec)

Etapa 3: Recupere os dados de profiling.

/*ROUTE_TO_LAST_USED*/SELECT * FROM information_schema.imci_sql_profiling;

Saída de exemplo:

+----+----------------------------------+----------+-----------+------------+-------------------+----------------------------------------------------+
| ID | Operator                         | Name     | A-Rows    | A-Cost     | Execution Time(s) | Extra Info                                         |
+----+----------------------------------+----------+-----------+------------+-------------------+----------------------------------------------------+
|  1 | Select Statement                 |          |         0 | 8336856.67 |                 0 |                                                    |
|  2 | └─Limit                          |          |        10 | 8336856.67 |             0.002 | Offset=0 Limit=10                                  |
|  3 |   └─Sort                         |          |         0 | 8336856.67 |             2.275 | Sort Key: c_name ASC                               |
|  4 |     └─Hash Groupby               |          |   9813586 | 8320763.22 |           160.083 | Group Key: customer.C_NAME                         |
|  5 |       └─Hash Right Semi Join     |          | 239598134 | 7994854.23 |            98.174 | Join Cond: lineitem.L_ORDERKEY = orders.O_ORDERKEY |
|  6 |         ├─Table Scan             | lineitem |  60013756 |   24001.52 |              3.28 | Cond: (L_PARTKEY > 18000000)                       |
|  7 |         └─Hash Join              |          | 600037902 | 5156677.35 |           301.503 | Join Cond: orders.O_ORDERKEY = lineitem.L_ORDERKEY |
|  8 |           ├─Hash Join            |          | 150000000 |  629777.96 |            97.201 | Join Cond: customer.C_CUSTKEY = orders.O_CUSTKEY   |
|  9 |           │ ├─Table Scan         | customer |  15000000 |        600 |             3.321 |                                                    |
| 10 |           │ └─Table Scan         | orders   | 150000000 |       6000 |             0.241 |                                                    |
| 11 |           └─Table Scan           | lineitem | 600037902 |   24001.52 |             0.661 |                                                    |
+----+----------------------------------+----------+-----------+------------+-------------------+----------------------------------------------------+

O Hash Join no ID 7 levou 301,503 s — cerca de metade do tempo total da consulta. Suas entradas são a tabela lineitem (600 milhões de linhas, ID 11) e o resultado do Hash Join ID 8 (150 milhões de linhas). A junção de dois conjuntos grandes força o mecanismo a construir uma tabela hash extremamente extensa, o que domina o tempo de execução.

O plano de execução também revela que o filtro o_orderkey IN (...) é avaliado como um Hash Right Semi Join (ID 5) somente após a conclusão da junção pesada no ID 7. Se o otimizador converter essa subconsulta IN em uma semi-junção e a antecipar antes do ID 7, será possível filtrar as linhas de orders mais cedo e reduzir o conjunto de resultados intermediários alimentado no ID 7.

Aplicar a otimização

Etapa 4: Ative o pushdown de semi-junção baseado em custo.

SET imci_optimizer_switch = 'semijoin_pushdown=on';

Etapa 5: Verifique o novo plano de execução.

EXPLAIN SELECT
    c_name,
    sum(l_quantity)
FROM
    customer,
    orders,
    lineitem
WHERE
    o_orderkey IN (
        SELECT
            l_orderkey
        FROM
            lineitem
        WHERE
            l_partkey > 18000000
    )
    AND c_custkey = o_custkey
    AND o_orderkey = l_orderkey
GROUP BY
    c_name
ORDER BY
    c_name
LIMIT 10;

Saída de exemplo:

+----+----------------------------------------+----------+-----------+------------+---------------------------------------------------------------+
| ID | Operator                               | Name     | E-Rows    | E-Cost     | Extra Info                                                    |
+----+----------------------------------------+----------+-----------+------------+---------------------------------------------------------------+
|  1 | Select Statement                       |          |           |            | IMCI Execution Plan (max_dop = 32, max_query_mem = unlimited) |
|  2 | └─Limit                                |          | 10        | 2800433.74 | Offset=0 Limit=10                                             |
|  3 |   └─Sort                               |          | 10        | 2800433.74 | Sort Key: c_name ASC                                          |
|  4 |     └─Hash Groupby                     |          | 14567321  | 2776544.58 | Group Key: customer.C_NAME                                    |
|  5 |       └─Hash Join                      |          | 57918330  | 2631846.75 | Join Cond: orders.O_ORDERKEY = lineitem.L_ORDERKEY            |
|  6 |         ├─Hash Join                    |          | 14567321  | 1014041.92 | Join Cond: orders.O_CUSTKEY = customer.C_CUSTKEY              |
|  7 |         │ ├─Hash Right Semi Join       |          | 12071937  | 906226.67  | Join Cond: lineitem.L_ORDERKEY = orders.O_ORDERKEY            |
|  8 |         │ │ ├─Table Scan               | lineitem | 59785766  | 24001.52   | Cond: (L_PARTKEY > 18000000)                                  |
|  9 |         │ │ └─Table Scan               | orders   | 150000000 | 6000.00    |                                                               |
| 10 |         │ └─Table Scan                 | customer | 15000000  | 600.00     |                                                               |
| 11 |         └─Table Scan                   | lineitem | 600037902 | 24001.52   |                                                               |
+----+----------------------------------------+----------+-----------+------------+---------------------------------------------------------------+

A semi-junção agora foi movida para o ID 7, filtrando as linhas de orders antes da junção custosa. O custo total estimado cai de 7.935.739 para 2.800.433.

Verificar a melhoria

Etapa 6: Execute novamente a consulta e colete o profiling.

SELECT
    c_name,
    sum(l_quantity)
FROM
    customer,
    orders,
    lineitem
WHERE
    o_orderkey IN (
        SELECT
            l_orderkey
        FROM
            lineitem
        WHERE
            l_partkey > 18000000
    )
    AND c_custkey = o_custkey
    AND o_orderkey = l_orderkey
GROUP BY
    c_name
ORDER BY
    c_name
LIMIT 10;

Saída de exemplo:

+--------------------+-----------------+
| c_name             | sum(l_quantity) |
+--------------------+-----------------+
| Customer#000000001 |          172.00 |
| Customer#000000002 |          663.00 |
| Customer#000000004 |          174.00 |
| Customer#000000005 |          488.00 |
| Customer#000000007 |         1135.00 |
| Customer#000000008 |          440.00 |
| Customer#000000010 |          625.00 |
| Customer#000000011 |          143.00 |
| Customer#000000013 |         1032.00 |
| Customer#000000014 |          564.00 |
+--------------------+-----------------+
10 rows in set (13.74 sec)

O tempo de execução caiu de 21,37 s para 13,74 s — uma redução de aproximadamente 40%.

Etapa 7: Confirme com os dados de profiling.

/*ROUTE_TO_LAST_USED*/SELECT * FROM information_schema.imci_sql_profiling;

Saída de exemplo:

+----+----------------------------------------+----------+-----------+------------+-------------------+----------------------------------------------------+
| ID | Operator                               | Name     | A-Rows    | A-Cost     | Execution Time(s) | Extra Info                                         |
+----+----------------------------------------+----------+-----------+------------+-------------------+----------------------------------------------------+
|  1 | Select Statement                       |          |         0 | 4318488.35 |                 0 |                                                    |
|  2 | └─Limit                                |          |        10 | 4318488.35 |             0.002 | Offset=0 Limit=10                                  |
|  3 |   └─Sort                               |          |         0 | 4318488.34 |             3.076 | Sort Key: c_name ASC                               |
|  4 |     └─Hash Groupby                     |          |   9813586 | 4302394.89 |           163.149 | Group Key: customer.C_NAME                         |
|  5 |       └─Hash Join                      |          | 239598134 | 3976485.91 |           151.253 | Join Cond: orders.O_ORDERKEY = lineitem.L_ORDERKEY |
|  6 |         ├─Hash Join                    |          |  49393149 | 1321335.54 |            55.392 | Join Cond: orders.O_CUSTKEY = customer.C_CUSTKEY   |
|  7 |         │ ├─Hash Right Semi Join       |          |  49393149 |  954805.16 |            52.552 | Join Cond: lineitem.L_ORDERKEY = orders.O_ORDERKEY |
|  8 |         │ │ ├─Table Scan               | lineitem |  60013756 |   24001.52 |             2.791 | Cond: (L_PARTKEY > 18000000)                       |
|  9 |         │ │ └─Table Scan               | orders   | 150000000 |       6000 |             0.152 |                                                    |
| 10 |         │ └─Table Scan                 | customer |  15000000 |        600 |             0.028 |                                                    |
| 11 |         └─Table Scan                   | lineitem | 600037902 |   24001.52 |             0.642 |                                                    |
+----+----------------------------------------+----------+-----------+------------+-------------------+----------------------------------------------------+

O gargalo anterior (Hash Join ID 7, 301,503 s) foi eliminado. O pushdown da semi-junção no ID 7 agora filtra orders para aproximadamente 49 milhões de linhas antes da junção no ID 5, reduzindo o tamanho da entrada da junção e o tempo total de execução.