「データエンジニアリングの基礎」を読もう 6章 ストレージへの保存 

# 本記事の位置付け

下記読書会のための要約です。
https://gaisaba.connpass.com/event/328612/

## 課題図書

翻訳版

https://www.oreilly.co.jp/books/9784814400652/

英語版

https://www.amazon.co.jp/dp/1098108302/

もともとは英語版をじっくり読むスタイルの読書会でしたが、進めているうちに翻訳版が出たことや、内容全体を早めにキャッチアップしたいことから、今は翻訳版を1章ずつ読み進めています。

## 今回の範囲

6章 ストレージへの保存

:::note warn
ボリューム多かったです。。。
要約は本文の個別論点に深く立ち入るより、全体のつながりを中心に記載します。
:::

# 要約

## 結論(6.7)を先に

この章の結論は、

使っているストレージシステムの内部構造と制限について深い知識を持ちましょう！
そのストレージに適したデータ、アクティビティ、ワークロードのタイプを知りましょう！

という話です。

:::note
ボリュームのある章ですが、自分の扱うストレージシステムを想定して、この観点で読んでいくと入りやすそうですね。
:::

## 全体の流れ

前半（6.1〜6.3）は、ストレージに関するテクノロジーを下位層から上位層に向かって概説するパートです。

最初に「データストレージの原材料」（6.1）として、磁気ディスクやSSDのような、ストレージに使われる物理的テクノロジの概要をさらいます。次に「データストレージシステム」（6.2）として、原材料を使った一つ上の階層であるファイルストレージ、ブロックストレージ、オブジェクトストレージの概要説明と、それを理解する上で重要な概念の解説があります。「データエンジニアリングにおけるストレージ抽象」（6.3）では、データウエアハウス、データレイク、データレイクハウスについてを取り上げます。

後半は、前半で扱った内容全般に関わる説明で、「ストレージの要点とトレンド」（6.4）における、データカタログやコンピュート・ストレージの分離などのトレンドの概説や、「一緒に仕事する人」（6.5）、「底流」（6.6）の説明があります。

## 6.1 データストレージの原材料

:::note warn
物理的な原材料と、それを扱う技術という区別が本書の中で明確にされているわけではないのですが、ごっちゃにしない方がわかりやすいかなということで要約上は分けています。
:::

### ストレージの物理的な原材料（6.1.1〜6.1.4）

データストレージの物理的な原材料としては、以下が挙げられる。

- 磁気ディスクドライブ
- SSD
- RAM
- ネットワークとCPU

#### HDD, SSD, RAM

上3つの特徴をまとめるとこんな感じ。

| 項目 | HDD | SSD | RAM |
|:-:|:-:|:-:|:-:|
|速度  | 遅い| 中程度|速い|
|価格 |安い |中程度 |高い|
|同じ価格で得られる<br>ストレージ量|大|中|小|
|永続 or 揮発|永続|永続|揮発|

同じコストで考えると、速さとストレージ量が常にトレードオフになる。
そのため、よく使うデータや、今まさに処理中のデータをより速いストレージ層に置き、そうでないデータを遅くて大きいストレージ層にこぼすという戦略がよく使われる。

各技術の詳細に少しだけ触れておくと…

##### HDD

磁気ディスク常の磁気情報をヘッドが読み込む形をとる。
磁気ディスクの回転やヘッドの動きといった物理的な動きが直接レイテンシに影響する。

10GBあたりの価格：20〜30セント

:::note warn
上記の価格は本文中の記載をもとに、10GBあたりの単位に揃えて計算しなおしたものです。
:::

##### SSD

データをフラッシュメモリセルに電荷として保存する。
データの読み書きは物理的な動きではなく、純粋に電子的手段によって行われるので、HDDに比べ高速。
ただし、同じ容量のSSDはHDDに比べ10倍ほど高いため、「何もかもSSDに突っ込んでしまえ」は大規模な分析データストレージにおいては正解ではない。

10GBあたりの価格：2〜3ドル

##### RAM

SSDより転送速度は格段に速いが、価格は高い。
HDD, SSDが永続的にデータを保持できるのに対し、RAMは電源が切られるとデータを失う（揮発性）。

- CPUに直接接続しており、CPUアドレス空間にマッピングされる。
- CPUが実行するコードと、そのコードが直接処理するデータを格納する。

10GBあたりの価格：約100ドル

#### ネットワークとCPU

ネットワークとCPUがなぜストレージの原材料として挙げられているかというと、分散ストレージが普及しているから。
分散ストレージは、HDDのストレージサイズあたりの価格の安さを活かしつつ、遅さをカバーするために並列処理を行うため、並列処理を制御するためのCPUと、個々のノードをつなぐネットワークがクラスタ全体の性能に大きく影響する。

### ストレージの物理的な原材料を扱う技術（6.1.5〜6.1.7）

ストレージの物理的な原材料を扱う技術として、以下が挙げられる。

- シリアライズ
- 圧縮
- キャッシュ

#### シリアライズ

シリアライズ・デシリアライズの概念は、以下のブログの図がわかりやすいかも。

https://yamory.io/blog/about-insecure-deserialization

データをメモリやストレージ上で保管可能なバイト列の形に変換するのがシリアライズ、バイト列をプログラムや人間の目で見て扱える形に変換するのがデシリアライズ。

シリアライズ / デシリアライズの技術については、本文の付録Aに解説あり。

行指向のシリアライズには CSV, XML, JSON, JSONL, Avro などがあり、列指向のシリアライズには Parquet, ORC, Apache Arrow のほか、インメモリシリアライズ という技術もある。

大規模データの分析環境では、列指向のシリアライズ技術が主に使われている。
なぜなら↓

https://x.com/IQ_Bocchi/status/1830051278908768438

列指向のシリアライズ技術の中では、ORC よりは Parquet が業界標準だが、最近はインメモリ処理と外部エクスポートが両方できる Apache Arrow や インメモリシリアライズといった技術もある。

:::note 
Apache Arrow 知らなかった。。。今度ちゃんと調べてみたい。
:::

さらに、複数のシリアライズ技術を組み合わせたり、シリアライズを他の抽象レイヤ（スキーマ管理など）と統合する技術としてハイブリッドシリアライズがあり、例として Apache Hudi や Apache Iceberg がある。

:::note
Apache Hudi や Apache Iceberg は オープンテーブルフォーマットの技術として認識していたけど、ハイブリッドシリアライズと言われるとなるほど。
Iceberg については [こちら](https://qiita.com/IQ_Bocchi/items/211d9a5021e95f622aa3#iceberg) の記事に有名な絵を載せています。
この絵の中の「Data Files」のフォーマットは複数のシリアライズに対応していて、現時点では Parquet, ORC, Avro に対応している。
:::

#### 圧縮

圧縮には、圧縮・解凍に伴うオーバーヘッドもあるが、以下の3つの利点がある。

1. ディスクスペースの節約
1. スキャン速度の向上
1. ネットワーク性能の向上

:::note
1しか考えたことなかった。2と3もあるのか、なるほど！
:::

#### キャッシュ

すぐ使うデータほど高くても速いタイプのストレージに置き、そうでないデータほど遅くても安いストレージに置いておくという考え方。

下表の中で、CPUキャッシュにはまさに今使っているデータ、アーカイブストレージには、捨てられないけど年に1度とかそれ以下の頻度でしかアクセスしないようなデータを置いておく。

| ストレージタイプ | データ取得レイテンシ | 帯域 | 価格 |
|:-:|:-:|:-:|:-:|
|CPUキャッシュ |1ナノ秒 |1TB/秒 |N/A |
|RAM |0.1マイクロ秒| 100GB/秒|10ドル/GB   |
|SSD|0.1ミリ秒|4GB/秒|0.2ドル/GB|
|HDD|4ミリ秒|300MB/秒|0.3ドル/GB|
|オブジェクトストレージ|100ミリ秒|10GB/秒| 月額0.02ドル/GB|
|アーカイブストレージ|12時間|★|月額0.004ドル/GB |

★アーカイブストレージの帯域は、利用可能になってからはオブジェクトストレージと同じ。

ナノ、マイクロ、ミリについては以下を参照。

https://45kaku.com/itpassport_text_35-02/

## 6.2 データストレージシステム

上記のデータストレージの原材料を、一段階抽象化させたレベルがデータストレージシステム。

### ストレージシステムの前提知識

#### 6.2.1 単体サーバ vs 分散ストレージ

最近の分析システム（オブジェクトストレージ、Apache Spark、クラウドデータウエアハウスなど）は分散ストレージアーキテクチャに依存しているものが多いので、データエンジニアは分散システムの一貫性パラダイムを意識しておこうね！

#### 6.2.2 結果整合性と強い一貫性

強い一貫性を持つ = ACID に準拠している
結果整合性を持つ = BASE に準拠している

BASE は [ACID](https://e-words.jp/w/ACID%E7%89%B9%E6%80%A7.html#google_vignette) の逆だと思えばいい

BA Basicalli Available - 基本的に利用可能
S Soft-tate - トランザクションの状態が曖昧で、コミットされているかいないかがわからない
E Eventual consistency - 最終的には一貫する

:::note warn
本文中では、分散データベースで ACID 準拠させる（＝強い一貫性を持たせる）場合はレイテンシを許容できることが条件となっているが、Iceberg などはこのあたりを解決する技術になり得るのでは
:::

データエンジニアが一貫性について意思決定を行うべき箇所として、以下の三つのレベルが挙げられる

1. データベーステクノロジ自体が実現できる一貫性
1. データベースの構成パラメータ
1. クエリレベルでの一貫性

いずれにしてもデータエンジニアは、データベースの一貫性についてよく理解しておこう。

### 6.2.3 ファイルストレージ

#### ファイルストレージの特徴

ここでは、ファイルを有限長で、追記とランダムアクセスができるバイトストリームとして定義する。

ファイルストレージシステムは、ファイルをディレクトリツリーに整理し、**ルートから順にディレクトリの階層を辿る**形でファイルにアクセスする。

以下のようなファイルがあったら、OSはまずルートディレクトリ `/` を見つけ、その後 `Users`, `Chihiro` とたどって最後に `file.txt` を見つける。

```
/Users/Chihiro/file.txt
```

#### データパイプラインでファイルストレージを扱うときの注意

- ファイルの状態に注意する
- できるだけ短い時間しか使わないようにする
- 中間ストレージには利用しない（オブジェクトストレージを使うべし）

#### ファイルストレージの種類

- ローカルディスクストレージ
    - SSDやHDDで構成されるローカルディスクのパーティション上に作られる
    - OSが管理するファイルシステム
    - Windows では NTFS(New Technology File System)が標準
    - Linux では ext4 が標準
    - 書き出し後の読み込み一貫性（read after write consistency）をサポート
- NAS (Network Attached Storage)
    - ネットワーク経由でクライアントにストレージシステムを提供
    - ネットワークを経由するので、性能上のペナルティはある
    - ストレージが仮想化されていることの利点もある
        - 冗長性
        - 信頼性
        - 資源の細粒度の制御
        - 複数ディスクにまたがるストレージプールによる大規模な火葬ボリューム
        - 複数マシンからのファイル共有
- クラウドファイルシステムサービス
    - EFS（Amazon Elastic File System）など
    - NASと似ているが、ネットワーク、ディスクやクラスタの管理、障害、設定などをクラウドベンダが完全に管理する点が異なる

### 6.2.4 ブロックストレージ

#### ブロックストレージとは

- SSDやHDDにより提供される生のストレージ
- クラウドでは、仮想化されたブロックストレージ（EBSなど）が VM ストレージの標準
- ブロック＝ディスクがサポートする一指定可能なデータの最小単位
- トランザクションシステムのデータベースはブロックレベルでディスクにアクセスする
- クラウドVMのOS起動ディスクのデフォルト
- RAIDによって、複数のディスクをOSからは複数のディスクをひとつのブロックデバイスのように見せ、容量や耐久性を向上させることができる。
- SAN(Storage Area Network) により、ブロックストレージをネットワーク越しに抽象化して提供できる
- クラウドの仮想化ブロックストレージ（EBSなど）はSANに似ているが、SANクラスタやネットワークの細部をエンジニアが意識する必要がない

#### EBS について

- AWSで提供される、クラウドブロックストレージの標準
- 常にEC2と同じAZで提供されるため、AZ障害に対する耐久性はない
- EC2から独立してEBSのボリュームレプリカを作ったり、スナップショットをS3に複製することができる

#### ローカルのボリューム

- AWSでいうと、インスタンスストアがこれにあたる
    - 揮発性で、EC2 を Terminate するとインスタンスストアも消える（EBSのように、EC2から独立して生き残ったり、レプリケーションすることはできない）
    - ローカルキャッシュ的な使い方がメインなので、それでいいのだ
- EC2を使って Hadoop クラスタを構成するときは、インスタンスストアをローカルキャッシュとして使用する

:::note
EBSとインスタンスストアの違いは、こちらの記事がよくまとまっていた気がします。
https://dev.classmethod.jp/articles/howto-ec2-volatile-block-storage-instance-store/
:::

### 6.2.5 オブジェクトストレージ

ファイルストレージと似ているが、以下の点が異なる

- 格納されるオブジェクトは変更不可であること
    - 同じキーのファイルを保存すると、ファイル全体が上書きされる（部分更新ではない）
- 階層構造のディレクトリになっていない

:::note
S3の一見階層構造みたいに見えるプレフィックス＋ファイル名が実は階層構造じゃない話と、それを踏まえて何に気をつければいいのかは以下の記事がわかりやすかったです。
https://tech.nri-net.com/entry/s3_folder_structure_and_prefix
:::

#### オブジェクトストレージの一貫性

最近まで、S3の一貫性は結果整合性だった。
結果整合のオブジェクトストレージに強い一貫性を持たせるための方法のひとつは、強い一貫性を持つデータベース（Postgresなど）を併用すること。

- 書き出し時
    - オブジェクトを書き出す
    - 書き出したオブジェクトのバージョンに関するメタデータを、強い一貫性を持つデータベースに書き込む
- 読み込み時
    - 強い一貫性を持つデータベースから、最新のオブジェクトのメタデータを取得する
    - ↑をもとに、このメタデータと一致するまでオブジェクトの読み込みを繰り返す

:::note
この手法は、Iceberg がやっているバージョン管理やタイムトラベルの手法と似ている。
Iceberg では、最新のバージョンだけでなく、（スナップショットを残している限り）任意のバージョンのデータを取り出せる。
:::

オブジェクトストレージ自体がバージョン管理機能を提供している場合もあり、バージョン指定してオブジェクトを読み込むことでも一貫性の問題をクリアできる。

#### オブジェクトストレージのティア

耐久性やアクセス性が低いかわりに、コストの低いオブジェクトストレージが提供されている。

耐久性が低い - S3 OneZone-IA
アクセス性が低い - S3 Glacier シリーズ

Glacier シリーズなどのアーカイブ系のオブジェクトストレージは、ストレージのコストを下げるかわりに取り出しの料金は高く設定されている。

:::note warn
アーカイブ系のオブジェクトストレージに入れたデータに、予定していたよりも頻繁にアクセスしてしまうとかえって高くつくことがあるので注意
:::

### 6.2.6 キャッシュとメモリベースのストレージシステム

RAMを活用したキャッシュシステムとして、Memcached という軽量オブジェクトキャッシュとして使えるキーバリューストアや、Redisという2秒ごとに永続化レイヤにデータを書き出すメモリキャッシュがあるよ。

### 6.2.7 HDFS

Hadoopの概要⬇️

https://x.com/IQ_Bocchi/status/1830170240107626661

Hadoop は死んだという主張をよく耳にするが、Amazon EMR など多くのビッグデータエンジンが HDFSを使っている。

### 6.2.8 ストリーミングストレージ

ストリーミング処理におけるデータは、一定期間が経過すると消滅することが期待される一方、Apache Kafka のように長時間のストリームデータ保持が可能なものもある。

Kafka は、古くてアクセス頻度の低いデータをオブジェクトストレージにプッシュすることで無期限にデータを保存することができる。

このようなデータの長期保存により、リプレイ（過去に保存したデータの指定した範囲を返す）ことが可能になる。

### 6.2.9 インデックス、パーティショニング、クラスタリング

トランザクション用のRDBでは性能向上のためにインデックスを張ることが一般的。
一方、カラム型データベースでは日付を保持する列の値などによってパーティションを区切ることがあり、これによってスキャン範囲を減らすことで性能を出す戦略がよくとられる。

:::note
パーティションを日付で区切ることが多いのは、分析の際に WHERE 句で日付を限定してデータを SELECT することが多いから。でもパーティションは日付でしか切ってはいけないわけじゃなく、限定する列が日付じゃなくて部門なら、部門でパーティションを切ってもいい。
ただし、各パーティションの中身の数がだいたい同じになるような分け方にする必要がある。ばらつきが大きいと、あるパーティションではすごい性能出るけど別のパーティションでは全然出ないという事態が起こり得るので注意。
:::

クラスタは、パーティション内のデータをさらに細かく分割したもの。

:::note warn
これをバケットと呼ぶエコシステムもある気がする
:::

Snowflake のマイクロパーティションでは、多くの行で繰り返し出現する値をメタデータベースとして持っておき性能向上をはかっている。これはRDBのインデックスに近い戦略。

## 6.3 データエンジニアリングにおけるストレージ抽象

ここからデータウエアハウス、データレイク、データレイクハウスの話に入っていくが、以下の検討事項をもとにどれにするか決めようね

- 目的とユースケース
    - データを何に使うのか？
- 更新パターン
    - 一括更新、ストリーミング挿入、アップサートに最適化されているか？
    - （⬆️の中で、自分達がやりたいことができる技術を選んでいるか）
- コスト
    - 直接・間接のコスト、価値を得られるまでの時間、機会費用も含めて考えよう
- ストレージとコンピュートの分離
    - トレンドのセクション参照

### 6.3.1 データウェアハウス

OLAPデータアーキテクチャの標準だが、非構造のデータを扱うことはできない

### 6.3.2 データレイク

もとは生データを未加工の状態で保持するストアとして考案された。
Hadoop を使ってデータレイクを構築すると、商用MPP（超並列処理システム）に高いお金を払わずに大量データを保持することができた。

ただし、以下によってデータレイクハウスが台頭。

- コンピュートとストレージ分離のトレンド
- MPPが提供するスキーマ管理、更新、マージ、削除機能などの有用性が見直されたこと

:::note warn
データウェアハウス、データレイクからなぜデータレイクハウスがトレンドになったかは諸説ある。
:::

### 6.3.3 データレイクハウス

データの持ち方はデータレイクと同じ（オブジェクトストレージ）だが、そこにあるデータをデータウエアハウスのように扱えるための機構（テーブルとスキーマのサポート、増分更新と削除の管理など）を備えたもの。

レイクハウスでは、必要とされる部分にはデータウエアハウスの機能を適用しつつ、そうでないデータは形式を問わず生のまま保持することができる。

### 6.3.4 データプラットフォーム

さまざまなベンダーが自社プロダクトを「データプラットフォーム」と呼び、相互運用性を主張しつつベンダーロックインしようとしている競争が始まっている。

ただしデータプラットフォームという概念がまだ完全に具現化されたわけではない。

### 6.3.5 ストリーム・トゥ・バッチ亞０着てくちゃ

Lamdba アーキテクチャのようなもの。

## 6.4 ストレージの要点とトレンド

ストレージアーキテクチャを構築する際の重要な考慮事項について。

### 6.4.1 データカタログ

組織全体の全データを一元的に管理するメタデータストアのこと。

一般的に、以下の特徴を備える

- 運用データソースと分析データソースいまたがって機能する
- データのリネージとデータの関係のプレゼンテーションを統合する
- データ記述のユーザーによる編集を提供する

:::note warn
ある閉じたシステムの中で、そのシステムが自分の中のデータを正しく扱えるようにするためのメタデータを保持・管理する仕組みをカタログと呼ぶこともあるが、この意味でのカタログとは分けて考えた方が良さそう。
いいネーミング（呼び分け）がないものか。
:::

### 6.4.2 データ共有

慎重にアクセスポリシーを定義しつつ、適切な相手にデータを共有することはデータプラットフォームの中核機能である。

### 6.4.3 スキーマ

テーブル形式のスキーマに限らず、データを読み書きする際のスキーマのこと。
トランザクションDBでは書き込み時スキーマ（Schema on Write、書き込む時点でスキーマ適合しているかをチェックし、適合していなければ弾く）を採用しているが、データレイクでは読み込み時スキーマ（Schema on Read、書き込み時は自由に書き込み、読むときにスキーマを当てる）が一般的。

### 6.4.4 コンピュートとストレージの分離

Hadoop はコンピュートとストレージのコロケーション（データに近いところで処理をする）を活用したアーキテクチャとして登場し、現在はコンピュートとストレージの分離がトレンドになっている。

…ように見えるが、データをやたら転送したりネットワーク上を流したりすることにはデメリットもあり、結局は分離とコロケーションのハイブリッドが真のトレンドになってゆくだろう！

### 6.4.5 データストレージのライフサイクルとデータ保持

データの読み出し頻度とストレージコスト、読み出しのコストを鑑みて、適切なストレージを選択しましょう。

| | Hot | Warm | Cold |
|:-:|:-:|:-:|:-:|
|アクセス頻度|非常に頻繁|頻繁ではない|頻繁ではない|
|ストレージコスト|高|中 | 低  |
|読み込みコスト| 低| 中  |  高 |

ホットはSSDやメモリなどの高速アクセス系、コールドはアーカイブのイメージ。

### 6.4.6 シングルテナントとマルチテナント

データベースとテナントが１：１なのがシングルテナント、１：他なのがマルチテナント。
それぞれを利用する際の注意点は「8章 クエリ、データモデリング、変換」で説明

## 6.5 一緒に仕事する人

インフラチーム（DevOps, セキュリティ, クラウドアーキテクト）などと交流しながら、下流のユーザーが安全に高品質なデータを使えるようにやっていきましょう。
企業の成熟度モデルによって、職務分掌と交流する相手も変わる。
成熟度が低い場合は、データエンジニアが自分でストレージシステムとワークフローを管理することになるだろう。
成熟度が高い場合は、データエンジニアはストレージシステムのみ or その一部を管理して、その両側（取り込みと変換）にいるエンジニアと交流するだろう。

## 6.6 底流

- セキュリティ
    - セキュリティは業務の障害ではない。きちんとしたアクセス制御ができていてこそ、データの共有が可能になり、データの価値を最大化できるのだ。
    - 最小権限の原則に従うこと。
- データ管理
    - メタデータの管理、オブジェクトストレージにおけるバージョン管理、プライバシー関連の法令対応に気を配りましょう
- DataOps
    - システムとデータのモニタリングの仕組みを検討しましょう
- データアーキテクチャ
    - 第3章を参考に、適切なデータアーキテクチャを採用しましょう
- オーケストレーション
    - データを流すポンプにあたるオーケストレーションツールは、ストレージシステムと密接に関わり合っています。
- ソフトウエアエンジニアリング
    - データを処理するためのソフトウエア
        - データリークやメモリリーク、性能上の問題を引き起こさないように正しく動作させましょう
    - インフラ定義としてのソフトウエア
        - IaaCを活用し、データ処理には短命な計算資源を使うようにしましょう

## 6.7 結論（ふたたび）

使っているストレージシステムの内部構造と制限について深い知識を持ちましょう！
そのストレージに適したデータ、アクティビティ、ワークロードのタイプを知りましょう！

# 最後に

こちらの読書会に興味を持ってくださった方は、ぜひこちらよりご参加ください。

https://gaisaba.connpass.com/

隔週月曜日 19時〜20時に開催しております。
（Fundamentals of Data Visualization と交互に開催）