22.10 以降、ClickHouse には、高い柔軟性でランダム データを生成する強力な機能が追加されました。
一様ランダム分布
ランド標準
ClickHouse には、すべてのデータベースやプログラミング言語が持つ標準的なランダム関数があります。この関数を使用して、randCanonical
[0, 1) 区間に均一に分布する擬似乱数値を返します。
SELECT randCanonical()
行制服
X…Yの範囲で乱数を生成します。区間は左閉、右開です。randUniform
関数を使用して、[X, Y)区間に均一に分布するfloat型の値を返します。
SELECT randUniform(5,10)
床
ランダムな整数を生成し、floor()
関数を使用して丸め、区間 [X, Y) の整数を返すことができます。
SELECT floor(randUniform(X, Y)) AS r
不均一なランダム分布
ClickHouse のバージョン 22.10 は、不均一 (および連続) 分布を生成できるランダム関数を提供します。
境界線通常
この関数は、最初の引数として平均を、2 番目の引数として分散を受け取り、平均値の周囲の浮動小数点数を出力します。randNormal(X, Y)
生成されたデータ分布を確認する例を示します。
SELECT
floor(randNormal(100, 5)) AS k,
count(*) AS c,
bar(c, 0, 50000, 100)
FROM numbers(100000) GROUP BY k ORDER BY k ASC
結果:
┌───k─┬────c─┬─bar(count(), 0, 50000, 100)─┐
│ 79 │ 1 │ │
│ 80 │ 5 │ │
│ 81 │ 8 │ │
│ 82 │ 17 │ │
│ 83 │ 35 │ │
│ 84 │ 80 │ ▏ │
│ 85 │ 130 │ ▎ │
│ 86 │ 208 │ ▍ │
│ 87 │ 362 │ ▋ │
│ 88 │ 559 │ █ │
│ 89 │ 868 │ █▋ │
│ 90 │ 1347 │ ██▋ │
│ 91 │ 1798 │ ███▌ │
│ 92 │ 2648 │ █████▎ │
│ 93 │ 3471 │ ██████▊ │
│ 94 │ 4365 │ ████████▋ │
│ 95 │ 5285 │ ██████████▌ │
│ 96 │ 6081 │ ████████████▏ │
│ 97 │ 7019 │ ██████████████ │
│ 98 │ 7599 │ ███████████████▏ │
│ 99 │ 8072 │ ████████████████▏ │
│ 100 │ 7909 │ ███████████████▋ │
│ 101 │ 7565 │ ███████████████▏ │
│ 102 │ 6994 │ █████████████▊ │
│ 103 │ 6240 │ ████████████▍ │
│ 104 │ 5384 │ ██████████▋ │
│ 105 │ 4411 │ ████████▋ │
│ 106 │ 3507 │ ███████ │
│ 107 │ 2595 │ █████▏ │
│ 108 │ 1890 │ ███▋ │
│ 109 │ 1337 │ ██▋ │
│ 110 │ 890 │ █▋ │
│ 111 │ 538 │ █ │
│ 112 │ 336 │ ▋ │
│ 113 │ 221 │ ▍ │
│ 114 │ 103 │ ▏ │
│ 115 │ 63 │ ▏ │
│ 116 │ 24 │ │
│ 117 │ 26 │ │
│ 118 │ 4 │ │
│ 119 │ 4 │ │
│ 121 │ 1 │ │
└─────┴──────┴─────────────────────────────┘
ここでは 10W の乱数が生成されrandNormal()
、四捨五入されて各数値の出現数がカウントされます。ほとんどの場合、関数は指定された平均に近い乱数を生成することがわかります。これはまさに正規分布の仕組みです。正規分布は、独立変数 (集約システムにおけるエラーの種類など) を合計すると発生します。
ラン二項
二項分布は、一連の「はい」または「いいえ」の質問における成功確率をモデル化するためによく使用されます。コイントスをモデル化する場合、表の合計数をモデル化するためによく使用されます。正規分布のように視覚化します。
SELECT
floor(randBinomial(100, 0.85)) AS k,
bar(count(*), 0, 50000, 100) AS b1
FROM numbers(100000)
GROUP BY k
ORDER BY k ASC
結果:
┌──k─┬─b1──────────────────────┐
│ 68 │ │
│ 70 │ │
│ 71 │ │
│ 72 │ │
│ 73 │ ▏ │
│ 74 │ ▎ │
│ 75 │ ▋ │
│ 76 │ █▏ │
│ 77 │ █▊ │
│ 78 │ ███▍ │
│ 79 │ █████▎ │
│ 80 │ ███████▊ │
│ 81 │ ███████████▏ │
│ 82 │ ███████████████ │
│ 83 │ ██████████████████▏ │
│ 84 │ █████████████████████ │
│ 85 │ ██████████████████████▏ │
│ 86 │ █████████████████████▋ │
│ 87 │ ███████████████████▋ │
│ 88 │ ████████████████▋ │
│ 89 │ ████████████▋ │
│ 90 │ █████████ │
│ 91 │ █████▍ │
│ 92 │ ██▊ │
│ 93 │ █▍ │
│ 94 │ ▌ │
│ 95 │ ▏ │
│ 96 │ │
│ 97 │ │
│ 98 │ │
└────┴─────────────────────────┘
rand負の二項
負の二項分布。ただし、シーケンス内で指定された数の裏を得るために必要なコイン投げの回数など、特定の二値イベントを達成するための試行回数をモデル化するためのものです。
SELECT
floor(randNegativeBinomial(100, 0.85)) AS k,
bar(count(*), 0, 50000, 100) AS b1
FROM numbers(100000)
GROUP BY k
ORDER BY k ASC
結果:
┌──k─┬─b1─────────────────┐
│ 3 │ │
│ 4 │ │
│ 5 │ │
│ 6 │ ▎ │
│ 7 │ ▋ │
│ 8 │ █▍ │
│ 9 │ ██▋ │
│ 10 │ ████▎ │
│ 11 │ ██████▎ │
│ 12 │ ████████▊ │
│ 13 │ ███████████▌ │
│ 14 │ █████████████▊ │
│ 15 │ ████████████████▏ │
│ 16 │ █████████████████ │
│ 17 │ █████████████████▋ │
│ 18 │ █████████████████▍ │
│ 19 │ ███████████████▊ │
│ 20 │ ██████████████▏ │
│ 21 │ ████████████▏ │
│ 22 │ ██████████▎ │
│ 23 │ ███████▋ │
│ 24 │ ██████▎ │
│ 25 │ ████▍ │
│ 26 │ ███▎ │
│ 27 │ ██▍ │
│ 28 │ █▋ │
│ 29 │ ▊ │
│ 30 │ ▋ │
│ 31 │ ▍ │
│ 32 │ ▏ │
│ 33 │ ▏ │
│ 34 │ │
│ 35 │ │
│ 36 │ │
│ 37 │ │
│ 38 │ │
│ 39 │ │
│ 40 │ │
│ 41 │ │
│ 43 │ │
└────┴────────────────────┘
randLogNormal
対数正規分布。失敗率、ゲーム時間、収入分布などの自然現象のモデル化によく役立ちます。
SELECT
floor(randLogNormal(1 / 100, 0.75)) AS k,
bar(count(*), 0, 50000, 10) AS b1
FROM numbers(100000)
GROUP BY k
ORDER BY k ASC
結果:
┌──k─┬─b1─────────┐
│ 0 │ █████████▊ │
│ 1 │ ██████▍ │
│ 2 │ ██▏ │
│ 3 │ ▋ │
│ 4 │ ▎ │
│ 5 │ ▏ │
│ 6 │ │
│ 7 │ │
│ 8 │ │
│ 9 │ │
│ 10 │ │
│ 11 │ │
│ 12 │ │
│ 13 │ │
│ 14 │ │
│ 15 │ │
│ 16 │ │
│ 17 │ │
│ 18 │ │
│ 22 │ │
│ 23 │ │
│ 25 │ │
│ 31 │ │
│ 34 │ │
└────┴────────────┘
ランド指数
指数分布。顧客の電話の継続時間または売上総額をモデル化するために使用できます。
SELECT
floor(randExponential(1 / 2)) AS k,
bar(count(*), 0, 50000, 10) AS b1
FROM numbers(100000)
GROUP BY k
ORDER BY k ASC
結果:
┌──k─┬─b1───────┐
│ 0 │ ███████▋ │
│ 1 │ ████▋ │
│ 2 │ ██▊ │
│ 3 │ █▋ │
│ 4 │ █ │
│ 5 │ ▋ │
│ 6 │ ▍ │
│ 7 │ ▏ │
│ 8 │ ▏ │
│ 9 │ │
│ 10 │ │
│ 11 │ │
│ 12 │ │
│ 13 │ │
│ 14 │ │
│ 15 │ │
│ 16 │ │
│ 17 │ │
│ 18 │ │
│ 19 │ │
│ 20 │ │
│ 21 │ │
│ 22 │ │
│ 26 │ │
└────┴──────────┘
ランドカイ二乗
カイ二乗分布、k 個の独立した標準正規確率変数の二乗和の分布。これは、統計的な仮定、特にデータセットが分布と一致するかどうかをテストする場合に主に役立ちます。
SELECT
floor(randChiSquared(10)) AS k,
bar(count(*), 0, 10000, 10) AS b1
FROM numbers(100000)
GROUP BY k
ORDER BY k ASC
結果:
┌──k─┬─b1─────────┐
│ 0 │ │
│ 1 │ ▎ │
│ 2 │ █▍ │
│ 3 │ ███▍ │
│ 4 │ █████▋ │
│ 5 │ ███████▋ │
│ 6 │ ████████▊ │
│ 7 │ █████████▌ │
│ 8 │ █████████▋ │
│ 9 │ █████████ │
│ 10 │ ████████▏ │
│ 11 │ ███████▎ │
│ 12 │ ██████▏ │
│ 13 │ ████▊ │
│ 14 │ ████ │
│ 15 │ ███▏ │
│ 16 │ ██▌ │
│ 17 │ █▊ │
│ 18 │ █▍ │
│ 19 │ █ │
│ 20 │ ▋ │
│ 21 │ ▌ │
│ 22 │ ▍ │
│ 23 │ ▎ │
│ 24 │ ▏ │
│ 25 │ ▏ │
│ 26 │ ▏ │
│ 27 │ │
│ 28 │ │
│ 29 │ │
│ 30 │ │
│ 31 │ │
│ 32 │ │
│ 33 │ │
│ 34 │ │
│ 35 │ │
│ 36 │ │
│ 37 │ │
│ 38 │ │
│ 39 │ │
└────┴────────────┘
ランド学生T
学生の T 分布。
SELECT
floor(randStudentT(4.5)) AS k,
bar(count(*), 0, 10000, 10) AS b1
FROM numbers(100000)
GROUP BY k
ORDER BY k ASC
結果:
┌───k─┬─b1─────────┐
│ -18 │ │
│ -17 │ │
│ -15 │ │
│ -14 │ │
│ -12 │ │
│ -11 │ │
│ -10 │ │
│ -9 │ │
│ -8 │ │
│ -7 │ │
│ -6 │ ▏ │
│ -5 │ ▎ │
│ -4 │ █▏ │
│ -3 │ ███▋ │
│ -2 │ ██████████ │
│ -1 │ ██████████ │
│ 0 │ ██████████ │
│ 1 │ ██████████ │
│ 2 │ ███▋ │
│ 3 │ █▏ │
│ 4 │ ▎ │
│ 5 │ ▏ │
│ 6 │ │
│ 7 │ │
│ 8 │ │
│ 9 │ │
│ 10 │ │
│ 11 │ │
│ 12 │ │
│ 13 │ │
│ 14 │ │
│ 17 │ │
│ 20 │ │
└─────┴────────────┘
ランドフィッシャーF
F 分布は主に、2 つの母集団の変動が分布の観点から同じかどうかを評価する統計検定で使用されます。
SELECT
floor(randFisherF(3, 20)) AS k,
bar(count(*), 0, 10000, 10) AS b1
FROM numbers(100000)
GROUP BY k
ORDER BY k ASC
結果:
┌──k─┬─b1─────────┐
│ 0 │ ██████████ │
│ 1 │ ██████████ │
│ 2 │ █████████ │
│ 3 │ ███▏ │
│ 4 │ █▎ │
│ 5 │ ▍ │
│ 6 │ ▏ │
│ 7 │ │
│ 8 │ │
│ 9 │ │
│ 10 │ │
│ 11 │ │
│ 12 │ │
│ 13 │ │
│ 21 │ │
└────┴────────────┘
エッジポアソン
ポアソン分布を使用すると、時間の経過に伴う特定のイベント (サッカーの試合のゴールなど) やイベント間の間隔 (ログ メッセージなど) をモデル化できます。
SELECT
floor(randPoisson(10)) AS k,
bar(count(*), 0, 15000, 10) AS b1
FROM numbers(100000)
GROUP BY k
ORDER BY k ASC
結果:
┌──k─┬─b1────────┐
│ 0 │ │
│ 1 │ │
│ 2 │ ▏ │
│ 3 │ ▌ │
│ 4 │ █▏ │
│ 5 │ ██▌ │
│ 6 │ ████▏ │
│ 7 │ ██████ │
│ 8 │ ███████▌ │
│ 9 │ ████████▎ │
│ 10 │ ████████▍ │
│ 11 │ ███████▌ │
│ 12 │ ██████▎ │
│ 13 │ ████▋ │
│ 14 │ ███▌ │
│ 15 │ ██▎ │
│ 16 │ █▍ │
│ 17 │ ▋ │
│ 18 │ ▍ │
│ 19 │ ▏ │
│ 20 │ │
│ 21 │ │
│ 22 │ │
│ 23 │ │
│ 24 │ │
│ 25 │ │
└────┴───────────┘
エッジベルヌーイ
特定の操作の失敗と成功をモデル化するために使用できる薄いベルヌーイ分布。
SELECT
floor(randBernoulli(0.75)) AS k,
count(*) AS c
FROM numbers(100000)
GROUP BY k
ORDER BY k ASC
結果:
┌─k─┬─────c─┐
│ 0 │ 24976 │
│ 1 │ 75024 │
└───┴───────┘
ランダムなデータを生成する
要件に従って任意のランダム ジェネレーターを使用し、テーブルにテスト データを入力できます。purchases
製品の売上を表すテーブルにデータを入力してみましょう。
CREATE TABLE purchases
(
`dt` DateTime,
`customer_id` UInt32,
`total_spent` Float32
)
ENGINE = MergeTree
ORDER BY dt
この関数を使用してrandExponential()
列のデータを生成し、total_spent
顧客の売上の分布をモデル化します。
INSERT INTO purchases SELECT
now() - randUniform(1, 1000000.),
number,
15 + round(randExponential(1 / 10), 2)
FROM numbers(1000000)
顧客 ID のシーケンス番号と均一なランダムな時間オフセットを使用してデータを伝播します。total_spent
の値が指数関数的に分布し、値 15 に向かう傾向があることがわかります($15.00
使用できる最低値と仮定します)。
SELECT
floor(total_spent) AS s,
count(*) AS n,
bar(n, 0, 350000, 50)
FROM purchases
GROUP BY s
ORDER BY s ASC
結果:
┌───s─┬─────n─┬─bar(count(), 0, 350000, 50)─┐
│ 15 │ 94520 │ █████████████▌ │
│ 16 │ 86711 │ ████████████▍ │
│ 17 │ 77290 │ ███████████ │
│ 18 │ 70446 │ ██████████ │
│ 19 │ 63580 │ █████████ │
│ 20 │ 57635 │ ████████▏ │
│ 21 │ 52518 │ ███████▌ │
│ 22 │ 47777 │ ██████▋ │
│ 23 │ 42808 │ ██████ │
│ 24 │ 38729 │ █████▌ │
│ 25 │ 34912 │ ████▊ │
│ 26 │ 31604 │ ████▌ │
│ 27 │ 28542 │ ████ │
│ 28 │ 26128 │ ███▋ │
│ 29 │ 23520 │ ███▎ │
│ 30 │ 21383 │ ███ │
│ 31 │ 19207 │ ██▋ │
│ 32 │ 17156 │ ██▍ │
│ 33 │ 15656 │ ██▏ │
│ 34 │ 14171 │ ██ │
│ 35 │ 12855 │ █▋ │
│ 36 │ 11772 │ █▋ │
│ 37 │ 10481 │ █▍ │
│ 38 │ 9542 │ █▎ │
│ 39 │ 8538 │ █▏ │
│ 40 │ 7854 │ █ │
│ 41 │ 7064 │ █ │
│ 42 │ 6467 │ ▊ │
│ 43 │ 5901 │ ▋ │
│ 44 │ 5418 │ ▋ │
│ 45 │ 4838 │ ▋ │
│ 46 │ 4198 │ ▌ │
│ 47 │ 3760 │ ▌ │
│ 48 │ 3542 │ ▌ │
│ 49 │ 3188 │ ▍ │
│ 50 │ 2858 │ ▍ │
│ 51 │ 2631 │ ▍ │
│ 52 │ 2347 │ ▎ │
│ 53 │ 2175 │ ▎ │
│ 54 │ 1896 │ ▎ │
│ 55 │ 1723 │ ▏ │
│ 56 │ 1611 │ ▏ │
│ 57 │ 1408 │ ▏ │
│ 58 │ 1253 │ ▏ │
│ 59 │ 1246 │ ▏ │
│ 60 │ 1089 │ ▏ │
│ 61 │ 976 │ ▏ │
│ 62 │ 859 │ │
│ 63 │ 785 │ │
│ 64 │ 741 │ │
│ 65 │ 666 │ │
│ 66 │ 553 │ │
│ 67 │ 524 │ │
│ 68 │ 479 │ │
│ 69 │ 394 │ │
│ 70 │ 386 │ │
│ 71 │ 356 │ │
│ 72 │ 305 │ │
│ 73 │ 307 │ │
│ 74 │ 244 │ │
│ 75 │ 233 │ │
│ 76 │ 214 │ │
│ 77 │ 189 │ │
│ 78 │ 160 │ │
│ 79 │ 154 │ │
│ 80 │ 136 │ │
│ 81 │ 131 │ │
│ 82 │ 118 │ │
│ 83 │ 121 │ │
│ 84 │ 110 │ │
│ 85 │ 90 │ │
│ 86 │ 67 │ │
│ 87 │ 76 │ │
│ 88 │ 62 │ │
│ 89 │ 73 │ │
│ 90 │ 60 │ │
│ 91 │ 52 │ │
│ 92 │ 45 │ │
│ 93 │ 41 │ │
│ 94 │ 44 │ │
│ 95 │ 23 │ │
│ 96 │ 22 │ │
│ 97 │ 24 │ │
│ 98 │ 14 │ │
│ 99 │ 16 │ │
│ 100 │ 16 │ │
│ 101 │ 28 │ │
│ 102 │ 16 │ │
│ 103 │ 16 │ │
│ 104 │ 10 │ │
│ 105 │ 17 │ │
│ 106 │ 10 │ │
│ 107 │ 8 │ │
│ 108 │ 5 │ │
│ 109 │ 12 │ │
│ 110 │ 6 │ │
│ 111 │ 3 │ │
│ 112 │ 5 │ │
│ 113 │ 3 │ │
│ 114 │ 4 │ │
│ 115 │ 4 │ │
│ 116 │ 6 │ │
│ 117 │ 4 │ │
│ 118 │ 2 │ │
│ 119 │ 3 │ │
│ 120 │ 3 │ │
│ 121 │ 2 │ │
│ 122 │ 1 │ │
│ 123 │ 2 │ │
│ 124 │ 1 │ │
│ 125 │ 1 │ │
│ 128 │ 2 │ │
│ 129 │ 2 │ │
│ 130 │ 1 │ │
│ 131 │ 2 │ │
│ 132 │ 1 │ │
│ 135 │ 1 │ │
│ 137 │ 1 │ │
│ 141 │ 1 │ │
│ 154 │ 1 │ │
│ 155 │ 2 │ │
└─────┴───────┴─────────────────────────────┘
指数分布を使用して総支払額を徐々に減らす方法に注目してください。正規分布 (randNormal()
関数を使用) またはその他の分布を使用して、さまざまなピークと形状を取得できます。
時間分布データの生成
前の例ではランダム分布を使用して値をモデル化しましたが、時間をモデル化することもできます。クライアント イベントを次のテーブルに収集するとします。
CREATE TABLE events
(
`dt` DateTime,
`event` String
)
ENGINE = MergeTree
ORDER BY dt
実際、1 日の特定の時間帯にはさらに多くのイベントが発生する場合があります。ポアソン分布は、時間の経過に伴う一連の独立したイベントをモデル化する良い方法です。時間分布をシミュレートするには、生成されたランダム値を時間列に追加するだけです。
INSERT INTO events SELECT
toDateTime('2022-12-12 12:00:00') - (((12 + randPoisson(12)) * 60) * 60),
'click'
FROM numbers(100000)
ここでは、正午をイベントのピーク時間 (この例では 12:00) として、約 24 時間にわたる 100,000 のクリック イベントを挿入します。
SELECT
toStartOfHour(dt) AS hour,
count(*) AS c,
bar(c, 0, 15000, 50)
FROM events
GROUP BY hour
ORDER BY hour ASC
結果:
┌────────────────hour─┬─────c─┬─bar(count(), 0, 15000, 50)──────────────┐
│ 2022-12-10 16:00:00 │ 1 │ │
│ 2022-12-10 20:00:00 │ 3 │ │
│ 2022-12-10 21:00:00 │ 13 │ │
│ 2022-12-10 22:00:00 │ 19 │ │
│ 2022-12-10 23:00:00 │ 42 │ ▏ │
│ 2022-12-11 00:00:00 │ 71 │ ▏ │
│ 2022-12-11 01:00:00 │ 183 │ ▌ │
│ 2022-12-11 02:00:00 │ 289 │ ▊ │
│ 2022-12-11 03:00:00 │ 543 │ █▋ │
│ 2022-12-11 04:00:00 │ 971 │ ███▏ │
│ 2022-12-11 05:00:00 │ 1606 │ █████▎ │
│ 2022-12-11 06:00:00 │ 2662 │ ████████▋ │
│ 2022-12-11 07:00:00 │ 3830 │ ████████████▋ │
│ 2022-12-11 08:00:00 │ 5342 │ █████████████████▋ │
│ 2022-12-11 09:00:00 │ 7214 │ ████████████████████████ │
│ 2022-12-11 10:00:00 │ 8896 │ █████████████████████████████▋ │
│ 2022-12-11 11:00:00 │ 10563 │ ███████████████████████████████████▏ │
│ 2022-12-11 12:00:00 │ 11502 │ ██████████████████████████████████████▎ │
│ 2022-12-11 13:00:00 │ 11532 │ ██████████████████████████████████████▍ │
│ 2022-12-11 14:00:00 │ 10581 │ ███████████████████████████████████▎ │
│ 2022-12-11 15:00:00 │ 8729 │ █████████████████████████████ │
│ 2022-12-11 16:00:00 │ 6618 │ ██████████████████████ │
│ 2022-12-11 17:00:00 │ 4304 │ ██████████████▎ │
│ 2022-12-11 18:00:00 │ 2536 │ ████████▍ │
│ 2022-12-11 19:00:00 │ 1220 │ ████ │
│ 2022-12-11 20:00:00 │ 516 │ █▋ │
│ 2022-12-11 21:00:00 │ 165 │ ▌ │
│ 2022-12-11 22:00:00 │ 41 │ ▏ │
│ 2022-12-11 23:00:00 │ 7 │ │
│ 2022-12-12 00:00:00 │ 1 │ │
└─────────────────────┴───────┴─────────────────────────────────────────┘
この場合、値を生成する代わりに、ランダム関数を使用して、計算された時点に新しいレコードを挿入します。
時間依存の値を生成する
前の例に基づいて、分布を使用して時間依存の値を生成できます。たとえば、CPU 使用率や RAM 使用率などのハードウェア メトリック収集を次の表にシミュレートするとします。
CREATE TABLE metrics
(
`name` String,
`dt` DateTime,
`val` Float32
)
ENGINE = MergeTree
ORDER BY (name, dt)
実際には、CPU が完全に負荷がかかるピーク時間と、負荷が低い時間帯が必ず発生します。これをモデル化するには、目的の分布のランダム関数を使用して、メトリックと時点の値を計算します。
INSERT INTO metrics SELECT
'cpu',
t + ((60 * 60) * randCanonical()) AS t,
round(v * (0.95 + (randCanonical() / 20)), 2) AS v
FROM
(
SELECT
toDateTime('2022-12-12 12:00:00') - toIntervalHour(k) AS t,
round((100 * c) / m, 2) AS v
FROM
(
SELECT
k,
c,
max(c) OVER () AS m
FROM
(
SELECT
floor(randBinomial(24, 0.5) - 12) AS k,
count(*) AS c
FROM numbers(1000)
GROUP BY k
ORDER BY k ASC
)
)
) AS a
INNER JOIN numbers(1000000) AS b ON 1 = 1
ここでは、二項分布から 1K の乱数値を生成し、生成された各数値とそれに関連する数を取得します。次に、ウィンドウ最大値関数を使用してこれらの値の最大値を計算し、それを列として各結果に追加します。最後に、外側のクエリで、そのカウントを最大値で割った値に基づいてメトリックを生成し、0...100
考えられる CPU 負荷の数値に対応する範囲内のランダムな値を取得します。また、数値にノイズを追加しtime
、val
を使用しrandCanonical()
、数値テーブルと結合して 1m メトリック イベントを生成します。
SELECT
toStartOfHour(dt) AS h,
round(avg(val), 2) AS v,
bar(v, 0, 100)
FROM metrics
GROUP BY h
ORDER BY h ASC
結果:
┌───────────────────h─┬─────v─┬─bar(round(avg(val), 2), 0, 100)────────────────────────────────────────────────┐
│ 2022-12-12 04:00:00 │ 1.78 │ █▍ │
│ 2022-12-12 05:00:00 │ 0.59 │ ▍ │
│ 2022-12-12 06:00:00 │ 5.35 │ ████▎ │
│ 2022-12-12 07:00:00 │ 10.11 │ ████████ │
│ 2022-12-12 08:00:00 │ 32.11 │ █████████████████████████▋ │
│ 2022-12-12 09:00:00 │ 50.53 │ ████████████████████████████████████████▍ │
│ 2022-12-12 10:00:00 │ 65.39 │ ████████████████████████████████████████████████████▎ │
│ 2022-12-12 11:00:00 │ 93.34 │ ██████████████████████████████████████████████████████████████████████████▋ │
│ 2022-12-12 12:00:00 │ 97.5 │ ██████████████████████████████████████████████████████████████████████████████ │
│ 2022-12-12 13:00:00 │ 87.98 │ ██████████████████████████████████████████████████████████████████████▍ │
│ 2022-12-12 14:00:00 │ 58.86 │ ███████████████████████████████████████████████ │
│ 2022-12-12 15:00:00 │ 51.13 │ ████████████████████████████████████████▉ │
│ 2022-12-12 16:00:00 │ 23.18 │ ██████████████████▌ │
│ 2022-12-12 17:00:00 │ 13.07 │ ██████████▍ │
│ 2022-12-12 18:00:00 │ 2.97 │ ██▍ │
│ 2022-12-12 21:00:00 │ 0.59 │ ▍ │
└─────────────────────┴───────┴────────────────────────────────────────────────────────────────────────────────┘
多峰性分布を生成する
これまでの例はすべて、単一のピークまたは最適値を持つデータを生成しました。マルチモーダル分布には複数のピークが含まれており、複数の季節的な売上ピークなど、現実世界のイベントをシミュレートするために使用できます。これを行うには、生成された値を特定のシーケンス番号でグループ化し、生成されたデータを繰り返します。
SELECT
floor(randBinomial(24, 0.75)) AS k,
count(*) AS c,
number % 3 AS ord,
bar(c, 0, 10000)
FROM numbers(100000)
GROUP BY
k,
ord
ORDER BY
ord ASC,
k ASC
これにより、二項分布データが 3 回繰り返されます。
┌──k─┬────c─┬─ord─┬─bar(count(), 0, 10000)─────────────────────────────┐
│ 7 │ 1 │ 0 │ │
│ 8 │ 1 │ 0 │ │
│ 9 │ 5 │ 0 │ │
│ 10 │ 12 │ 0 │ │
│ 11 │ 44 │ 0 │ ▎ │
│ 12 │ 162 │ 0 │ █▎ │
│ 13 │ 440 │ 0 │ ███▌ │
│ 14 │ 1059 │ 0 │ ████████▍ │
│ 15 │ 2282 │ 0 │ ██████████████████▎ │
│ 16 │ 3802 │ 0 │ ██████████████████████████████▍ │
│ 17 │ 5380 │ 0 │ ███████████████████████████████████████████ │
│ 18 │ 6126 │ 0 │ █████████████████████████████████████████████████ │
│ 19 │ 5793 │ 0 │ ██████████████████████████████████████████████▎ │
│ 20 │ 4372 │ 0 │ ██████████████████████████████████▊ │
│ 21 │ 2542 │ 0 │ ████████████████████▎ │
│ 22 │ 1002 │ 0 │ ████████ │
│ 23 │ 277 │ 0 │ ██▏ │
│ 24 │ 34 │ 0 │ ▎ │
│ 8 │ 1 │ 1 │ │
│ 9 │ 2 │ 1 │ │
│ 10 │ 10 │ 1 │ │
│ 11 │ 39 │ 1 │ ▎ │
│ 12 │ 153 │ 1 │ █▏ │
│ 13 │ 435 │ 1 │ ███▍ │
│ 14 │ 1120 │ 1 │ ████████▊ │
│ 15 │ 2220 │ 1 │ █████████████████▋ │
│ 16 │ 3768 │ 1 │ ██████████████████████████████▏ │
│ 17 │ 5352 │ 1 │ ██████████████████████████████████████████▋ │
│ 18 │ 6080 │ 1 │ ████████████████████████████████████████████████▋ │
│ 19 │ 5988 │ 1 │ ███████████████████████████████████████████████▊ │
│ 20 │ 4318 │ 1 │ ██████████████████████████████████▌ │
│ 21 │ 2537 │ 1 │ ████████████████████▎ │
│ 22 │ 994 │ 1 │ ███████▊ │
│ 23 │ 285 │ 1 │ ██▎ │
│ 24 │ 31 │ 1 │ ▏ │
│ 8 │ 1 │ 2 │ │
│ 9 │ 1 │ 2 │ │
│ 10 │ 17 │ 2 │ ▏ │
│ 11 │ 52 │ 2 │ ▍ │
│ 12 │ 211 │ 2 │ █▋ │
│ 13 │ 474 │ 2 │ ███▋ │
│ 14 │ 1110 │ 2 │ ████████▊ │
│ 15 │ 2242 │ 2 │ █████████████████▊ │
│ 16 │ 3741 │ 2 │ █████████████████████████████▊ │
│ 17 │ 5306 │ 2 │ ██████████████████████████████████████████▍ │
│ 18 │ 6256 │ 2 │ ██████████████████████████████████████████████████ │
│ 19 │ 5779 │ 2 │ ██████████████████████████████████████████████▏ │
│ 20 │ 4360 │ 2 │ ██████████████████████████████████▊ │
│ 21 │ 2461 │ 2 │ ███████████████████▋ │
│ 22 │ 1035 │ 2 │ ████████▎ │
│ 23 │ 255 │ 2 │ ██ │
│ 24 │ 32 │ 2 │ ▎ │
└────┴──────┴─────┴────────────────────────────────────────────────────┘
アナログバイナリ状態
この関数は、たとえば、使用するケースの 90% を取得したい場合、指定された確率に基づいて、またはをrandBernoulli()
返します。0
1
1
SELECT randBernoulli(0.9)
これは、失敗したトランザクションや成功したトランザクションなどのバイナリ状態のデータを生成するときに役立ちます。
SELECT
If(randBernoulli(0.95), 'success', 'failure') AS status,
count(*) AS c
FROM numbers(1000)
GROUP BY status
結果:
┌─status──┬───c─┐
│ failure │ 52 │
│ success │ 948 │
└─────────┴─────┘
success
ここでは、状態の 95% を生成し、 は 5% だけを生成しますfailure
。
enum のランダムな値を生成する
配列とランダム関数を組み合わせてサブセットから値を取得し、それを使用して ENUM 列に値を設定できます。
SELECT
['200', '404', '502', '403'][toInt32(randBinomial(4, 0.1)) + 1] AS http_code,
count(*) AS c
FROM numbers(1000)
GROUP BY http_code
結果:
┌─http_code─┬───c─┐
│ 403 │ 3 │
│ 502 │ 49 │
│ 200 │ 685 │
│ 404 │ 263 │
└───────────┴─────┘
ここでは、二項分布を使用して、4 つの考えられる HTTP 応答コードのいずれかを含むリクエストの数を取得します。通常は 200 を超えるエラーが予想されるため、そのようにモデル化します。
ランダムな文字列を生成する
ClickHouse では、 および 関数を使用してランダムな文字列を生成することもrandomString()
できrandomStringUTF8()
ますrandomPrintableASCII()
。すべての関数は文字列の長さをパラメータとして受け入れます。ランダムな文字列を含むデータセットを作成するには、文字列生成とランダム関数を組み合わせて、任意の長さの文字列を取得します。以下では、このメソッドを使用して、長さ 5 ~ 25 シンボルの人間が判読できる文字であるランダムな文字列を 10 個生成します。
SELECT
randomPrintableASCII(randUniform(5, 25)) AS s,
length(s) AS length
FROM numbers(10)
結果:
┌─s──────────────────┬─length─┐
│ 3{
{mc │ 5 │
│ F7g S)a:i*q/)_'g: │ 17 │
│ :ccV^f4{vpwgr'Qq#M │ 18 │
│ G=G': │ 5 │
│ }6o,0yMDo*x`!BqnY$ │ 18 │
│ \7Y5]" │ 6 │
│ kkS3q?fE+%4hD6ItJA │ 18 │
│ .<S<+n&eyu59=*6g │ 16 │
│ [!cBR │ 5 │
│ +,hD}`7#B+HYv$ │ 14 │
└────────────────────┴────────┘
ノイズの多いデータを生成する
現実の世界では、データには常にエラーが含まれます。これは、関数を使用して ClickHouse でfuzzBits()
シミュレートできます。この関数は、指定された確率でビットをランダムにシフトすることにより、ユーザー指定の有効な値に基づいてエラー データを生成します。文字列フィールド値にエラーを追加するとします。以下は、初期値に基づいてランダムにエラーを生成します。
SELECT fuzzBits('Good string', 0.01)
FROM numbers(10)
結果:
┌─fuzzBits('Good string', 0.01)─┐
│ Good string │
│ Good string │
│ Eood string │
│ Good string │
│ Good string │
│ Good strkng │
│ Good string │
│ G/od string │
│ Good!strino │
│ Good string │
└───────────────────────────────┘
生成されるエラーの数は関数に渡す値の長さに依存するため、確率を必ず調整してください。エラーの可能性を低くするには、より低い値を使用します。
SELECT
IF(fuzzBits('Good string', 0.001) = 'Good string', 1, 0) AS has_errors,
count(*)
FROM numbers(1000)
GROUP BY has_errors
結果:
┌─has_errors─┬─count()─┐
│ 0 │ 279 │
│ 1 │ 721 │
└────────────┴─────────┘
ここでは、確率 0.001 を使用して、約 25% の誤った値を取得します。
実際のデータセットの生成
要約すると、正午にピークを迎える、1 日以内の現実世界に近い分布で 30 日間のクリックストリームをシミュレートしてみましょう。これには正規分布を使用します。各イベントには、ベルヌーイ関数を使用して分散される2 つの可能な状態success
ORもあります。fail
私たちのテーブル:
CREATE TABLE click_events
(
`dt` DateTime,
`event` String,
`status` Enum8('success' = 1, 'fail' = 2)
)
ENGINE = MergeTree
ORDER BY dt
このテーブルに 1,000 万個のイベントを入力してみましょう。
INSERT INTO click_events SELECT
(parseDateTimeBestEffortOrNull('12:00') - toIntervalHour(randNormal(0, 3))) - toIntervalDay(number % 30),
'Click',
['fail', 'success'][randBernoulli(0.9) + 1]
FROM numbers(10000000)
90% の成功確率を使用したため、 randBernoulli()
10 のうちsuccess
9 列目の値が得られます。status
私たちはイベントのディストリビューションを生成することに慣れていますrandNormal()
。次のクエリを使用して、このデータを視覚化してみましょう。
SELECT
dt,
count(*) AS c,
bar(c, 0, 100000)
FROM click_events
GROUP BY dt
ORDER BY dt ASC
結果:
┌──────────────────dt─┬─────c─┬─bar(count(), 0, 100000)────────────────────────────────────────────────┐
│ 1999-12-02 22:00:00 │ 1 │ │
│ 1999-12-02 23:00:00 │ 1 │ │
│ 1999-12-03 00:00:00 │ 6 │ │
│ 1999-12-03 01:00:00 │ 27 │ │
│ 1999-12-03 02:00:00 │ 110 │ │
│ 1999-12-03 03:00:00 │ 321 │ ▎ │
│ 1999-12-03 04:00:00 │ 866 │ ▋ │
│ 1999-12-03 05:00:00 │ 1965 │ █▌ │
│ 1999-12-03 06:00:00 │ 4417 │ ███▌ │
│ 1999-12-03 07:00:00 │ 8372 │ ██████▋ │
│ 1999-12-03 08:00:00 │ 14392 │ ███████████▌ │
│ 1999-12-03 09:00:00 │ 22358 │ █████████████████▉ │
│ 1999-12-03 10:00:00 │ 31178 │ ████████████████████████▉ │
│ 1999-12-03 11:00:00 │ 39093 │ ███████████████████████████████▎ │
│ 1999-12-03 12:00:00 │ 87328 │ █████████████████████████████████████████████████████████████████████▊ │
│ 1999-12-03 13:00:00 │ 38772 │ ███████████████████████████████ │
│ 1999-12-03 14:00:00 │ 31445 │ █████████████████████████▏ │
│ 1999-12-03 15:00:00 │ 22470 │ █████████████████▉ │
│ 1999-12-03 16:00:00 │ 14399 │ ███████████▌ │
│ 1999-12-03 17:00:00 │ 8251 │ ██████▌ │
│ 1999-12-03 18:00:00 │ 4296 │ ███▍ │
│ 1999-12-03 19:00:00 │ 1973 │ █▌ │
│ 1999-12-03 20:00:00 │ 823 │ ▋ │
│ 1999-12-03 21:00:00 │ 322 │ ▎ │
│ 1999-12-03 22:00:00 │ 106 │ │
│ 1999-12-03 23:00:00 │ 30 │ │
│ 1999-12-04 00:00:00 │ 22 │ │
......
│ 2000-01-01 00:00:00 │ 18 │ │
│ 2000-01-01 01:00:00 │ 36 │ │
│ 2000-01-01 02:00:00 │ 120 │ │
│ 2000-01-01 03:00:00 │ 302 │ ▏ │
│ 2000-01-01 04:00:00 │ 798 │ ▋ │
│ 2000-01-01 05:00:00 │ 1993 │ █▌ │
│ 2000-01-01 06:00:00 │ 4339 │ ███▍ │
│ 2000-01-01 07:00:00 │ 8280 │ ██████▌ │
│ 2000-01-01 08:00:00 │ 14686 │ ███████████▋ │
│ 2000-01-01 09:00:00 │ 22395 │ █████████████████▉ │
│ 2000-01-01 10:00:00 │ 31481 │ █████████████████████████▏ │
│ 2000-01-01 11:00:00 │ 39121 │ ███████████████████████████████▎ │
│ 2000-01-01 12:00:00 │ 86806 │ █████████████████████████████████████████████████████████████████████▍ │
│ 2000-01-01 13:00:00 │ 39060 │ ███████████████████████████████▏ │
│ 2000-01-01 14:00:00 │ 31020 │ ████████████████████████▊ │
│ 2000-01-01 15:00:00 │ 22618 │ ██████████████████ │
│ 2000-01-01 16:00:00 │ 14543 │ ███████████▋ │
│ 2000-01-01 17:00:00 │ 8235 │ ██████▌ │
│ 2000-01-01 18:00:00 │ 4263 │ ███▍ │
│ 2000-01-01 19:00:00 │ 1947 │ █▌ │
│ 2000-01-01 20:00:00 │ 809 │ ▋ │
│ 2000-01-01 21:00:00 │ 320 │ ▎ │
│ 2000-01-01 22:00:00 │ 114 │ │
│ 2000-01-01 23:00:00 │ 31 │ │
│ 2000-01-02 00:00:00 │ 3 │ │
│ 2000-01-02 01:00:00 │ 3 │ │
└─────────────────────┴───────┴────────────────────────────────────────────────────────────────────────┘
724 rows in set. Elapsed: 0.453 sec.
技術的な問題について話し合うために WX: xiedeyantu を追加することを歓迎します。