- Categorias:
Funções do sistema (Informações de consulta) , Funções de tabela
GET_QUERY_OPERATOR_STATS¶
Retorna estatísticas sobre os operadores de consulta individual dentro de uma consulta que tenha sido concluída. Você pode executar esta função para qualquer consulta concluída que tenha sido executada nos últimos 14 dias.
Você pode usar estas informações para compreender a estrutura de uma consulta e identificar os operadores de consulta (por exemplo, o operador de junção) que causam problemas de desempenho.
Por exemplo, você pode usar estas informações para determinar quais operadores estão consumindo mais recursos. Como outro exemplo, você pode usar esta função para identificar junções que tenham mais linhas de saída do que linhas de entrada, o que pode ser um sinal de uma junção «explodindo» (por exemplo, um produto cartesiano não intencional).
Estas estatísticas também estão disponíveis na guia perfil da consulta em Snowsight. A função GET_QUERY_OPERATOR_STATS()
torna as mesmas informações disponíveis através de uma interface programática.
Para obter mais informações sobre como encontrar operadores de consulta problemáticos, consulte Problemas comuns de consulta identificados pelo perfil de consulta.
Sintaxe¶
GET_QUERY_OPERATOR_STATS( <query_id> )
Argumentos¶
query_id
A ID de uma consulta. Você pode usar:
Uma cadeia de caracteres literal (uma cadeia de caracteres entre aspas simples).
Uma variável de sessão contendo um ID de consulta.
O valor de retorno de uma chamada para a função LAST_QUERY_ID.
Retornos¶
Se a função GET_QUERY_OPERATOR_STATS for uma função de tabela. Ela retorna linhas com estatísticas sobre cada operador de consulta na consulta. Para obter mais informações, consulte as seções Notas de uso e Saída abaixo.
Notas de uso¶
Esta função só retorna estatísticas sobre as consultas que foram concluídas.
Você deve ter privilégios OPERATE ou MONITOR no warehouse onde executou a consulta.
Esta função fornece estatísticas detalhadas sobre cada operador de consulta utilizada na consulta especificada. Os possíveis operadores de consulta incluem:
Aggregate: agrupa entradas e computa funções agregadas.
CartesianJoin: um tipo especializado de junção.
Delete: remove um registro de uma tabela.
ExternalFunction: representa o processamento por uma função externa.
ExternalScan: representa o acesso a dados armazenados em objetos de preparação.
Filter: representa uma operação que filtra as linhas.
Flatten: processa registros VARIANT, possivelmente nivelando-os em um caminho especificado.
Generator: gera registros usando o constructo TABLE(GENERATOR(…)).
GroupingSets: representa construtos como GROUPING SETS, ROLLUP e CUBE.
Insert: adiciona registros a uma tabela através de uma operação INSERT ou COPY.
InternalObject: representa o acesso a um objeto de dados interno (por exemplo, um Information Schema ou o resultado de uma consulta anterior).
Join: combina duas entradas em uma determinada condição.
JoinFilter: operação de filtragem especial que remove tuplas que podem ser identificadas como possivelmente não correspondendo à condição de uma junção mais além no plano da consulta.
Merge: realiza uma operação MERGE em uma tabela.
Pivot: transforma valores únicos de uma coluna em várias colunas e faz qualquer agregação necessária.
Result: retorna o resultado da consulta.
Sort: ordena a entrada em uma determinada expressão.
SortWithLimit: produz uma parte da sequência de entrada após a classificação, normalmente um resultado de um constructo
ORDER BY ... LIMIT ... OFFSET ...
.TableScan: representa o acesso a uma única tabela.
UnionAll: concatena duas entradas.
Unload: representa uma operação COPY que exporta dados de uma tabela para um arquivo em um estágio.
Unpivot: gira uma tabela transformando colunas em linhas.
Update: atualiza um registro em uma tabela.
ValuesClause: lista de valores fornecidos com a cláusula VALUES.
WindowFunction: computa funções de janela.
WithClause: precede o corpo da instrução SELECT e define um ou mais CTEs.
WithReference: instância de uma cláusula WITH.
A informação é devolvida como uma tabela. Cada linha na tabela corresponde a um operador. A linha contém a divisão da execução e as estatísticas de consulta para esse operador.
A linha também pode listar atributos do operador (estes dependem do tipo de operador).
As estatísticas que decompõem o tempo de execução da consulta são expressas como uma porcentagem do tempo consumido pela consulta total.
Para obter mais informações sobre estatísticas específicas, consulte Saída (neste tópico).
Como esta função é uma função de tabela, você deve usá-la em uma cláusula FROM e deve encapsulá-la em
TABLE()
. Por exemplo:select * from table(get_query_operator_stats(last_query_id()));
Para cada execução individual de uma consulta específica (ou seja, um UUID específico), esta função é determinista; ela retorna os mesmos valores a cada vez.
Entretanto, para diferentes execuções de um mesmo texto de consulta, esta função pode retornar estatísticas de tempo de execução diferentes. As estatísticas dependem de muitos fatores. Os seguintes fatores podem ter um grande impacto na execução e, portanto, nas estatísticas retornadas por esta função:
O volume de dados.
A disponibilidade de exibições materializadas e as mudanças (se houver) nos dados desde que essas exibições materializadas foram atualizadas pela última vez.
A presença ou ausência de clustering.
A presença ou ausência de dados previamente armazenados em cache.
O tamanho do warehouse virtual.
Os valores também podem ser afetados por fatores fora da consulta e dos dados do usuário. Estes fatores são geralmente pequenos. Os fatores incluem:
Tempo de inicialização do warehouse virtual.
Latência com funções externas.
Saída¶
A função retorna as seguintes colunas:
Nome da coluna |
Tipo de dados |
Descrição |
---|---|---|
QUERY_ID |
VARCHAR |
Um ID de consulta, que é um identificador interno gerado pelo sistema para a instrução SQL. |
STEP_ID |
NUMBER(38, 0) |
Identificador da etapa no plano de consulta. |
OPERATOR_ID |
NUMBER(38, 0) |
O identificador do operador. Isto é único dentro da consulta. Os valores começam em 0. |
PARENT_OPERATORS |
ARRAY contendo um ou mais NUMBER(38, 0) |
Identificadores dos operadores pai para este operador ou NULL se este for o operador final no plano de consulta (que normalmente é o operador Resultado). |
OPERATOR_TYPE |
VARCHAR |
O tipo de operador de consulta (por exemplo, |
VARIANT contendo um OBJECT |
Estatísticas sobre o operador (por exemplo, o número de linhas de saída do operador). |
|
VARIANT contendo um OBJECT |
Informações sobre o tempo de execução do operador. |
|
VARIANT contendo um OBJECT |
Informações sobre o operador. Esta informação depende do tipo de operador. |
Se não houver informações para a coluna específica do operador, o valor será NULL.
Três destas colunas contêm OBJECTs. Cada objeto contém pares de chave/valor. As tabelas abaixo mostram informações sobre as chaves destas tabelas.
OPERATOR_STATISTICS¶
Os campos em OBJECTs da coluna OPERATOR_STATISTICS
fornecem informações adicionais sobre o operador. As informações podem incluir:
Chave |
Chave aninhada (se aplicável) |
Tipo de dados |
Descrição |
---|---|---|---|
|
Estatísticas para consultas de linguagem de manipulação de dados (DML): |
||
|
DOUBLE |
O número de linhas inseridas em uma tabela (ou tabelas). |
|
|
DOUBLE |
O número de linhas atualizadas em uma tabela. |
|
|
DOUBLE |
O número de linhas excluídas de uma tabela. |
|
|
DOUBLE |
O número de linhas descarregadas durante a exportação de dados. |
|
|
Informações sobre chamadas para funções externas. Se o valor de um campo, por exemplo |
||
|
DOUBLE |
O número de vezes que uma função externa foi chamada. (Isto pode ser diferente do número de chamadas de funções externas no texto da instrução SQL devido ao número de lotes em que as linhas estão divididas, o número de novas tentativas (se houver problemas transitórios na rede), etc.) |
|
|
DOUBLE |
O número de linhas enviadas para funções externas. |
|
|
DOUBLE |
O número de linhas recebidas de volta das funções externas. |
|
|
DOUBLE |
O número de bytes enviados para funções externas. Se a chave incluir |
|
|
DOUBLE |
O número de bytes recebidos de funções externas. Se a chave incluir |
|
|
DOUBLE |
O número de tentativas de repetição devido a erros transitórios. |
|
|
DOUBLE |
A média de tempo por invocação (chamada) em milissegundos entre o momento em que Snowflake enviou os dados e o recebimento dos dados devolvidos. |
|
|
INTEGER |
Número total de solicitações de HTTP que retornaram um código de status 4xx. |
|
|
INTEGER |
Número total de solicitações de HTTP que retornaram um código de status 5xx. |
|
|
DOUBLE |
Latência média para solicitações de HTTP bem-sucedidas. |
|
|
DOUBLE |
Sobretaxa média por solicitação bem-sucedida devido a uma desaceleração causada pela limitação (HTTP 429). |
|
|
DOUBLE |
Número de lotes que foram repetidos devido a erros HTTP 429. |
|
|
DOUBLE |
Latência de percentil 50 para solicitações de HTTP bem-sucedidas. 50 por cento de todas as solicitações bem-sucedidas levaram menos do que esse tempo para serem concluídas. |
|
|
DOUBLE |
Latência de percentil 90 para solicitações de HTTP bem-sucedidas. 90 por cento de todas as solicitações bem-sucedidas levaram menos do que esse tempo para serem concluídas. |
|
|
DOUBLE |
Latência de percentil 95 para solicitações de HTTP bem-sucedidas. 95 por cento de todas as solicitações bem-sucedidas levaram menos do que esse tempo para serem concluídas. |
|
|
DOUBLE |
Latência de percentil 99 para solicitações de HTTP bem-sucedidas. 99 por cento de todas as solicitações bem-sucedidas levaram menos do que esse tempo para serem concluídas. |
|
|
INTEGER |
O número de linhas de entrada. Isto pode estar faltando para um operador sem bordas de entrada de outros operadores. |
|
|
Informações sobre as operações de I/O (entrada/saída) realizadas durante a consulta. |
||
|
DOUBLE |
A porcentagem de dados verificados para uma determinada tabela até o momento. |
|
|
DOUBLE |
O número de bytes verificados até o momento. |
|
|
DOUBLE |
A porcentagem de dados escaneados a partir do cache de disco local. |
|
|
DOUBLE |
Bytes gravados (por exemplo, ao carregar em uma tabela). |
|
|
DOUBLE |
Bytes gravados em um objeto de resultado. Por exemplo, Em geral, o objeto de resultado representa tudo o que é produzido como resultado da consulta, e |
|
|
DOUBLE |
Bytes lidos de um objeto resultado. |
|
|
DOUBLE |
Bytes lidos a partir de um objeto externo (por exemplo, um estágio). |
|
|
|
DOUBLE |
A quantidade de dados enviados pela rede. |
|
INTEGER |
O número de linhas de saída. Isto pode estar em falta para o operador que retorna os resultados ao usuário (que normalmente é o operador RESULT). |
|
|
Informações sobre a remoção realizada na tabela. |
||
|
DOUBLE |
O número de partições verificadas até o momento. |
|
|
DOUBLE |
O número total de partições em uma determinada tabela. |
|
|
Informações sobre o uso do disco para operações nas quais os resultados intermediários não cabem na memória. |
||
|
DOUBLE |
O volume de dados despejados em disco remoto. |
|
|
DOUBLE |
O volume de dados despejados em disco local. |
|
|
Informações sobre chamadas para funções de extensão. Se o valor de um campo for zero, então o campo não será exibido. |
||
|
DOUBLE |
quantidade de tempo para que o manipulador da UDF de Java seja carregado. |
|
|
DOUBLE |
número de vezes que o manipulador da UDF de Java é invocado. |
|
|
DOUBLE |
quantidade de tempo máxima para que o manipulador da UDF de Java seja executado. |
|
|
DOUBLE |
quantidade média de tempo para executar o manipulador da UDF de Java. |
|
|
DOUBLE |
número de vezes que o método de processo da UDTF foi invocado. |
|
|
DOUBLE |
quantidade de tempo para executar o processo da UDTF de Java. |
|
|
DOUBLE |
quantidade média de tempo para executar o processo da UDTF de Java. |
|
|
DOUBLE |
número de vezes que o construtor da UDTF foi invocado. |
|
|
DOUBLE |
quantidade de tempo para executar o construtor da UDTF de Java. |
|
|
DOUBLE |
quantidade média de tempo para executar o construtor da UDTF de Java. |
|
|
DOUBLE |
número de vezes que o método endPartition da UDTF foi invocado. |
|
|
DOUBLE |
quantidade de tempo para executar o método endPartition da UDTF de Java. |
|
|
DOUBLE |
quantidade média de tempo para executar o método endPartition da UDTF de Java. |
|
|
DOUBLE |
quantidade máxima de tempo para baixar as dependências da UDF de Java. |
|
|
DOUBLE |
pico de uso de memória conforme relatado pelo JVM. |
|
|
DOUBLE |
tempo de compilação para o código inline da UDF de Java. |
|
|
DOUBLE |
número de vezes que o manipulador da UDF de Python foi invocado. |
|
|
DOUBLE |
tempo total de execução do manipulador da UDF de Python. |
|
|
DOUBLE |
quantidade média de tempo para executar o manipulador da UDF de Python. |
|
|
DOUBLE |
pico de uso de memória pelo ambiente sandbox do Python. |
|
|
DOUBLE |
quantidade média de tempo para criar o ambiente Python, incluindo download e instalação de pacotes. |
|
|
DOUBLE |
quantidade de tempo para executar o solucionador Conda para resolver pacotes Python. |
|
|
DOUBLE |
quantidade de tempo para criar o ambiente Python. |
|
|
DOUBLE |
quantidade de tempo para inicializar a UDF de Python. |
|
|
DOUBLE |
número de bytes de arquivos externos lidos para UDFs. |
|
|
DOUBLE |
número de arquivos externos acessados para UDFs. |
EXECUTION_TIME_BREAKDOWN¶
Os campos em OBJECTs da coluna EXECUTION_TIME_BREAKDOWN
são mostrados abaixo.
Chave |
Tipo de dados |
Descrição |
---|---|---|
|
DOUBLE |
A porcentagem do tempo total de consulta gasto por este operador. |
|
DOUBLE |
Tempo gasto na preparação do processamento da consulta. |
|
DOUBLE |
Tempo gasto no processamento dos dados pela CPU. |
|
DOUBLE |
Tempo gasto sincronizando as atividades entre os processos participantes. |
|
DOUBLE |
Tempo durante o qual o processamento foi bloqueado enquanto se aguardava o acesso ao disco local. |
|
DOUBLE |
Tempo durante o qual o processamento foi bloqueado enquanto se aguardava o acesso remoto ao disco. |
|
DOUBLE |
Tempo durante o qual o processamento aguardava a transferência dos dados da rede. |
OPERATOR_ATTRIBUTES¶
Cada linha de saída descreve um operador na consulta. A tabela abaixo mostra os tipos possíveis de operadores (por exemplo, o operador do filtro). Para cada tipo de operador, a tabela mostra os atributos possíveis (por exemplo, a expressão usada para filtrar as linhas).
Os atributos do operador são armazenados na coluna OPERATOR_ATTRIBUTES
, que é do tipo VARIANT e contém um OBJECT. O OBJECT contém pares de chave/valor. Cada chave corresponde a um atributo do operador.
Nome do operador |
Chave |
Tipo de dados |
Descrição |
---|---|---|---|
|
|||
|
ARRAY de VARCHAR |
Lista de funções computadas. |
|
|
ARRAY de VARCHAR |
A expressão de agrupamento. |
|
|
|||
|
VARCHAR |
Expressão de junção de não equidade. |
|
|
VARCHAR |
Expressão de junção de equidade. |
|
|
VARCHAR |
Tipo de junção (INNER). |
|
|
|
VARCHAR |
Nome da tabela atualizada. |
|
|||
|
VARCHAR |
O nome do estágio a partir do qual os dados são lidos. |
|
|
VARCHAR |
O tipo do estágio. |
|
|
|
VARCHAR |
A expressão utilizada para filtrar dados. |
|
|
VARCHAR |
A expressão de entrada usada para nivelar os dados. |
|
|||
|
NUMBER |
Valor do parâmetro de entrada ROWCOUNT. |
|
|
NUMBER |
Valor do parâmetro de entrada TIMELIMIT. |
|
|
|||
|
ARRAY de VARCHAR |
Lista de funções computadas. |
|
|
ARRAY de VARCHAR |
Lista de conjuntos de agrupamento. |
|
|
|||
|
VARCHAR |
Quais expressões são inseridas. |
|
|
ARRAY de VARCHAR |
Lista dos nomes das tabelas às quais são adicionados os registros. |
|
|
|
VARCHAR |
O nome do objeto acessado. |
|
|||
|
VARCHAR |
Expressão de junção de não equidade. |
|
|
VARCHAR |
Expressão de junção de equidade. |
|
|
VARCHAR |
Tipo de junção (INNER, OUTER, LEFT JOIN etc.). |
|
|
|
NUMBER |
O id do operador da junção usada para identificar tuplas que podem ser filtradas. |
|
|
VARCHAR |
Nome da tabela atualizada. |
|
|||
|
ARRAY de VARCHAR |
Colunas restantes nas quais os resultados são agregados. |
|
|
ARRAY de VARCHAR |
Colunas resultantes de valores articulados. |
|
|
|
ARRAY de VARCHAR |
Lista de expressões produzidas. |
|
|
ARRAY de VARCHAR |
Expressão que define a classificação. |
|
|||
|
NUMBER |
Posição na sequência ordenada a partir da qual as tuplas produzidas são emitidas. |
|
|
NUMBER |
Número de linhas produzidas. |
|
|
ARRAY de VARCHAR |
Expressão que define a classificação. |
|
|
|||
|
ARRAY de VARCHAR |
Lista de colunas verificadas. |
|
|
ARRAY de VARCHAR |
Lista de caminhos extraídos das colunas de variantes. |
|
|
VARCHAR |
Alias da tabela sendo acessada. |
|
|
VARCHAR |
Nome da tabela sendo acessada. |
|
|
|
VARCHAR |
Estágio onde os dados são salvos. |
|
|
ARRAY de VARCHAR |
Colunas de saída da consulta não articulada. |
|
|
VARCHAR |
Nome da tabela atualizada. |
|
|||
|
NUMBER |
Número de valores produzidos. |
|
|
VARCHAR |
Lista de valores. |
|
|
|
ARRAY de VARCHAR |
Lista de funções computadas. |
|
|
VARCHAR |
Alias da cláusula WITH. |
Se um operador não for listado, nenhum atributo será produzido e o valor será informado como {}
.
Nota
Os seguintes operadores não têm atributos de operador e, portanto, não estão incluídos na tabela de
OPERATOR_ATTRIBUTES
:UnionAll
ExternalFunction
Exemplos¶
Recuperação de dados de uma única consulta¶
Este exemplo mostra as estatísticas para um SELECT que une duas pequenas tabelas.
Execute a instrução SELECT:
select x1.i, x2.i
from x1 inner join x2 on x2.i = x1.i
order by x1.i, x2.i;
Obtenha o ID da consulta:
set lqid = (select last_query_id());
Chame GET_QUERY_OPERATOR_STATS() para obter estatísticas dos operadores da consulta individual na consulta:
select * from table(get_query_operator_stats($lqid));
+--------------------------------------+---------+-------------+--------------------+---------------+-----------------------------------------+-----------------------------------------------+----------------------------------------------------------------------+
| QUERY_ID | STEP_ID | OPERATOR_ID | PARENT_OPERATORS | OPERATOR_TYPE | OPERATOR_STATISTICS | EXECUTION_TIME_BREAKDOWN | OPERATOR_ATTRIBUTES |
|--------------------------------------+---------+-------------+--------------------+---------------+-----------------------------------------+-----------------------------------------------+----------------------------------------------------------------------|
| 01a8f330-0507-3f5b-0000-43830248e09a | 1 | 0 | NULL | Result | { | { | { |
| | | | | | "input_rows": 64 | "overall_percentage": 0.000000000000000e+00 | "expressions": [ |
| | | | | | } | } | "X1.I", |
| | | | | | | | "X2.I" |
| | | | | | | | ] |
| | | | | | | | } |
| 01a8f330-0507-3f5b-0000-43830248e09a | 1 | 1 | [ 0 ] | Sort | { | { | { |
| | | | | | "input_rows": 64, | "overall_percentage": 0.000000000000000e+00 | "sort_keys": [ |
| | | | | | "output_rows": 64 | } | "X1.I ASC NULLS LAST", |
| | | | | | } | | "X2.I ASC NULLS LAST" |
| | | | | | | | ] |
| | | | | | | | } |
| 01a8f330-0507-3f5b-0000-43830248e09a | 1 | 2 | [ 1 ] | Join | { | { | { |
| | | | | | "input_rows": 128, | "overall_percentage": 0.000000000000000e+00 | "equality_join_condition": "(X2.I = X1.I)", |
| | | | | | "output_rows": 64 | } | "join_type": "INNER" |
| | | | | | } | | } |
| 01a8f330-0507-3f5b-0000-43830248e09a | 1 | 3 | [ 2 ] | TableScan | { | { | { |
| | | | | | "io": { | "overall_percentage": 0.000000000000000e+00 | "columns": [ |
| | | | | | "bytes_scanned": 1024, | } | "I" |
| | | | | | "percentage_scanned_from_cache": 1, | | ], |
| | | | | | "scan_progress": 1 | | "table_name": "MY_DB.MY_SCHEMA.X2" |
| | | | | | }, | | } |
| | | | | | "output_rows": 64, | | |
| | | | | | "pruning": { | | |
| | | | | | "partitions_scanned": 1, | | |
| | | | | | "partitions_total": 1 | | |
| | | | | | } | | |
| | | | | | } | | |
| 01a8f330-0507-3f5b-0000-43830248e09a | 1 | 4 | [ 2 ] | JoinFilter | { | { | { |
| | | | | | "input_rows": 64, | "overall_percentage": 0.000000000000000e+00 | "join_id": "2" |
| | | | | | "output_rows": 64 | } | } |
| | | | | | } | | |
| 01a8f330-0507-3f5b-0000-43830248e09a | 1 | 5 | [ 4 ] | TableScan | { | { | { |
| | | | | | "io": { | "overall_percentage": 0.000000000000000e+00 | "columns": [ |
| | | | | | "bytes_scanned": 1024, | } | "I" |
| | | | | | "percentage_scanned_from_cache": 1, | | ], |
| | | | | | "scan_progress": 1 | | "table_name": "MY_DB.MY_SCHEMA.X1" |
| | | | | | }, | | } |
| | | | | | "output_rows": 64, | | |
| | | | | | "pruning": { | | |
| | | | | | "partitions_scanned": 1, | | |
| | | | | | "partitions_total": 1 | | |
| | | | | | } | | |
| | | | | | } | | |
+--------------------------------------+---------+-------------+--------------------+---------------+-----------------------------------------+-----------------------------------------------+----------------------------------------------------------------------+
Identificação a “explosão” de operadores de junção¶
O exemplo a seguir mostra como usar GET_QUERY_OPERATOR_STATS para examinar uma consulta complicada. Este exemplo procura por operadores dentro de uma consulta que produzam muito mais linhas do que foram entradas para aquele operador.
Esta é a consulta a ser analisada:
select *
from t1
join t2 on t1.a = t2.a
join t3 on t1.b = t3.b
join t4 on t1.c = t4.c
;
Obtenha o ID da consulta anterior:
set lid = last_query_id();
A consulta seguinte mostra a relação entre as linhas de saída e as linhas de entrada para cada um dos operadores de junção na consulta.
select
operator_id,
operator_attributes,
operator_statistics:output_rows / operator_statistics:input_rows as row_multiple
from table(get_query_operator_stats($lid))
where operator_type = 'Join'
order by step_id, operator_id;
+---------+-------------+--------------------------------------------------------------------------+---------------+
| STEP_ID | OPERATOR_ID | OPERATOR_ATTRIBUTES | ROW_MULTIPLE |
+---------+-------------+--------------------------------------------------------------------------+---------------+
| 1 | 1 | { "equality_join_condition": "(T4.C = T1.C)", "join_type": "INNER" } | 49.969249692 |
| 1 | 3 | { "equality_join_condition": "(T3.B = T1.B)", "join_type": "INNER" } | 116.071428571 |
| 1 | 5 | { "equality_join_condition": "(T2.A = T1.A)", "join_type": "INNER" } | 12.20657277 |
+---------+-------------+--------------------------------------------------------------------------+---------------+
Após identificar as junções com explosão, você pode rever cada condição de junção para verificar se a condição está correta.