Consultas úteis para troubleshooting
Sem nenhuma ordem específica, aqui estão algumas consultas úteis para solucionar problemas no ClickHouse e entender o que está acontecendo.
Também temos um ótimo post no blog com algumas consultas essenciais para monitorar o ClickHouse.
Veja quais configurações foram alteradas em relação ao valor padrão
SELECT
name,
value
FROM system.settings
WHERE changedVerifique o tamanho de todas as suas tabelas
SELECT table,
formatReadableSize(sum(bytes)) as size
FROM system.parts
WHERE active
GROUP BY tableA resposta é assim:
┌─table───────────┬─size──────┐
│ stat │ 38.89 MiB │
│ customers │ 525.00 B │
│ my_sparse_table │ 40.73 MiB │
│ crypto_prices │ 32.18 MiB │
│ hackernews │ 6.23 GiB │
└─────────────────┴───────────┘Número de linhas e tamanho médio diário da sua tabela
SELECT
table,
formatReadableSize(size) AS size,
rows,
days,
formatReadableSize(avgDaySize) AS avgDaySize
FROM
(
SELECT
table,
sum(bytes) AS size,
sum(rows) AS rows,
min(min_date) AS min_date,
max(max_date) AS max_date,
max_date - min_date AS days,
size / (max_date - min_date) AS avgDaySize
FROM system.parts
WHERE active
GROUP BY table
ORDER BY rows DESC
)Percentual de compressão das colunas, bem como o tamanho do índice primário em memória
Você pode ver o nível de compressão dos seus dados por coluna. Esta consulta também retorna o tamanho dos seus índices primários em memória — algo útil de saber, porque os índices primários precisam caber na memória.
SELECT
parts.*,
columns.compressed_size,
columns.uncompressed_size,
columns.compression_ratio,
columns.compression_percentage
FROM
(
SELECT
table,
formatReadableSize(sum(data_uncompressed_bytes)) AS uncompressed_size,
formatReadableSize(sum(data_compressed_bytes)) AS compressed_size,
round(sum(data_compressed_bytes) / sum(data_uncompressed_bytes), 3) AS compression_ratio,
round(100 - ((sum(data_compressed_bytes) * 100) / sum(data_uncompressed_bytes)), 3) AS compression_percentage
FROM system.columns
GROUP BY table
) AS columns
RIGHT JOIN
(
SELECT
table,
sum(rows) AS rows,
max(modification_time) AS latest_modification,
formatReadableSize(sum(bytes)) AS disk_size,
formatReadableSize(sum(primary_key_bytes_in_memory)) AS primary_keys_size,
any(engine) AS engine,
sum(bytes) AS bytes_size
FROM system.parts
WHERE active
GROUP BY
database,
table
) AS parts ON columns.table = parts.table
ORDER BY parts.bytes_size DESCNúmero de consultas enviadas pelo cliente nos últimos 10 minutos
Você pode aumentar ou diminuir o intervalo de tempo na função toIntervalMinute(10):
SELECT
client_name,
count(),
query_kind,
toStartOfMinute(event_time) AS event_time_m
FROM system.query_log
WHERE (type = 'QueryStart') AND (event_time > (now() - toIntervalMinute(10)))
GROUP BY
event_time_m,
client_name,
query_kind
ORDER BY
event_time_m DESC,
count() ASCNúmero de partes em cada partição
SELECT
concat(database, '.', table),
partition_id,
count()
FROM system.parts
WHERE active
GROUP BY
database,
table,
partition_idEncontrar consultas de longa duração
Isso pode ajudar a encontrar consultas travadas:
SELECT
elapsed,
initial_user,
client_name,
hostname(),
query_id,
query
FROM clusterAllReplicas(default, system.processes)
ORDER BY elapsed DESCUsando o Query id da consulta com pior desempenho, podemos obter um stack trace que pode ajudar na depuração.
SET allow_introspection_functions=1;
SELECT
arrayStringConcat(
arrayMap(
x,
y -> concat(x, ': ', y),
arrayMap(x -> addressToLine(x), trace),
arrayMap(x -> demangle(addressToSymbol(x)), trace)
),
'\n'
) as trace
FROM
system.stack_trace
WHERE
query_id = '0bb6e88b-9b9a-4ffc-b612-5746c859e360';Veja os erros mais recentes
SELECT *
FROM system.errors
ORDER BY last_error_time DESCA resposta é assim:
┌─name──────────────────┬─code─┬─value─┬─────last_error_time─┬─last_error_message──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬─last_error_trace─┬─remote─┐
│ UNKNOWN_TABLE │ 60 │ 3 │ 2023-03-14 01:02:35 │ Table system.stack_trace doesn't exist │ [] │ 0 │
│ BAD_GET │ 170 │ 1 │ 2023-03-14 00:58:55 │ Requested cluster 'default' not found │ [] │ 0 │
│ UNKNOWN_IDENTIFIER │ 47 │ 1 │ 2023-03-14 00:49:12 │ Missing columns: 'parts.table' 'table' while processing query: 'table = parts.table', required columns: 'table' 'parts.table' 'table' 'parts.table' │ [] │ 0 │
│ NO_ELEMENTS_IN_CONFIG │ 139 │ 2 │ 2023-03-14 00:42:11 │ Certificate file is not set. │ [] │ 0 │
└───────────────────────┴──────┴───────┴─────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴──────────────────┴────────┘As 10 consultas que mais usam CPU e memória
SELECT
type,
event_time,
initial_query_id,
formatReadableSize(memory_usage) AS memory,
`ProfileEvents.Values`[indexOf(`ProfileEvents.Names`, 'UserTimeMicroseconds')] AS userCPU,
`ProfileEvents.Values`[indexOf(`ProfileEvents.Names`, 'SystemTimeMicroseconds')] AS systemCPU,
normalizedQueryHash(query) AS normalized_query_hash
FROM system.query_log
ORDER BY memory_usage DESC
LIMIT 10Quanto espaço em disco minhas projeções usam
SELECT
name,
parent_name,
formatReadableSize(bytes_on_disk) AS bytes,
formatReadableSize(parent_bytes_on_disk) AS parent_bytes,
bytes_on_disk / parent_bytes_on_disk AS ratio
FROM system.projection_partsMostrar o armazenamento em disco, o número de partes, o número de linhas em system.parts e de marcas nos bancos de dados
SELECT
database,
table,
partition,
count() AS parts,
formatReadableSize(sum(bytes_on_disk)) AS bytes_on_disk,
formatReadableQuantity(sum(rows)) AS rows,
sum(marks) AS marks
FROM system.parts
WHERE (database != 'system') AND active
GROUP BY
database,
table,
partition
ORDER BY database ASCListe os detalhes das novas partes gravadas recentemente
Os detalhes incluem quando elas foram criadas, qual é o tamanho delas, quantas linhas elas têm e mais:
SELECT
modification_time,
rows,
formatReadableSize(bytes_on_disk),
*
FROM clusterAllReplicas(default, system.parts)
WHERE (database = 'default') AND active AND (level = 0)
ORDER BY modification_time DESC
LIMIT 100Consultas de monitoramento em todo o cluster
As consultas a seguir são úteis para monitorar clusters do ClickHouse. Elas usam clusterAllReplicas() para agregar dados de todos os nós.
Média de novas partes criadas por minuto e por segundo (na última hora)
WITH
PER_MINUTE AS
(
SELECT
toStartOfInterval(modification_time, toIntervalMinute(1)) AS t,
count() AS new_part_count
FROM
clusterAllReplicas(default, merge(system, '^parts'))
WHERE
(database = 'default') AND
(table = 'your_table') AND
(active = true) AND
(level = 0) AND
(modification_time >= (now() - toIntervalHour(1)))
GROUP BY
t
ORDER BY
t ASC
SETTINGS skip_unavailable_shards = 1
)
SELECT
AVG(new_part_count) AS new_parts_per_minute,
new_parts_per_minute / 60 AS new_parts_per_second
FROM
PER_MINUTESubstitua 'your_table' pelo nome da tabela que você quer monitorar.
Consultas com uso intensivo de CPU e memória (em todo o cluster)
SELECT
type,
event_time,
initial_query_id,
formatReadableSize(memory_usage) AS memory,
`ProfileEvents.Values`[indexOf(`ProfileEvents.Names`, 'UserTimeMicroseconds')] AS userCPU,
`ProfileEvents.Values`[indexOf(`ProfileEvents.Names`, 'SystemTimeMicroseconds')] AS systemCPU,
normalizedQueryHash(query) AS normalized_query_hash
FROM clusterAllReplicas(default, merge(system, '^query_log'))
ORDER BY memory_usage DESC
LIMIT 10Mesclagens em andamento com ETA
Esta consulta mostra as mesclagens em execução no momento no cluster, com tempo estimado para conclusão:
SELECT
hostName(),
database,
table,
round(elapsed, 0) AS elapsed_seconds,
round(progress, 4) AS progress_ratio,
formatReadableTimeDelta((elapsed / progress) - elapsed) AS estimated_time_remaining,
num_parts,
result_part_name
FROM clusterAllReplicas(default, merge(system, '^merges'))
ORDER BY (elapsed / progress) - elapsed ASCConsultas mais frequentes por hash normalizado
Encontre as consultas executadas com maior frequência (útil para identificar quais delas otimizar):
SELECT
normalizedQueryHash(query) AS query_hash,
count() AS execution_count,
any(query) AS example_query
FROM clusterAllReplicas(default, merge(system, '^query_log'))
WHERE event_date >= today() - 1
GROUP BY normalizedQueryHash(query)
ORDER BY execution_count DESC
LIMIT 20Contagem de erros por tipo de evento e data
Analise os erros na criação de partes em todo o cluster:
SELECT
event_date,
event_type,
table,
error,
COUNT() AS error_count
FROM clusterAllReplicas(default, merge(system, '^part_log'))
WHERE database = 'default'
GROUP BY
event_date,
event_type,
error,
table
ORDER BY
event_date DESC,
error_count DESCNúmero de tabelas por nó
Verifique como as tabelas se distribuem pelos nós do cluster:
SELECT
hostName() AS host,
count() AS table_count
FROM clusterAllReplicas('default', merge(system, '^tables'))
WHERE database = 'default'
GROUP BY hostName()
ORDER BY table_count DESCVerifique operações de async insert
Monitore a atividade de async insert:
SELECT
event_date,
count() AS total_count,
sum(if(query LIKE '%async%', 1, 0)) AS async_count,
sum(if(query LIKE '%INSERT%', 1, 0)) AS insert_count
FROM clusterAllReplicas(default, merge(system, '^query_log'))
WHERE event_date >= today() - 7
GROUP BY event_date
ORDER BY event_date DESCAnálise de partes e mesclagem
Partes ativas atualmente por tabela
Veja o número de partes ativas por tabela em todo o cluster:
SELECT
database,
table,
count() AS part_count,
formatReadableSize(sum(bytes_on_disk)) AS total_size
FROM clusterAllReplicas(default, system.parts)
WHERE active = 1 AND database = 'default'
GROUP BY database, table
ORDER BY part_count DESCPartições com excesso de partes
Encontre partições que possam ter excesso de partes (o que pode afetar o desempenho da consulta):
SELECT
database,
table,
partition,
count() AS part_count,
formatReadableSize(sum(bytes_on_disk)) AS total_size
FROM clusterAllReplicas(default, system.parts)
WHERE active = 1
GROUP BY database, table, partition
HAVING part_count > 100
ORDER BY part_count DESCPartes desanexadas
Verifique se há partes desanexadas que precisem ser investigadas:
SELECT
database,
table,
partition_id,
name,
reason,
count()
FROM clusterAllReplicas(default, system.detached_parts)
GROUP BY database, table, partition_id, name, reason
ORDER BY database, tableConsultas de informações do sistema
Uso de memória do cluster por nó
Monitore o consumo de memória em todos os nós:
SELECT
hostName() AS host,
formatReadableSize(max(memory_usage)) AS peak_memory,
formatReadableSize(avg(memory_usage)) AS avg_memory,
formatReadableSize(min(memory_usage)) AS min_memory
FROM clusterAllReplicas(default, merge(system, '^query_log'))
WHERE event_date >= today() - 1
GROUP BY hostName()
ORDER BY peak_memory DESCExecutar consultas no cluster
Confira quais consultas estão em execução no momento:
SELECT
hostName() AS host,
initial_user,
query_id,
elapsed,
read_rows,
formatReadableSize(memory_usage) AS memory_usage,
normalizedQueryHash(query) AS query_hash
FROM clusterAllReplicas(default, system.processes)
ORDER BY elapsed DESCConfigurações modificadas em relação aos valores padrão
Veja quais configurações foram alteradas em relação aos valores padrão:
SELECT
hostName() AS host,
name,
value
FROM clusterAllReplicas(default, system.settings)
WHERE changed = 1
ORDER BY hostName(), nameStatus da fila de replicação
Para tabelas replicadas, verifique a fila de replicação:
SELECT
hostName() AS host,
database,
table,
count() AS queue_size,
sum(if(is_currently_executing = 1, 1, 0)) AS executing_count
FROM clusterAllReplicas(default, system.replication_queue)
GROUP BY hostName(), database, table
HAVING queue_size > 0
ORDER BY queue_size DESC