Gerar dados aleatórios é útil ao testar novos casos de uso ou fazer benchmarking da sua implementação. O ClickHouse tem uma ampla gama de funções para gerar dados aleatórios que, em muitos casos, eliminam a necessidade de um gerador de dados externo.
Este guia apresenta vários exemplos de como gerar conjuntos de dados aleatórios no ClickHouse com diferentes requisitos de aleatoriedade.
Conjunto de dados simples com distribuição uniforme
Caso de uso: Gere rapidamente um conjunto de dados de eventos de usuários com timestamps aleatórios e tipos de evento.
CREATE TABLE user_events (
event_id UUID,
user_id UInt32,
event_type LowCardinality(String),
event_time DateTime
) ENGINE = MergeTree
ORDER BY event_time;
INSERT INTO user_events
SELECT
generateUUIDv4() AS event_id,
rand() % 10000 AS user_id,
arrayElement(['click','view','purchase'], toUInt32(rand()) % 3 + 1) AS event_type,
now() - INTERVAL rand() % 3600*24 SECOND AS event_time
FROM numbers(1000000);rand() % 10000: distribuição uniforme de 10 mil usuáriosarrayElement(...): seleciona aleatoriamente um de três tipos de evento- Timestamps distribuídos ao longo das últimas 24 horas
Distribuição exponencial
Caso de uso: Simular valores de compra em que a maioria é baixa, mas alguns são altos.
CREATE TABLE purchases (
dt DateTime,
customer_id UInt32,
total_spent Float32
) ENGINE = MergeTree
ORDER BY dt;
INSERT INTO purchases
SELECT
now() - INTERVAL randUniform(1,1_000_000) SECOND AS dt,
number AS customer_id,
15 + round(randExponential(1/10), 2) AS total_spent
FROM numbers(500000);- Timestamps uniformemente distribuídos em um período recente
randExponential(1/10)— a maioria dos totais fica próxima de 0, com 15 como valor mínimo ([ClickHouse][1], [ClickHouse][2], [Atlantic.Net][3], [GitHub][4])
Eventos distribuídos ao longo do tempo (Poisson)
Caso de uso: Simule chegadas de eventos que se concentram em um período específico (por exemplo, no horário de pico).
CREATE TABLE events (
dt DateTime,
event_type String
) ENGINE = MergeTree
ORDER BY dt;
INSERT INTO events
SELECT
toDateTime('2022-12-12 12:00:00')
- ((12 + randPoisson(12)) * 3600) AS dt,
'click' AS event_type
FROM numbers(200000);- Os eventos atingem o pico por volta do meio-dia, com desvio com distribuição de Poisson
Distribuição normal variável ao longo do tempo
Caso de uso: Emular métricas do sistema (por exemplo, uso de CPU) que variam ao longo do tempo.
CREATE TABLE IF NOT EXISTS cpu_metrics (
host String,
ts DateTime,
usage Float32
) ENGINE = MergeTree
ORDER BY (host, ts);
INSERT INTO cpu_metrics
SELECT
arrayJoin(['host1','host2','host3']) AS host,
now() - INTERVAL number SECOND AS ts,
greatest(0.0, least(100.0,
(50 + 30 * sin(toUInt32(number) % 86400 / 86400.0 * 2 * pi()))
+ randNormal(0, 10)
)) AS usage
FROM numbers(10000);usagesegue uma onda senoidal ao longo do dia + aleatoriedade- Valores limitados ao intervalo [0,100]
Dados categóricos e aninhados
Caso de uso: Crie perfis de usuário com interesses múltiplos.
CREATE TABLE user_profiles (
user_id UInt32,
interests Array(String),
scores Array(UInt8)
) ENGINE = MergeTree
ORDER BY user_id;
INSERT INTO user_profiles
SELECT
number AS user_id,
arrayShuffle(['sports','music','tech'])[1 + rand() % 3 : 1 + rand() % 3] AS interests,
[rand() % 100, rand() % 100, rand() % 100] AS scores
FROM numbers(20000);- Comprimento aleatório do array entre 1 e 3
- Três pontuações por usuário para cada interesse
Gerando tabelas aleatórias
A função generateRandomStructure é particularmente útil quando combinada com o mecanismo de tabela generateRandom para testes, benchmarking ou criação de dados simulados com schemas arbitrários.
Vamos começar vendo como é uma estrutura aleatória usando a função generateRandomStructure:
SELECT generateRandomStructure(5);Você pode ver algo assim:
c1 UInt32, c2 Array(String), c3 DateTime, c4 Nullable(Float64), c5 Map(String, Int16)Você também pode usar uma semente para obter sempre a mesma estrutura:
SELECT generateRandomStructure(3, 42);c1 String, c2 Array(Nullable(Int32)), c3 Tuple(UInt8, Date)Agora, vamos criar uma tabela propriamente dita e preenchê-la com dados aleatórios:
CREATE TABLE my_test_table
ENGINE = MergeTree
ORDER BY tuple()
AS SELECT *
FROM generateRandom(
'col1 UInt32, col2 String, col3 Float64, col4 DateTime',
1, -- semente para gerar os dados
10 -- número de valores aleatórios diferentes
)
LIMIT 100; -- 100 linhas
-- Etapa 2: consulte a nova tabela
SELECT * FROM my_test_table LIMIT 5;┌───────col1─┬─col2──────┬─────────────────────col3─┬────────────────col4─┐
│ 4107652264 │ &b!M-e;7 │ 1.0013455832230728e-158 │ 2059-08-14 19:03:26 │
│ 652895061 │ Dj7peUH{T │ -1.032074207667996e112 │ 2079-10-06 04:18:16 │
│ 2319105779 │ =D[ │ -2.066555415720528e88 │ 2015-04-26 11:44:13 │
│ 1835960063 │ _@}a │ -1.4998020545039013e110 │ 2063-03-03 20:36:55 │
│ 730412674 │ _}! │ -1.3578492992094465e-275 │ 2098-08-23 18:23:37 │
└────────────┴───────────┴──────────────────────────┴─────────────────────┘Vamos combinar as duas funções para criar uma tabela completamente aleatória. Primeiro, veja a estrutura que vamos obter:
SELECT generateRandomStructure(7, 123) AS structure FORMAT vertical;┌─structure──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ c1 Decimal64(7), c2 Enum16('c2V0' = -21744, 'c2V1' = 5380), c3 Int8, c4 UUID, c5 UUID, c6 FixedString(190), c7 Map(Enum16('c7V0' = -19581, 'c7V1' = -10024, 'c7V2' = 27615, 'c7V3' = -10177, 'c7V4' = -19644, 'c7V5' = 3554, 'c7V6' = 29073, 'c7V7' = 28800, 'c7V8' = -11512), Float64) │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘Agora, crie a tabela com essa estrutura e use a instrução DESCRIBE para ver o que foi criado:
CREATE TABLE fully_random_table
ENGINE = MergeTree
ORDER BY tuple()
AS SELECT *
FROM generateRandom(generateRandomStructure(7, 123), 1, 10)
LIMIT 1000;
DESCRIBE TABLE fully_random_table; ┌─name─┬─type─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
1. │ c1 │ Decimal(18, 7) │ │ │ │ │ │
2. │ c2 │ Enum16('c2V0' = -21744, 'c2V1' = 5380) │ │ │ │ │ │
3. │ c3 │ Int8 │ │ │ │ │ │
4. │ c4 │ UUID │ │ │ │ │ │
5. │ c5 │ UUID │ │ │ │ │ │
6. │ c6 │ FixedString(190) │ │ │ │ │ │
7. │ c7 │ Map(Enum16('c7V4' = -19644, 'c7V0' = -19581, 'c7V8' = -11512, 'c7V3' = -10177, 'c7V1' = -10024, 'c7V5' = 3554, 'c7V2' = 27615, 'c7V7' = 28800, 'c7V6' = 29073), Float64) │ │ │ │ │ │
└──────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘Inspecione a primeira linha para ver uma amostra dos dados gerados:
SELECT * FROM fully_random_table LIMIT 1 FORMAT vertical;Row 1:
──────
c1: 80416293882.257732 -- 80,42 bilhões
c2: c2V1
c3: -84
c4: 1a9429b3-fd8b-1d72-502f-c051aeb7018e
c5: 7407421a-031f-eb3b-8571-44ff279ddd36
c6: g̅b�&��rҵ���5C�\�|��H�>���l'V3��R�[��=3�G�LwVMR*s緾/2�J.���6#��(�h>�lە��L^�M�:�R�9%d�ž�zv��W����Y�S��_no��BP+��u��.0��UZ!x�@7:�nj%3�Λd�S�k>���w��|�&��~
c7: {'c7V8':-1.160941256852442}