TPC-DS scale factor = 1000(1TB)のデータセットを用意する（ DBFS上のInitスクリプトの有効期間終了ver）


※コードなど詳細についてはgithubにまとめました。ご覧ください。

https://github.com/reijiotake/tpc-ds-dataset-generator-2025-ver-How-to-Unload-Data-to-a-Data-Lake-Using-Databricks-/blob/main/README.md

# はじめに
TPC-DSデータセット 1TB(scale facter = 1000)の生成にかなり苦労したので、
参考になった資料、躓きポイントをまとめました。

簡単なまとめとなり大変恐縮ですが、皆様の一助となれば幸いです。

# 手順

## 1. 以下の記事を見て全体像を把握

https://3cloudsolutions.com/resources/generate-data-with-databricks-using-tpc-ds/

## 2. 1.の記事にリンクのあるGithubのクローンをDatabricksに置く

https://github.com/BlueGranite/tpc-ds-dataset-generator/tree/master

### 2-1. 【準備】ADLSの準備とクラスタを作成しておく

▽クラスタ構成（一例）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3921999/4db48aa6-4265-febc-35b1-062c4056c011.png)


### 2-2. TPC-DS-Configure.pyを実行する

:::note 
DBFS上のInitスクリプトは有効期間が終了しているので以下対応策です。
※Unity Catalog無効環境で実施してます。
①ノートブックに記載のある以下を実行し、スクリプトを一旦dbfsに保存

```ruby:
dbutils.fs.mkdirs("dbfs:/databricks/scripts")
```

```ruby:
dbutils.fs.put("/databricks/scripts/tpcds-install.sh","""
#!/bin/bash
sudo apt-get --assume-yes install gcc make flex bison byacc git

cd /usr/local/bin
git clone https://github.com/databricks/tpcds-kit.git
cd tpcds-kit/tools
make OS=LINUX""", True)
```

② DBFS上のファイルを /FileStore ディレクトリにコピー

```ruby:
dbutils.fs.cp("/databricks/scripts/tpcds-install.sh", "/FileStore/tpcds-install.sh")
```

③ダウンロードリンクの生成:

```ruby:
displayHTML("<a href='/files/tpcds-install.sh' download>Download tpcds-install.sh</a>")
```
④表示されたリンクをクリックして、ファイルをダウンロード

⑤ダウンロードした.shファイルをvisual studioなどを使用し以下のように修正します。
修正せず、そのままinitスクリプトとして使用するとエラーになります。

```ruby:
#!/bin/bash

# 必要なパッケージのインストール
apt-get update
apt-get --assume-yes install gcc make flex bison byacc git

# tpcds-kitのクローンとビルド
cd /usr/local/bin
git clone https://github.com/databricks/tpcds-kit.git
cd tpcds-kit/tools
make OS=LINUX
```

⑥スクリプトをローカルからDatabricksの任意のワークスペースにアップロード

⑦ワークスペースにアップロードしたスクリプトのパスを用いてクラスターのinitスクリプトに登録
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3921999/e38ef845-081e-d202-e81d-cb0f1485093b.png)

⑧クラスターを再起動

▽参考
https://learn.microsoft.com/ja-jp/azure/databricks/init-scripts/#cluster-scoped-init-script
:::

### 2-3. TPC-DS-GenerateData.pyを実行する

scale facter = 1000　など適宜値を変更する
私が実行したコードは以下

```ruby:
%scala
import com.databricks.spark.sql.perf.tpcds.TPCDSTables

// Set:
val scaleFactor = "1000" // scaleFactor defines the size of the dataset to generate (in GB).
val scaleFactoryInt = scaleFactor.toInt

val scaleName = if(scaleFactoryInt < 1000){
    f"${scaleFactoryInt}%03d" + "GB"
  } else {
    f"${scaleFactoryInt / 1000}%03d" + "TB"
  }

val fileFormat = "parquet" // valid spark file format like parquet, csv, json.
val rootDir = s"/mnt/datalake/raw/tpc-ds/source_files_${scaleName}_${fileFormat}"
val databaseName = "tpcds" + scaleName // name of database to create.

// Run:
val tables = new TPCDSTables(sqlContext,
    dsdgenDir = "/usr/local/bin/tpcds-kit/tools", // location of dsdgen 
    scaleFactor = scaleFactor,
    useDoubleForDecimal = false, // true to replace DecimalType with DoubleType 
    useStringForDate = false) // true to replace DateType with StringType

tables.genData(
    location = rootDir,
    format = fileFormat,
    overwrite = true, // overwrite the data that is already there
    partitionTables = true, // create the partitioned fact tables 
    clusterByPartitionColumns = true, // shuffle to get partitions coalesced into single files. 
    filterOutNullPartitionValues = true, // true to filter out the partition with NULL key value
    tableFilter = "", // "" means generate all tables
    numPartitions = 1000) // how many dsdgen partitions to run - number of input tasks.

// Create the specified database
sql(s"create database IF NOT EXISTS $databaseName")

// Create metastore tables in a specified database for your data.
// Once tables are created, the current database will be switched to the specified database.
tables.createExternalTables(rootDir, fileFormat, databaseName, overwrite = true, discoverPartitions = true)

// Or, if you want to create temporary tables
// tables.createTemporaryTables(location, fileFormat)

// For Cost-based optimizer (CBO) only, gather statistics on all columns:
tables.analyzeTables(databaseName, analyzeColumns = true)

```

53分で終了しました。

:::note alert
なぜかGitHubのコードで以下が二回繰り返されているので片方は削除
削除しないとエラーになる
またIF NOT EXISTSを追加した
```ruby:
// Create the specified database
sql(s"create database IF NOT EXISTS $databaseName")
```
:::


### 2-4. customerテーブルを表示し、実行が成功していることを再確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3921999/51a69443-0cbd-2f89-1c6b-56b56d7e153c.png)

### 2-5. ADLS2内の中身も確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3921999/8f682aeb-a7b6-a612-9c8f-6f51807e5aaf.png)

# パーティションなし・1Parquetファイルあたりのサイズを調整したい場合
ここまでで、TPC-DSの環境設定とデータセット生成を一通り行うことができましたが、
今後これらのデータセットを活用するうえで、パーティションなし・1Parquetファイルあたりのサイズを調整する必要がでてきました。

オプションとなりますので、以下の記事にまとめました。

https://qiita.com/ReijiOtake/items/3d6bc52f4c78afee9269


# その他参考リンク

https://www.tpc.org/tpcds/results/tpcds_result_detail5.asp?id=121103001#


https://www.databricks.com/jp/blog/2021/11/15/snowflake-claims-similar-price-performance-to-databricks-but-not-so-fast.html

https://qiita.com/manabian/items/93d9330cdb607383c2b9