Software Design 202406
Bun
Node.js は以下の問題を抱えていた。
package.json
やnode_modules
などによるパッケージ管理の複雑さ- CJS/ESM の混在による複雑さ
- TypeScript の非サポート
これらを解消すべく Deno が生み出された。
package.json
やnode_modules
、CJS 廃止- テストランナー・バンドラーの同梱
- TS の標準サポート
しかし、Deno は Node.js との互換性がなく、移行はあまり進んでいない。これを踏まえ、Bun は Node.js と Deno の中間的な特徴を持って誕生した。
- パッケージマネージャー、テストランナー、バンド ラー、TS トランスパイラをすべて同梱しており追加作業が不要
- npm/yarn/jest/webpack/esbuild/babel などがすべて不要
- とにかく速い
- Node.js/Jest と互換性を持つ
- ドロップインリプレイスメントになることを目指している
Bun CLI というツールが含まれており、この CLI を使って様々な作業を行う。
bun run <file path>
ファイルを実行bun run <script name>
package.json スクリプトを実行bun x <package name
npx の代わり。bunx
でもよい。bun exec "echo hello"
シェルスクリプトを実行bun install
パッケージのインストールbun add <package name>
パッケージの追加bun remove <package name>
パッケージの削除bun update
semver に沿って最新化bun link/unlink
外部パッケージのリンク/アンリンク- yarn link と同じ
- dependencies に
"pkg_a": "link:pkg_a"
のように書かれる
bun pm
パッケージマネージャーの使い方bun pm bin (-g)
bin フォルダのパスを表示bun pm ls
パッケージを一覧表示bun pm cache (rm)
キャッシュフォルダを表示/削除bun test
テストを実行するbun test -t <filename>
特定の名前を含むテストファイルを実行bun test <filepath>
特定のテストファイルを実行bun build ./index.ts
バンドルして JS ファイルとして出力する(ベータ版)bun compile ./index.ts
実行可能バイナリとしてコンパイルする
実行計画インデックスの仕組み
RDBMS と SQL の基礎概念
リレーショナルモデルとは
リレーショナルモデル(関係モデル)とは、データモデルの一種である。
データモデルとは、データの表現方法と、演算の定義の組み合わせからなる。
リレーショナルモデルが扱うデータの単位はリレーション/関係と呼ばれる。特別な構造をもった、数学的な意味での「集合」の一種であり、順序も重複もない。リレーショナルモデルでは、このリレーションを値として演算を行う。
つまり、リレーショナルモデルとは、リレーションという集合がどのようなものであるか、そしてそれに対する演算はどのようなものかを定義したものである。
リレーションの構造は以下のようになっている。
- リレーション
- ヘッダ/見出しと、ボディ/本体からなる。
- 単に「リレーション」といった場合は、一般的に「ボディの全部」を指す。
- ヘッダ
- 属性の集合である。
- 属性は名前とデータ型からなる。
- データ型もまた集合である。
- ボディ
- タプル/組の集合である。
- タプルは属性値の集合である。
- 含まれる属性値はヘッダに定義されているため、全てのタプルは同じ構造を持つ。
※以下は便宜上テーブルとして表現しているものの、リレーションは集合であるため、順序はない。本来はベン図などで表すべきである。
学生 ID | 名前 | 年齢 | 学年 |
---|---|---|---|
1 | 田中太郎 | 20 | 2 年 |
2 | 鈴木花子 | 19 | 1 年 |
- 属性: 学生 ID(int), 名前(string), 年齢(int), 学年(int)
- 属性値: 「田中太郎」, 「20」など
- ヘッダ: 属性の集合
- タプル: 属性値の集合(田中太郎さんのデータ、鈴木花子さんのデータなど)
- ボディ: タプルの集合
リレーショナルモデルの演算
演算は、1 つ又は複数のリレーションを入力として、1 つのリレーションを出力するものである。これにより、リレーションの演算はその結果をま た別の演算の入力として利用することができる。以下のような種類がある。
射影 / Project
ヘッダから特定の属性のみを取り出し、タプルの属性を絞り込む演算。
重複は取り除かれる(集合には重複は存在しないため)。
e.g. 従業員のモデルから職位を重複なく抽出する
制限 / Restrict
特定の条件を持つタプルだけをリレーションから選出する演算。
e.g. 従業員のモデルから入社日が 2018 年以降の社員を選出する
和 / Union
集合和、つまり足し合わせたものを求める演算。同じヘッダを持つリレーション同士でしか行えない演算。重複は取り除かれる。
積 / Intersect
集合積、つまり共通部分を求める演算。同じヘッダを持つリレーション同士でしか行えない演算。重複は取り除かれる。
結合 / Join
SQL にはいろいろな結合があるが、リレーショナルモデルにおける結合は自然結合の一種類しかない。
自然結合は 2 つのリレーションを入力とし、まずは 2 つのリレーションに共通して存在する属性を見つけ、それらの属性の値が等しいタプル同士を見つけて合体させて新たなタプルとしていき、最終的にそのタプルの集合を出力する演算。
ヘッダが全く同じ 2 つのリレーションを入力とする場合、結果は積と同じになる。積は結合の特殊パターンといえる。
ヘッダに共通部分が全くない場合、結果は直積/Product となり、総当たり(タプルの総数 x タプルの総数)の組み合わせとなる。
SQL とリレーショナルモデルの関係性
SQL においてリレーションの概念を体現している要素は以下の通り。
- テーブル: リレーション
- カラム: 属性
- レコード: タプル
SQL の演算の入力はテーブルであり、出力もまたテーブルに相当するものであるという点が非常に重要である。
SQL の演算とリレーショナルモデルでの演算は以下のように対応する。実は SELECT は 3 つの演算を同時に行っているのである。
SELECT employee_name -- 射影
FROM employees -- 結合 (ここではJOINはしていないけど)
WHERE hire_date > '2018-01-01'; -- 制限
和は UNION で、積は JOIN で代用できる。
テーブルは以下の特徴もち、つまりリレーションではないため、演算の用語はリレーショナルモデルと SQL では異なっている。
- 行に順序がある
- 行が重複できる
- NULL を持てる
逆に、これらの特徴を可能な限りテーブルから取り除いておけば、リレーショナルモデルの利点を最大限引き出すことができる。たとえば、宣言的にクエリを記述することが可能になる。とはいえデータがリレーショナルモデルの範疇に収まるかどうかは、データの性質によるため、見極めが大事である。
リレーショナルモデルとインデックス
リレーショナルモデルとインデックスの親和性は低い。
そもそもインデックスや、インデックスを使って実装されている主キーというものは、リレーショナルモデルには存在しない。インデックスは RDBMS のベンダーごとに異なる実装の話である。キーも、リレーショナルモデルに存在するのは「候補キー」という「タプルを一意に特定するための属性の組み合わせのうち、属性の数が最小になるもの」が定義されているのみである。