Os perfis de consulta capturam detalhes de execução por nó para cada consulta. Use-os para identificar gargalos de desempenho e otimizar a performance das consultas.
Ativar perfis de consulta
Defina a variável enable_profile para iniciar a coleta de perfis:
SET enable_profile=true;
Quando
enable_profile
está definido como
true
, o SelectDB gera um perfil para cada consulta executada. Cada perfil registra os detalhes de execução em todos os nós.
Visualizar perfis de consulta
A instrução SHOW QUERY PROFILE é suportada apenas nas versões do SelectDB Core anteriores à V4.0.0. Para o SelectDB Core V4.0.0 e posteriores, visualize ou baixe os perfis de consulta no console do SelectDB ou use a API HTTP. Para mais detalhes, consulte Usar o recurso de auditoria de consultas e Exportar perfis de consulta.
Execute a seguinte instrução para listar todos os perfis armazenados:
SHOW QUERY PROFILE "/"\G;
Cada linha no resultado corresponde a um perfil:
SHOW QUERY PROFILE "/"\G
*************************** 1. row ***************************
Profile ID: c257c52f93e149ee-ace8ac14e8c9fef9
Task Type: QUERY
Start Time: 2021-04-08 11:30:50
End Time: 2021-04-08 11:30:50
Total: 9ms
Task State: EOF
User: root
Default Db: default_cluster:db1
Sql Statement: select tbl1.k1, sum(tbl1.k2) from tbl1 join tbl2 on tbl1.k1 = tbl2.k1 group by tbl1.k1 order by tbl1.k1
Nas respostas da API HTTP, os campos
Query ID
e
query_id
referem-se ao ID do perfil.
Analisar perfis de consulta
Siga este fluxo de trabalho de três etapas para localizar o gargalo de desempenho em uma consulta. Cada etapa avança um nível na hierarquia de execução.
Etapa 1: Identificar o fragmento mais lento
Objetivo: Encontrar o fragmento que representa o principal gargalo.
A árvore do plano de execução mostra a estrutura dos fragmentos e o tempo de execução de cada um. O valor MaxActiveTime em cada nó remetente representa o maior tempo de execução entre todas as unidades de execução desse fragmento.
SHOW QUERY PROFILE "/<profile_id>"\G
Exemplo de saída:
SHOW QUERY PROFILE "/c257c52f93e149ee-ace8ac14e8c9fef9"\G
*************************** 1. row ***************************
Fragments:
┌──────────────────────┐
│[-1: DataBufferSender]│
│Fragment: 0 │
│MaxActiveTime: 6.626 ms│
└──────────────────────┘
│
┌──────────────────┐
│[9: EXCHANGE_NODE]│
│Fragment: 0 │
└──────────────────┘
│
┌──────────────────────┐
│[9: DataStreamSender] │
│Fragment: 1 │
│MaxActiveTime: 5.449 ms│
└──────────────────────┘
│
┌──────────────┐
│[4: SORT_NODE]│
│Fragment: 1 │
└──────────────┘
┌┘
┌─────────────────────┐
│[8: AGGREGATION_NODE]│
│Fragment: 1 │
└─────────────────────┘
└┐
┌──────────────────┐
│[7: EXCHANGE_NODE]│
│Fragment: 1 │
└──────────────────┘
│
┌──────────────────────┐
│[7: DataStreamSender] │
│Fragment: 2 │
│MaxActiveTime: 3.505 ms│
└──────────────────────┘
┌┘
┌─────────────────────┐
│[3: AGGREGATION_NODE]│
│Fragment: 2 │
└─────────────────────┘
│
┌───────────────────┐
│[2: HASH_JOIN_NODE]│
│Fragment: 2 │
└───────────────────┘
┌────────────┴────────────┐
┌──────────────────┐ ┌──────────────────┐
│[5: EXCHANGE_NODE]│ │[6: EXCHANGE_NODE]│
│Fragment: 2 │ │Fragment: 2 │
└──────────────────┘ └──────────────────┘
│ │
┌─────────────────────┐ ┌────────────────────────┐
│[5: DataStreamSender]│ │[6: DataStreamSender] │
│Fragment: 4 │ │Fragment: 3 │
│MaxActiveTime: 1.87 ms│ │MaxActiveTime: 636.767 us│
└─────────────────────┘ └────────────────────────┘
│ ┌┘
┌───────────────────┐ ┌───────────────────┐
│[0: OLAP_SCAN_NODE]│ │[1: OLAP_SCAN_NODE]│
│Fragment: 4 │ │Fragment: 3 │
└──────────────────┘ └──────────────────┘
│ │
┌─────────────┐ ┌─────────────┐
│[OlapScanner]│ │[OlapScanner]│
│Fragment: 4 │ │Fragment: 3 │
└─────────────┘ └─────────────┘
│ │
┌─────────────────┐ ┌─────────────────┐
│[SegmentIterator]│ │[SegmentIterator]│
│Fragment: 4 │ │Fragment: 3 │
└─────────────────┘ └─────────────────┘
1 row in set (0.02 sec)
Neste exemplo, o Fragmento 1 apresenta o maior MaxActiveTime (5,449 ms), sendo portanto o principal gargalo. Prossiga para a Etapa 2 com o Fragmento 1.
Etapa 2: Identificar a unidade de execução mais lenta
Objetivo: Descobrir qual instância de nó dentro do fragmento crítico consome mais tempo.
Após identificar o fragmento mais lento, liste todas as unidades de execução (instâncias) contidas nele:
SHOW QUERY PROFILE "/<profile_id>/<fragment_id>";
Exemplo de saída para o Fragmento 1:
SHOW QUERY PROFILE "/c257c52f93e149ee-ace8ac14e8c9fef9/1";
+-----------------------------------+-------------------+------------+
| Instances | Host | ActiveTime |
+-----------------------------------+-------------------+------------+
| c257c52f93e149ee-ace8ac14e8c9ff03 | 10.200.00.01:9060 | 5.449ms |
| c257c52f93e149ee-ace8ac14e8c9ff05 | 10.200.00.02:9060 | 5.367ms |
| c257c52f93e149ee-ace8ac14e8c9ff04 | 10.200.00.03:9060 | 5.358ms |
+-----------------------------------+-------------------+------------+
A instância com o maior valor de ActiveTime é o alvo para a Etapa 3.
Etapa 3: Inspecionar métricas por operador
Objetivo: Determinar qual operador consome mais tempo e recursos na unidade de execução alvo.
SHOW QUERY PROFILE "/<profile_id>/<fragment_id>/<instance_id>"\G
Exemplo de saída para a instância c257c52f93e149ee-ace8ac14e8c9ff03 no Fragmento 1:
SHOW QUERY PROFILE "/c257c52f93e149ee-ace8ac14e8c9fef9/1/c257c52f93e149ee-ace8ac14e8c9ff03"\G
*************************** 1. row ***************************
Instance:
┌───────────────────────────────────────┐
│[9: DataStreamSender] │
│(Active: 37.222 us, non-child: 0.40) │
│ - Counters: │
│ - BytesSent: 0.00 │
│ - IgnoreRows: 0 │
│ - OverallThroughput: 0.0 /sec │
│ - PeakMemoryUsage: 8.00 KB │
│ - SerializeBatchTime: 0ns │
│ - UncompressedRowBatchSize: 0.00 │
└───────────────────────────────────────┘
└┐
│
┌──────────────────────────────────┐
│[4: SORT_NODE] │
│(Active: 5.421 ms, non-child: 0.71)│
│ - Counters: │
│ - PeakMemoryUsage: 12.00 KB │
│ - RowsReturned: 0 │
│ - RowsReturnedRate: 0 │
└──────────────────────────────────┘
┌┘
│
┌───────────────────────────────────┐
│[8: AGGREGATION_NODE] │
│(Active: 5.355 ms, non-child: 10.68)│
│ - Counters: │
│ - BuildTime: 3.701us │
│ - GetResultsTime: 0 ns │
│ - HTResize: 0 │
│ - HTResizeTime: 1.211 us │
│ - HashBuckets: 0 │
│ - HashCollisions: 0 │
│ - HashFailedProbe: 0 │
│ - HashFilledBuckets: 0 │
│ - HashProbe: 0 │
│ - HashTravelLength: 0 │
│ - LargestPartitionPercent: 0 │
│ - MaxPartitionLevel: 0 │
│ - NumRepartitions: 0 │
│ - PartitionsCreated: 16 │
│ - PeakMemoryUsage: 34.02 MB │
│ - RowsProcessed: 0 │
│ - RowsRepartitioned: 0 │
│ - RowsReturned: 0 │
│ - RowsReturnedRate: 0 │
│ - SpilledPartitions: 0 │
└───────────────────────────────────┘
└┐
│
┌──────────────────────────────────────────┐
│[7: EXCHANGE_NODE] │
│(Active: 4.360 ms, non-child: 46.84) │
│ - Counters: │
│ - BytesReceived: 0.00 │
│ - ConvertRowBatchTime: 387 ns │
│ - DataArrivalWaitTime: 4.357 ms │
│ - DeserializeRowBatchTimer: 0 ns │
│ - FirstBatchArrivalWaitTime: 4.356 ms│
│ - PeakMemoryUsage: 0.00 │
│ - RowsReturned: 0 │
│ - RowsReturnedRate: 0 │
│ - SendersBlockedTotalTimer(*): 0 ns │
└──────────────────────────────────────────┘
Uma porcentagem alta de Active combinada com uma porcentagem elevada de non-child em um nó indica que o próprio nó é o gargalo (e não um operador filho). Concentre seus esforços de otimização nesse ponto.
Exportar perfis de consulta
A exportação de perfis de consulta requer o SelectDB Core V3.0.4 ou posterior.
Exporte um perfil para um arquivo para análise offline ou compartilhamento.
-
Ative os perfis de consulta.
SET enable_profile=true; -
Execute a consulta que deseja analisar.
-- Run your target query. SelectDB generates a profile for it. SELECT count(1) FROM test_table LIMIT 10; -
Obtenha o ID do perfil.
Versões do SelectDB 4.0.x
Envie uma solicitação HTTP para obter informações sobre a consulta. O campo
Query IDna resposta corresponde ao ID do perfil.curl -u'<userName>:<userPassword>' \ "http://<selectdbAddress>:<httpPort>/rest/v2/manager/query/query_info?is_all_node=true"Exemplo de resposta:
{ "msg": "success", "code": 0, "data": { "column_names": [ "Query ID", "FE Node", "Query User", "Execution Database", "Sql", "Query Type", "Start Time", "End Time", "Execution Duration", "Status" ], "rows": [ [ ... ] ] }, "count": 0 }Versões do SelectDB 3.0.x
O exemplo a seguir mostra como obter o perfil no SelectDB 3.0:
SHOW QUERY PROFILE "/";Exemplo de saída:
+-----------------------------------+-----------+---------------------+---------------------+-------+------------+-------+------------------------------------+-------------------------------+ | Profile ID | Task Type | Start Time | End Time | Total | Task State | User | Default Db | Sql Statement | +-----------------------------------+-----------+---------------------+---------------------+-------+------------+-------+------------------------------------+-------------------------------+ | b9c9ba063d9d4365-97878361371e757a | QUERY | 2024-02-07 17:40:04 | 2024-02-07 17:40:04 | 32ms | EOF | admin | default_cluster:information_schema | select * from user_privileges | | 8800c306137e4072-9bb1ed419f4ac9f2 | QUERY | 2024-02-07 17:40:00 | 2024-02-07 17:40:00 | 3ms | ERR | admin | default_cluster:information_schema | select * from user_priveleges | | e2efdd1a996c4de2-ab939ad49b409990 | QUERY | 2024-02-07 17:39:51 | 2024-02-07 17:39:51 | 13ms | EOF | admin | | SELECT DATABASE() | +-----------------------------------+-----------+---------------------+---------------------+-------+------------+-------+------------------------------------+-------------------------------+ -
Exporte o perfil usando seu ID.
Espaço reservado
Descrição
Padrão
<userName>Nome de usuário para acessar a instância do SelectDB
—
<userPassword>Senha para acessar a instância do SelectDB
—
<selectdbAddress>Endpoint da instância do SelectDB
—
<httpPort>Número da porta HTTP
8080
<query_id>ID do perfil obtido na etapa 3
—
curl -u'<userName>:<userPassword>' \ "http://<selectdbAddress>:<httpPort>/api/profile?query_id=<query_id>"Para salvar a saída em um arquivo, redirecione a resposta:
curl -u'<userName>:<userPassword>' \ "http://<selectdbAddress>:<httpPort>/api/profile?query_id=<query_id>" > res.txtSubstitua os espaços reservados abaixo pelos valores reais:
-
(Opcional) Formate o arquivo exportado para melhorar a legibilidade.
sudo sed -r 's/\\n/\n/g' res.txt | sed -r 's/\\t/\t/g' > new.txt
Referência de parâmetros do perfil
As tabelas a seguir descrevem todos os parâmetros coletados em um perfil de consulta.
Fragmento
|
Parâmetro |
Descrição |
|
|
Quantidade de threads usadas na execução do fragmento, excluindo o uso do pool de threads. |
|
|
Pico de uso de memória do buffer pool. |
|
|
Limite de memória para a consulta. |
|
|
Pico de uso de memória de uma unidade de execução durante a consulta. |
|
|
Número de linhas cujas colunas foram processadas. |
BlockMgr
|
Parâmetro |
Descrição |
|
|
Quantidade de blocos criados pelo BlockManager. |
|
|
Quantidade de blocos reutilizados. |
|
|
Tamanho total dos dados gravados em disco. |
|
|
Tamanho de um único bloco. |
|
|
Tempo total consumido para ler blocos. |
DataStreamSender
|
Parâmetro |
Descrição |
|
|
Tamanho total dos dados enviados. Calculado como: número de receptores x tamanho dos dados enviados. |
|
|
Quantidade de linhas filtradas. |
|
|
Tamanho dos dados enviados pelo nó local e recebidos pelo mesmo nó durante a troca de dados. |
|
|
Throughput total. Calculado como: |
|
|
Tempo consumido para serializar os dados enviados. |
|
|
Tamanho dos dados RowBatch enviados antes da compressão. |
ODBC_TABLE_SINK
|
Parâmetro |
Descrição |
|
|
Quantidade total de linhas gravadas em uma tabela externa. |
|
|
Tempo consumido para serializar os dados enviados em instruções INSERT. |
|
|
Tempo consumido para gravar dados usando o driver Open Database Connectivity (ODBC). |
EXCHANGE_NODE
|
Parâmetro |
Descrição |
|
|
Tamanho dos dados recebidos pela rede. |
|
|
Caso a ordenação ocorra no nó filho, o nó de troca realiza uma mesclagem e ordenação unificadas. Este é o tempo total para essa operação, incluindo |
|
|
Tempo consumido pelo nó de mesclagem para buscar dados. Na mesclagem e ordenação de nível único, os dados vêm de uma fila de rede. Na mesclagem multinível, os dados vêm de um mesclador filho. |
|
|
Quando muitos remetentes enviam dados simultaneamente, a mesclagem single-thread torna-se um gargalo. O ApsaraDB for SelectDB inicia múltiplas threads no nó de mesclagem filho para mesclar e ordenar em paralelo. Este valor representa o tempo acumulado de todas as threads. |
|
|
Tempo consumido pelo nó de mesclagem filho para buscar dados. Valores altos podem indicar gargalos no nó de envio de dados filho. |
|
|
Tempo total de espera pelo envio de dados do remetente. |
|
|
Tempo de espera pelo primeiro lote de dados do remetente. |
|
|
Tempo consumido para desserializar os dados da rede. |
|
|
Tempo total de espera no lado do remetente quando a memória da fila DataStreamRecv está totalmente ocupada. |
|
|
Tempo consumido para converter os dados recebidos em RowBatch. |
|
|
Quantidade de linhas recebidas. |
|
|
Taxa de recebimento de linhas. |
SORT_NODE
|
Parâmetro |
Descrição |
|
|
Tempo consumido para ordenação em memória. |
|
|
Quantidade de vezes que a ordenação é inicializada. O valor é |
|
|
Tamanho total dos dados ordenados. |
|
|
Tempo consumido pelo MergeSort para obter o próximo lote de múltiplas execuções ordenadas. Medido apenas quando os dados são gravados em disco. |
|
|
Tempo consumido pelo MergeSort para extrair o lote da próxima execução ordenada. Medido apenas quando os dados são gravados em disco. |
|
|
Quantidade de vezes que a mesclagem externa é realizada. |
AGGREGATION_NODE
|
Parâmetro |
Descrição |
|
|
Quantidade de partições em que a consulta de agregação é dividida. |
|
|
Tempo consumido para obter resultados agregados das partições. |
|
|
Tempo consumido para redimensionar a tabela hash. |
|
|
Quantidade de vezes que a tabela hash é redimensionada. |
|
|
Quantidade de buckets na tabela hash. |
|
|
Quantidade de buckets com nós duplicados na tabela hash. |
|
|
Quantidade de colisões de hash na tabela hash. |
|
|
Quantidade de nós duplicados pertencentes ao mesmo bucket na tabela hash. |
|
|
Quantidade de operações de sondagem falhas na tabela hash. |
|
|
Quantidade de buckets preenchidos com dados na tabela hash. |
|
|
Quantidade de vezes que a tabela hash é consultada. |
|
|
Quantidade de passos percorridos durante uma consulta à tabela hash. |
HASH_JOIN_NODE
|
Parâmetro |
Descrição |
|
|
Método de construção da tabela hash para o nó filho direito: síncrono ou assíncrono. |
|
|
Quantidade de buckets na tabela hash. |
|
|
Quantidade de linhas na tabela hash. |
|
|
Tempo consumido para construir a tabela hash. |
|
|
Fator de carga da tabela hash, indicando a quantidade de buckets não vazios. |
|
|
Quantidade de linhas nas quais a operação de sondagem hash é realizada após percorrer os nós filhos esquerdos. |
|
|
Tempo consumido para percorrer os nós filhos esquerdos para sondagem hash, excluindo o tempo para chamar GetNext no RowBatch do nó filho esquerdo. |
|
|
Tempo consumido para calcular condições de pushdown de predicado. |
|
|
Tempo total consumido para pushdown de predicado. Consultas JOIN em nós filhos direitos que atendem às condições são convertidas em consultas IN nos nós filhos esquerdos. |
CROSS_JOIN_NODE
|
Parâmetro |
Descrição |
|
|
Método de construção do RowBatchList para o nó filho direito: síncrono ou assíncrono. |
|
|
Quantidade de linhas do RowBatchList (linhas no nó filho direito). |
|
|
Tempo consumido para construir o RowBatchList. |
|
|
Quantidade de linhas no nó filho esquerdo. |
|
|
Tempo consumido para percorrer os nós filhos esquerdo e direito para gerar o produto cartesiano, excluindo o tempo para chamar GetNext no RowBatch do nó filho esquerdo. |
UNION_NODE
|
Parâmetro |
Descrição |
|
|
Tempo consumido para avaliar expressões de conversão de tipo e materializar resultados quando os tipos de campo diferem em ambos os lados de um UNION. |
ANALYTIC_EVAL_NODE
|
Parâmetro |
Descrição |
|
|
Tempo total consumido para computação de funções analíticas (funções de janela). |
|
|
Tempo consumido para alocar um novo bloco durante a inicialização. O bloco armazena em cache a janela de Rows ou uma partição inteira para computação da função analítica. |
|
|
Tempo consumido para alocar um novo bloco ou reler na memória um bloco que foi gravado em disco. |
|
|
Tempo consumido para gravar os dados de um bloco em disco quando o bloco não é mais necessário ou quando o operador atual está sob alta pressão de memória. |
OLAP_SCAN_NODE
O OLAP_SCAN_NODE gerencia tarefas de varredura de dados. Ele cria um ou mais scanners OLAP, cada um responsável por varrer uma parte dos dados. O perfil organiza-se em três camadas que refletem a hierarquia de chamadas: OLAP_SCAN_NODE -> OlapScanner -> SegmentIterator.
Algumas ou todas as condições de predicado são enviadas ao OLAP_SCAN_NODE. As condições que podem usar índices do mecanismo de armazenamento são encaminhadas diretamente ao mecanismo para filtragem; as demais são avaliadas no próprio OLAP_SCAN_NODE.
Alguns valores de métricas variam dependendo do formato de armazenamento (V1 ou V2).
O exemplo a seguir mostra um perfil típico do OLAP_SCAN_NODE:
OLAP_SCAN_NODE (id=0):(Active: 1.2ms, % non-child: 0.00%)
- BytesRead: 265.00 B # Size of data read from data files. For example, 10 x 32-bit integers = 40 bytes. This reflects data fully loaded into memory, not raw I/O size.
- NumDiskAccess: 1 # Number of disks accessed by the ScanNode.
- NumScanners: 20 # Number of scanners created by the ScanNode.
- PeakMemoryUsage: 0.00 # Peak memory usage during the query.
- RowsRead: 7 # Rows returned from the storage engine to the scanner, excluding rows filtered by the scanner.
- RowsReturned: 7 # Rows returned from the ScanNode to the parent node.
- RowsReturnedRate: 6.979K /sec # RowsReturned / ActiveTime.
- TabletCount: 20 # Number of tablets accessed by the ScanNode.
- TotalReadThroughput: 74.70 KB/sec # BytesRead divided by total execution time. For I/O-bound queries, this approaches total disk throughput.
- ScannerBatchWaitTime: 426.886us # Time for the transfer thread to wait for the scanner thread to return RowBatch data.
- ScannerWorkerWaitTime: 17.745us # Time for the scanner thread to wait for available worker threads in the thread pool.
OlapScanner:
- BlockConvertTime: 8.941us # Time to convert a vectorized block to a row-structured RowBlock. The vectorized block is VectorizedRowBatch (V1) or RowBlockV2 (V2).
- BlockFetchTime: 468.974us # Time for the rowset reader to get blocks.
- ReaderInitTime: 5.475ms # Time for the OLAP scanner to initialize readers. Includes MergeHeap creation time (V1) and the time to generate all iterator levels and read the first block group (V2).
- RowsDelFiltered: 0 # Rows filtered based on DELETE information in the tablet and rows marked for deletion in the Unique Key model.
- RowsPushedCondFiltered: 0 # Rows filtered by predicates pushed down from a join operation (e.g., from BuildTable to ProbeTable). This value is approximate; filtering may be skipped if the effect is poor.
- ScanTime: 39.24us # Time for data to travel from ScanNode to the parent node.
- ShowHintsTime_V1: 0ns # V1 only: time to read some data for ScanRange splitting.
SegmentIterator:
- BitmapIndexFilterTimer: 779ns # Time to filter data using bitmap indexes.
- BlockLoadTime: 415.925us # Time for the segment reader (V1) or segment iterator (V2) to get blocks.
- BlockSeekCount: 12 # Number of block seeks during segment reading.
- BlockSeekTime: 222.556us # Time consumed for block seeks during segment reading.
- BlocksLoad: 6 # Number of blocks read.
- CachedPagesNum: 30 # V2 only: number of pages that hit the page cache.
- CompressedBytesRead: 0.00 # V1: size of data before decompression read from file. V2: size of pages before compression that did not hit the page cache.
- DecompressorTimer: 0ns # Time consumed for data decompression.
- IOTimer: 0ns # Actual I/O time for reading data from the operating system.
- IndexLoadTime_V1: 0ns # V1 only: time to read index streams.
- NumSegmentFiltered: 0 # Number of segments completely filtered out based on column statistics and query conditions.
- NumSegmentTotal: 6 # Total number of segments involved in the query.
- RawRowsRead: 7 # Source data rows read from the storage engine after all preceding filtering.
- RowsBitmapIndexFiltered: 0 # V2 only: rows filtered using bitmap indexes.
- RowsBloomFilterFiltered: 0 # V2 only: rows filtered using BloomFilter indexes.
- RowsKeyRangeFiltered: 0 # V2 only: rows filtered using SortkeyIndex indexes.
- RowsStatsFiltered: 0 # V2: rows filtered using ZoneMap indexes, including delete conditions. V1: includes rows filtered using BloomFilter indexes.
- RowsConditionsFiltered: 0 # V2 only: rows filtered by all column indexes combined.
- RowsVectorPredFiltered: 0 # Rows filtered by vectorized condition operations.
- TotalPagesNum: 30 # V2 only: total number of pages read.
- UncompressedBytesRead: 0.00 # V1: size of data after decompression (or file size if not compressed). V2: size of pages that did not hit the page cache after decompression (or page size if not compressed).
- VectorPredEvalTime: 0ns # Time to perform filtering by vectorized condition.
- ShortPredEvalTime: 0ns # Time to perform filtering by short-circuit predicate.
- PredColumnReadTime: 0ns # Time consumed for predicate column reading.
- LazyReadTime: 0ns # Time consumed to read non-predicate columns.
- OutputColumnTime: 0ns # Time consumed for column materialization.
Relação entre as métricas de filtragem
As métricas de contagem de linhas em um perfil do OLAP_SCAN_NODE revelam a eficácia dos predicados e índices na redução do volume de dados em cada etapa. A descrição abaixo refere-se à sequência de filtragem do formato V2. As métricas do formato V1 possuem significados ligeiramente diferentes.
Fase de inicialização
A filtragem ocorre nesta ordem:
SortkeyIndex — Se a consulta possuir intervalos de chave (prefix key ranges), os dados são filtrados primeiramente. As linhas eliminadas são registradas em
RowsKeyRangeFiltered.Índices Bitmap — Aplica-se filtragem precisa de colunas para condições correspondentes aos índices bitmap. As linhas eliminadas são registradas em
RowsBitmapIndexFiltered.-
Índices BloomFilter — Condições de igualdade (
=,IN,IS) são filtradas usando índices BloomFilter. As linhas eliminadas são registradas emRowsBloomFilterFiltered.NotaRowsBloomFilterFiltered
é calculado como o total de linhas do segmento menos as linhas restantes após a filtragem BloomFilter. Pode haver sobreposição com linhas já eliminadas por índices bitmap.
Índices ZoneMap — Os dados são filtrados com base nas condições de consulta e exclusão. As linhas eliminadas são registradas em
RowsStatsFiltered.RowsConditionsFilteredrepresenta o total de linhas filtradas por todos os índices combinados, incluindoRowsBloomFilterFilteredeRowsStatsFiltered.
Próxima fase
Após a inicialização, os dados restantes passam por estágios adicionais:
RowsDelFiltered: Linhas eliminadas por condições de exclusão. Estas também são contabilizadas emRowsStatsFiltered.RawRowsRead: Linhas restantes após toda a filtragem anterior.RowsRead: Linhas retornadas do mecanismo de armazenamento para o scanner. Geralmente é menor queRawRowsReadporque o mecanismo de armazenamento pode agregar linhas. Uma grande diferença entreRawRowsReadeRowsReadindica agregação intensa, o que pode ser uma preocupação de desempenho.RowsReturned: Linhas finalmente retornadas pelo ScanNode ao nó pai. Normalmente é menor queRowsReadporque predicados não enviados ao mecanismo de armazenamento são aplicados no nível do scanner. Uma grande diferença entreRowsReadeRowsReturnedsignifica que muitos predicados de alta seletividade não estão chegando ao mecanismo de armazenamento, onde a filtragem seria mais eficiente.
Em conjunto, as métricas Rows***Filtered permitem avaliar se os predicados da consulta estão sendo enviados ao mecanismo de armazenamento e qual a eficácia de cada tipo de índice.
Outras métricas
-
As métricas sob
OlapScanner— comoIOTimereBlockFetchTime— são cumulativas em todas as threads do scanner. Como as threads do scanner leem dados de forma assíncrona, esses valores acumulados refletem o tempo total de trabalho do scanner, e não o tempo de relógio (wall-clock) do ScanNode. A porcentagemActiveregistra a proporção real de tempo que o ScanNode contribuiu para o plano de execução geral. É normal observarIOTimerna casa das dezenas de segundos enquantoActivemarca apenas alguns segundos, por dois motivos:IOTimeracumula tempo de vários scanners rodando em paralelo.Se o nó pai for lento (por exemplo, 100 segundos), o ScanNode (10 segundos) termina cedo e prepara os dados em segundo plano. O nó pai então recupera os dados preparados, resultando em um tempo
Activecurto para o ScanNode.
NumScannersindica a quantidade de tarefas que o scanner submete ao pool de threads, gerenciado peloRuntimeState. Os parâmetrosdoris_scanner_thread_pool_thread_numedoris_scanner_thread_pool_queue_sizecontrolam o tamanho do pool de threads e o comprimento da fila. Se a quantidade de threads for excessiva ou insuficiente, a eficiência da consulta será afetada. Você também pode dividir algumas métricas pelo número de threads para estimar aproximadamente o tempo consumido por cada thread.TabletCountrepresenta a quantidade de tablets a serem varridos. Uma contagem alta de tablets implica mais leituras aleatórias e operações de mesclagem de dados.UncompressedBytesReadreflete o volume de dados lidos. Um valor alto pode indicar E/S intensa.Compare
CachedPagesNumcomTotalPagesNumpara avaliar a taxa de acerto do cache de páginas. Uma taxa de acerto maior reduz tanto a E/S quanto a sobrecarga de descompressão.
Buffer pool
|
Parâmetro |
Descrição |
|
|
Tempo consumido para alocação de memória. |
|
|
Tamanho cumulativo da memória alocada. |
|
|
Quantidade cumulativa de alocações de memória. |
|
|
Tamanho máximo de reserva. |
|
|
Tamanho dos dados de memória não fixados (unpinned). |
|
|
Uso de memória das reservas. |
|
|
Limite de reserva no buffer pool. |