> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-fix-nav-issues.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# ClickHouse でランダムなテストデータを生成する

> ClickHouse でランダムなテストデータを生成する方法を紹介します

新しいユースケースの検証や実装のベンチマークでは、ランダムデータの生成が役立ちます。
ClickHouse には、[ランダムデータを生成するための幅広い関数](/ja/reference/functions/regular-functions/random-functions) が用意されており、多くの場合、外部のデータ生成ツールは不要です。

このガイドでは、求めるランダム性が異なるさまざまなケースに応じて、ClickHouse でランダムなデータセットを生成する方法をいくつかの例で紹介します。

<div id="simple-uniform-dataset">
  ## シンプルな一様分布のデータセット
</div>

**用途**: ランダムなタイムスタンプとイベントタイプを持つユーザーイベントのデータセットを手早く生成します。

```sql theme={null}
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`: 1万人のユーザーに対する一様分布
* `arrayElement(...)`: 3種類のイベントタイプのうち1つをランダムに選択
* タイムスタンプは過去24時間にわたって分散

***

<div id="exponential-distribution">
  ## 指数分布
</div>

**ユースケース**: 多くは少額で、ごく一部だけが高額になる購入金額をシミュレートします。

```sql theme={null}
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);
```

* 直近の期間全体に均等に分布したタイムスタンプ
* `randExponential(1/10)` — 値の大半は 0 付近で、最小値が 15 になるようにオフセット (\[ClickHouse]\[1], \[ClickHouse]\[2], \[Atlantic.Net]\[3], \[GitHub]\[4])

***

<div id="poisson-distribution">
  ## 時間帯に偏りのあるイベント (ポアソン)
</div>

**ユースケース**: 特定の時間帯 (例: ピーク時間帯) に集中して発生するイベントの到着をシミュレートします。

```sql theme={null}
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);
```

* イベントは正午ごろにピークを迎え、ばらつきはポアソン分布に従います

***

<div id="time-varying-normal-distribution">
  ## 時間とともに変化する正規分布
</div>

**ユースケース**: 時間とともに変化するシステムメトリクス (例: CPU 使用率) を再現します。

```sql theme={null}
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);
```

* `usage` は日周の正弦波＋ランダムな変動に従います
* 値は \[0,100] の範囲に収まります

***

<div id="categorical-and-nested-data">
  ## カテゴリカルデータとネストデータ
</div>

**ユースケース**: 複数の興味・関心を持てるユーザープロファイルを作成します。

```sql theme={null}
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);
```

* 配列の長さは1〜3のランダムな値
* 各関心項目に対して、ユーザーごとのスコアを3つ

<Tip>
  さらに多くの例については、[ClickHouse でランダムデータを生成する](https://clickhouse.com/blog/generating-random-test-distribution-data-for-clickhouse)ブログをお読みください。
</Tip>

<div id="generating-random-tables">
  ## ランダムなテーブルの生成
</div>

[`generateRandomStructure`](/ja/reference/functions/regular-functions/other-functions#generateRandomStructure) 関数は、[`generateRandom`](/ja/reference/functions/table-functions/generate) テーブルエンジンと組み合わせることで、テストやベンチマーク、あるいは任意のスキーマを持つモックデータの作成に特に役立ちます。

まずは、`generateRandomStructure` 関数を使って、ランダムな構造がどのようなものかを見てみましょう。

```sql theme={null}
SELECT generateRandomStructure(5);
```

次のように表示されることがあります:

```response theme={null}
c1 UInt32, c2 Array(String), c3 DateTime, c4 Nullable(Float64), c5 Map(String, Int16)
```

シードを使うことで、毎回同じ構造を得ることもできます:

```sql theme={null}
SELECT generateRandomStructure(3, 42);
```

```response theme={null}
c1 String, c2 Array(Nullable(Int32)), c3 Tuple(UInt8, Date)
```

では、実際にテーブルを作成し、ランダムなデータを投入してみましょう。

```sql theme={null}
CREATE TABLE my_test_table
ENGINE = MergeTree
ORDER BY tuple()
AS SELECT * 
FROM generateRandom(
    'col1 UInt32, col2 String, col3 Float64, col4 DateTime',
    1,  -- データ生成のシード
    10  -- 異なるランダム値の数
)
LIMIT 100;  -- 100行

-- ステップ2: 新しいテーブルにクエリを実行する
SELECT * FROM my_test_table LIMIT 5;
```

```response theme={null}
┌───────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 │
└────────────┴───────────┴──────────────────────────┴─────────────────────┘
```

両方の関数を組み合わせて、完全にランダムなテーブルを作りましょう。
まず、どのような構造になるかを見てみましょう。

```sql theme={null}
SELECT generateRandomStructure(7, 123) AS structure FORMAT vertical;
```

```response theme={null}
┌─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) │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
```

次に、その構造でテーブルを作成し、`DESCRIBE`ステートメントを使って作成結果を確認します。

```sql theme={null}
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;
```

```response theme={null}
   ┌─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) │              │                    │         │                  │                │
   └──────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘
```

生成されたデータのサンプルとして、最初の行を確認します。

```sql theme={null}
SELECT * FROM fully_random_table LIMIT 1 FORMAT vertical;
```

```response theme={null}
Row 1:
──────
c1: 80416293882.257732 -- 約804億2000万
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}
```
