RDB vs NoSQL vsNewSQL
まとめ
- データベースシステムは大きくRDB,NoSQL,NewSQLがある(2025/4現在)
- データベースの性能や特徴を表す指標として,ACID特性,CAP定理,スケーラビリティがある.
- データベースシステムは,計算機の性能向上・低価格化・クラウド化などの歴史に伴って変化している
前提知識
RDB
Relational Database.複数の表形式のテーブルからなるDB.SQL言語でクエリを記述し,データを取得する.ACID特性が保証されており,ACIDに対するDBMSの責務が大きい.一方,デメリットはスケーラビリティが低いこと. MySQL,PostgreSQL etc...
NoSQL
Not Only SQL.key-value型/KVS(Redis,DynamoDB),ドキュメント型(MongoDB,Google Firestore)など. エントリやドキュメント(JSON風の構造化データ)単位で,それぞれは互いに独立しているので,シャーディングが簡単.従ってスケールアウトしやすい.一方で,ACID特性が保証されない(複雑なトランザクションは諦めるか,アプリケーション側のロジックで限定的に対応)
NewSQL
RDBのACID特性を維持しつつも,水平スケーラビリティを高め,分散システムでの運用を便利にしたデータベースシステム. テーブルを分割して各マシンに置く(シャーディング).ACID特性などは,数学的・アルゴリズム的な呪術(Raftなど)によって保証されている.
Google Spanner,TiDB,CockroachDBなど.
トランザクション
CRUD処理(DB操作の最小単位)を組み合わせた意味のある処理の単位.トランザクションの完了はコミット,失敗した場合は元にトランザクションの開始前にロールバックされる.
ACID特性
- Atomicity(原子性):トランザクションは0(失敗)か1(成功)のどちらか.中途半端な状態はない
- Consistency(一貫性):データが一貫して正当な状態であること
- Isolation(独立性):複数のトランザクションが独立して実行されること.
- Durability(永続性):トランザクションがコミットされた時点で,その結果は永続しなくてはならない.
CAP定理
www.ibm.com 分散システムにおけるデータの持つべき特性.
- Consistency(一貫性):どのノードへアクセスしても同じデータが返ってくること
- Availability(可用性):あるノードの障害によって,別のノードの機能性が損なわれず,応答を返してくれる.(単一障害点となるノードが無い,全体としては常に稼働している)
- Partition tolerance(分断耐性):ネットワークの一部が切断されても,稼働し続ける
上記の3項目のうち,同時に満たせるのは2つまでであるという定理.データベースシステムのトレードオフ性.
スケールアウト
データベースサーバの数を増やすスケーリング.データベース,特にRDBのスケールアウトは,複数サーバー間でACID特性を満足する必要があり難しい.(そもそも,RDBは単一サーバでの稼働を前提に考えられている) 一方,NoSQLはシャーディングが簡単なので,スケールアウトしやすい (スケールアップ:マシン自体の性能を高めるスケーリング)
シャーディング
データベースの水平分割.
RDB vs NoSQL vs NewSQL
- トランザクション,複雑なDB処理などに対するデータの整合性が重要,ACIDが重要→RDB
- データ構造やクエリ自体はそこまで複雑にならないが,拡張性,柔軟性が欲しい→ NoSQL
- RDBのACID特性+NoSQLの拡張性・柔軟性が両方欲しい→NewSQL(ただし,技術的な要求は高い)
という結論になりそう
終わりに
データベースシステムの変遷には以下のような歴史があるみたい
- 初期:データベースシステムとしてのRDB.高性能な一つのマシンをDBサーバとして使用するのが最良.
- 中期:マシンの低価格,高スペック化.OSSの成熟,クラウドコンピューティングの普及などにより,廉価な複数のマシンによる水平スケーリングが台頭
- 最近:水平スケーラビリティの高く,柔軟性,変更性の高いNoSQLは,移り変わりや成長の激しいtoCサービス(SNS)などに最良の選択.また,NewSQLなど,スケーラビリティとACIDの両立を目指す技術も出てくる.
参考
【備忘録】Laravel sailで作成したdocker環境における,マイグレーション時のファイルパス指定について
解決したので,解決方法を共有
docker上にLaravel sailで構築したLaravel 環境において,特定のマイグレーションファイルのみを実行しようとしたらエラーが発生
ErrorException
mkdir(): File exists
at vendor/laravel/framework/src/Illuminate/Filesystem/Filesystem.php:651
647▕ if ($force) {
648▕ return @mkdir($path, $mode, $recursive);
649▕ }
650▕
➜ 651▕ return mkdir($path, $mode, $recursive);
652▕ }
653▕
654▕ /**
655▕ * Move a directory.
+17 vendor frames
18 artisan:35
Illuminate\Foundation\Console\Kernel::handle()
mkdir(): File existsとあるので,ファイル周りが原因らしいが,よくわからない... ちなみに,ファイル指定しないマイグレーションは普通にできたので,ファイルパスが原因そう...
ChatGPTさんに聞くと,こんな回答が返ってきた.
✅ --path の正しい指定方法 もしファイルがあるなら、次のように --path の指定を修正 して実行してください。
sh コピーする 編集する ./vendor/bin/sail artisan migrate --path=/var/www/html/database/migrations/2025_02_20_165310_rename_recipes_table_column.php
💡 ポイント /var/www/html/ は Sail 環境の Laravel のルートディレクトリ /var/www/html/database/migrations/ のフルパスで指定するのが確実 database/migrations/xxxx_xx_xx_xxxxxx_your_migration_file.php だけを実行できる
実際に上記のファイルパスを指定してやってみたら,うまく行った.やったぜ.

どうやら,sailコマンド自体はローカルから .vendor/bin/sail で実行できるが,処理自体はコンテナ内で行われるため,ファイルパスはコンテナを基準にする必要があるとのこと. 詳しいことはあまりわからなかった.ただ,var/www/htmlはdocker-compose.ymlのvolumesに記載されているパスで,永続化とかマウントとか色々な言葉が出てきた.よくわからない
用語
- Laravel sail
Laravel Sailは、LaravelのデフォルトのDocker開発環境を操作するための軽量コマンドラインインターフェイスです。 Sailは、Dockerの経験がなくても、PHP、MySQL、Redisを使用してLaravelアプリケーションを構築するための優れた出発点を提供します。
- docker volumes dockerのコンテナ内で作成したデータを永続化するための場所
その他
エンジニアのキャリア、アスリートと似てる説
ソフトウェアエンジニアの働き方というのは、いわゆるジョブ型というやつで、日本においてはまだまだ特殊な部類になる気がする。
就活期間は家族をはじめ周囲の人たちにエンジニアのキャリアの特性(転職の回数が多い・リモート勤務・業界の企業の規模感)を理解してもらうことにやや手間取った。
大学を卒業したら当然地元の企業に勤めると思っており、東京で就職すると言ったら、やたらめったらお金のことを心配してくれる。(結局、親は金銭面以外では完全に自由法人なので、心配こそすれ、何かを勧めてくることはないのだけど)
さて、どうすれば世間一般に馴染みのないエンジニアの特殊な働き方を理解してもらえるだろうか、と色々考えてみて、
「キャリア的に、エンジニアとアスリートはとても似ている」
という説明を思いついた。
エンジニアとアスリート、世間一般の人々の中には「陰と陽」のように対極のイメージを持つ人も少なくないだろう。
だが、エンジニアとアスリートは、ことキャリアの面においてはかなり似ている。
1つは、エンジニアの転職スパンの短さで、特にソフトウェアエンジニアについては、3〜5年のスパンで転職を繰り返すことも珍しくないそうだ。
また、実力主義的なところも似ている。エンジニアも、市場の中で客観的に評価される経験やスキルを活用してキャリアアップや年収アップを目指す。この点において、日本の従来型のメンバーシップ型雇用では、会社内で経験やスキルというクローズドなものが評価の材料になることが多いようだ。(近年では徐々にジョブ型への移行が行われているという動きはあるだろうが)
また、エンジニアをアスリートに例えるなら、キャリア選択における最適解は、特に若手のうちは「試合に出れる環境に身を置く」ということになるのだと思う。
したがって、僕も当分は試合に出れる環境に身を置くことを意識しながらキャリア選択をしていきたいと思っている。
就活終わったー
就活終わったー、じゃないよ。
むしろ、ここからがスタート。
ということで気持ちを引き締めてこれからも頑張る。
エンジニアになるからには、エンジニアらしいキャリア体験がしてみたいし、そのためには明確な目的意識と、強固な習慣、それを達成するための体力が必要だと思っている。
残りの大学生活では、研究やアルバイトに精を出しつつ、将来について今一度じっくり考える時期にしたい。
情報系研究における実験環境の構築について
情報系学生は研究において、どのようにメインのプログラムを実行して、そのデータを取得し、解析しているのだろうか。
例えば、プログラムの実行においては、1つのpythonファイル(main.py)で様々な3rdパーティライブラリをインポートし、最終的な実験結果はcsvファイルに出力するのではないか。また、実験における条件はmain.pyの中にべた書きするのが一番楽ちんだと思う。
データの解析ではcsvファイルをエクセルで図評価するか、pythonのmatplotlib図表を作成している人が多いだろうか。
さて、研究にあたって、特に私の研究分野はアルゴリズムの性能向上であり、理論系である。研究において、アルゴリズムの中身を書く部分も重要なのだが、むしろそれ以外の部分が研究における精神的ハードルになっていると感じる。
具体的には
・実験データの可視化
・実験データのフォーマット・どのデータが必要か
・どの条件を変更すべきか、また、それに伴うコードの変更
・モジュール、レイヤーの密結合による保守性、可読性の低さ
「情報系研究における実験環境の構築」について、体系的に述べられた記事はざっと調べた感じでは見当たらなかった。
そもそも、「情報系研究における実験環境」を分解して考えると以下のように考えられそうだ
・定数:ハードウェア、ベースとなるフレームワーク、対象とする問題領域
・変数:フレームワーク内の個別手法、パラメータ、使用するデータ、対象の問題の種類
・実行:実験を実行する部分、定数と変数を元に処理を行い、出力する
・出力:得られた実験データ。生のデータに近い。(使い道がありそうなデータは全て記録するのが望ましい)
・分析:得られた実験データにおける統計的な分析結果や、figureとして見やすい形式に加工したもの。
これらを適切な結合度になるようにプログラムを書けば、研究の効率化ができそうだ。
「研究における実験環境」は入力と出力、内部条件からなる1つのシステムであり、プログラミングやシステム開発のベストプラクティス的なものを敷衍して応用するのがベターだろうが、「研究における実験環境」にフォーカスして良い環境構築を行うための工夫や知恵があっても良いと思う。
量子チップを卑近に例えてみる
2024年12月9日、googleが新量子チップ「Willlow」を発表した。
その性能は(数字上は)凄まじく、古典チップでは10^25年かかる計算が5分未満で実行可能になるとのこと。
古典チップ
量子チップの雰囲気を掴むためには、古典チップについて知っておく必要がある。
古典チップは、電流(電子の移動)と、論理ゲートからなる。細かいことはともかく、チップ状のサーキットを電子が流れることによって計算されているのだ。
量子チップ
対して量子チップは趣がだいぶ異なる。量子チップは「量子の不確実性」「量子の干渉」「波の重ね合わせ」などを持ちいて計算を行っている。一見すると、何を言っているのかわからないし、正確な理解のためには量子力学の理解が必須である。したがって、物理的なイメージから理解しようとせず、たとえ話で考えてみることにする。
私の思いつきだが、量子チップの仕組みは「合議制による意思決定」に例えるとしっくりくる。
合議制は、複数の人間が確率的に発言を行い、議長を中心としてそれらの発言をまとめ上げ、、全体の意思を一致していくプロセスである。
量子チップのシステムをこれに例えると、
・量子ビット=人間
・議長=量子アルゴリズム
・出力=全体の意思
というふうに対応する。
量子ビットは0か1を確立的にとる。ここには不確定性が存在しているのみで、単体では計算機として機能しない。そこで、これらの量子ビットを複数用意する。そうすると、これらの確率は重ね合わせ、干渉によって、一つの解に収束する。ここにおいて、個別の量子ビットの動作を完全に制御することはできないが、適切な量子アルゴリズムを設計することで、個々の量子ビットを重ね合わせて全体の動作を制御し、最終的な出力を得るというイメージ。
とにかく、個別の量子はそれぞれ不確定・確率的で、それらを適切な制御方法で重ね合わせれば全体としては所望の動作が得られるよね!っていうイメージで理解してみた。
通常配列と連想配列の併用による時間計算量削減
はじめに
ABC343-D問題を解いていたら、通常配列と連想配列を併用して解く問題が登場した。
素朴に考えれば、データは1つの形式で持っておく方が自然だし、同じ対象を2つの形式で保持すれば、両者の間に競合が発生し内容に実装にナイーブになる必要がある。
通常配列 vs 連想配列
通常配列は、順番が重要なデータに対して使用される。ランダムアクセスがO(1)だが、追加削除がO(N)である。とにかく、前から順番に値が入るので、順番が重要なデータは通常配列として持つのが自然。
連想配列は、データの順番が重要では無い場合に使用すると有効。追加や削除、検索はO(1)で行える。
対象に応じてこれらの特性を活かすのが大事で、他にもデータ構造は複数あるし、言語によっても違う。ただ、「順序が必要かどうか」は、データ構造を考える上で広く使える味方だと思う。
「連結リスト+連想配列」の実例
一見不自然で素朴では無い気がしたこの実装、実は現実問題に対しても使われている。
LRUというキャッシュアルゴリズムでは、最近使われていない、つまり最後に使われてから最も時間が経過しているものを削除するという方法でキャッシュを管理する。
ここで、連想配列は idから履歴のデータを参照するために、連結リストは、時系列順にでデータを保持するために、という別々の用途で使用されているらしい。
keita-matsushita.hatenablog.com