データベースを自分で構築する!難易度自在で深い学びと楽しさを手に入れよう
引用元:https://news.ycombinator.com/item?id=45657827
この記事の元ネタは『Designing Data-Intensive Applications』って本だよ。O’Reillyのこのページで確認できるよ。
https://www.oreilly.com/library/view/designing-data-intensiv…
この記事は魅力的に書かれてるけど、データベースの定義に異論があるな。「永続的なデータ保存と効率的な検索」は、ファイルフォーマットかアクセスメソッドって呼ばれることが多いよ。俺が思うに、データベースのホントのキモは「クエリ評価」だね。PrologやSQLみたいな言語で質問を表現して、インデックスやマテリアライズドビューなんかで効率的に答えることだよ。dbmやISAMはデータベースじゃないけど、SQLiteのインメモリはデータベースだ。
「永続的にデータを保存して、効率的に検索する」っていう定義の「効率的に」って言葉、見落としてるんじゃない?
いや、見落としてないよ。多分、お前がISAMとかdbmが何かわかってないから、そう思うんだろうな。
数ヶ月前にErlangで自分なりのDBを組んだよ。Bitcaskとriak_coreは使ったけど、レプリケーションや耐障害性は自分でやった。めっちゃ楽しかったな。KVデータベースは、JSONのシリアライズ/デシリアライズから始めて、最終的にちゃんとしたレプリケートされたDBを作って、簡単なクエリ言語まで作ったんだ。難易度を自在に変えられるのがいいよ。
リポジトリとかある?プロダクションレディじゃなくてもいいよ。mnesiaやCouchDBと比べて、どうやってレプリケーションを処理したのか興味あるんだ。特にErlangがJSONをネイティブサポートした今、どうしてるか知りたいな。
ごめん、プライベートリポジトリなんだ。製品として売る野望があって、まだ諦めてないからね。でも、ほとんどの概念はオープンソースのriak_coreから来てるよ。ここだよ。
https://github.com/OpenRiak/riak_core
この記事のデザインと例がすごくいいね。めちゃくちゃ読みやすいよ。こういう演習はホント楽しいし、ゼロから何かを始めるのは自分の知識がどれだけあるか試される、いい機会になるんだ。
最初は「自分でDB作るな、KVデータベースも使うな、SQL使え」って即座に却下したくなったんだ。でも、よく考えたら、俺がそう言うのは、SQLを避けるために自分でDB作ったりKVデータベース使ったりして、結局SQLをひどく再発明してた経験があるからだなって。この経験は学ぶ価値があるかもしれないね。
ちょっとした批判だけど、Lorem ipsumの例を使ってるのが唯一気になるな。あれを見ると読み飛ばしたくなるから、現実的なデータの方が好きだよ。それ以外は、ホントにクールな記事だね。
このリンクにあるexampledb.pyってやつ、面白いかもよ。SQL文を生成してくれて、顧客や商品のデータを挿入してくれるんだ。テーブルも作ってくれるよ。会計の例だからちょっとつまんないけど、ランダムなデータが良い味出してるね。今はLLMがあるから、もっと面白いデータ作れるかもな。
http://canonical.org/~kragen/sw/dev3/exampledb.py
俺も同じこと言おうと思ってたんだ。Lorem Ipsumだとデータが区別しにくいよね。動的な例だとテキスト生成が必要なのはわかるけど、ラテン語はベストな選択じゃないと思うな。記事は良かったよ、ありがとう!
fooとかbarを例に使われると、俺も同じように感じるよ。
誰かに、動物を例に使うのがいいってアドバイスもらったよ。できればサイズとか色が全然違う動物がいいって。そうするとみんなすぐにイメージできて、記憶に残るんだって。
記事はすごくいいんだけど、ハッシュテーブルがなんで高速で定数時間検索なのか、もっと詳しく説明してほしいな。インデックスがDBを速くする理由の核心だからさ。
データベースを作るなら、この無料のオンラインブックもおすすめだよ!
https://build-your-own.org/database/
たしか1年くらい前だったかな、ここで誰かがbashの例でデータベースの概念を説明してる記事を見たんだけど(“bashでDBを書く”みたいなやつ)、どこにも見当たらないんだよね。誰か知ってる人いる?
元記事の投稿者がブログで使ってるフレームワークはこれだよ。
https://github.com/nandanmen/NotANumber
LSM treesはDynamoDBの基盤データ構造だけど、8000万rpsを捌けるってのはちょっと誤解を招くかな。LSMはノードレベルのストレージエンジンで使われてるだけで、分散システム全体でどうスケールするかは説明してないもんね。昔のDynamoはBerkeleyDB(B-treeかLSM)だったけど、2012年の論文からは完全にLSMベースになったって聞いたよ。
「こうしなきゃ」って考えると、やることが多すぎて頭がパンクしちゃうから、「maker」になれないんだよね。この記事も最初は面白いんだけど、どんどんストレスに感じてくる。汎用データベースを作りたいわけじゃないけど、もっと小さなタスクでも考えすぎちゃうんだ。
俺も全く同じ問題を抱えてたけど、最近は「信じること」が大事だって気づいて、かなり良くなったんだ。成功すると信じれば、問題は一時的な障害になる。でも失敗するって信じちゃうと、どんな問題も絶望的なものに見えちゃうからね。
君の意見は分かるんだけど、細かい情報を読むのと、それに深く関わるのは違うって思うんだ。もし本当にその要件を満たそうとしてるなら、すごく夢中になれるだろうけど、そうでなければ読み飛ばしちゃうよね。今週引っ越しなんだけど、考えるのはすっごく大変なのに、実際にやるのはそれほどでもないんだよ。
ADHDの可能性を考えたことある?
データベースが内部でどう動くのか、ビジュアルも使ってすごく分かりやすく説明されてるね。筆者は素晴らしい先生だわ。
この「first principles」アプローチで説明するやり方が本当に大好きだよ。これを読み進めると、その時々で何を解決すべき問題で、それがどんな別の問題を引き起こすのかを理解できて、最終的に納得できる解決策にたどり着けるんだ。
もし筆者がこれ読んでたら、サイトにRSSフィードを追加してくれない?Feedlyに追加したいんだけど。
Kill The Newsletterってサービスが、メール配信しかしてないサイトをフォローするのにすごく便利だよ。https://kill-the-newsletter.com/
omg天才じゃん、笑。こんなにシンプルで賢いユーティリティってすごいな。これ、Chrome拡張機能作ってみようかな。
これ、追加するのめっちゃ楽しみだったんだ!全体的にプロダクションの質が高いのに、見つからなくてマジでびっくりしたよ。
もっとコメントを表示(1)
大学の卒業制作の一つで、C言語で基本的なデータベースを設計・プログラミングしたんだ。20年経った今でも、それがプロジェクトの中で一番面白かったと思ってるよ。
>問題:データを永続的に保存し、後で効率的に参照するにはどうすればいいか?
ってあるけど、実際問題としてトランザクションがないなら、まだデータベースとは言えないと思うな。
多くのデータベースはそうは思わないだろうね。
代わりに2フェーズコミットを実装できるよ。データ管理でちょっと計画が必要だけど、こっちの方がずっとエレガントでスケールすると思うな。DBトランザクションは高価で無駄に複雑だよ。
シンプルな2フェーズコミットなら、最初は全レコードを’保留中’としてマークして、関連行が全て挿入されたら’確定済み’に更新すればOK。タイムスタンプを記録すれば再開場所が分かるしね。以前、IDをハッシュ化して特定のプロセスにマッピングし、複数プロセスが並行して決済するシステムを作ったんだけど、これめっちゃスケールしたよ。
>’代わりに2フェーズコミットを実装できる’ってあるけど、2フェーズコミットはシステムが分散している時のトランザクション実装の特定の方法だよ。’代わりに’って話じゃないよね。
システムは分散型である必要はないよ。一般的に、レコードの挿入とそれらの決済を分けるだけでいいんだ。
何か良いことを見つけたかもしれないね。
でも、それってウェブスケールだよ!
「Sorting in Practice」セクションの最初の例が壊れてるみたいだよ。テキストではインメモリでソートしてからディスクに書き出すって言ってるのに、例だとディスクに書き出す時にリストが未ソートになっちゃうんだ。追記:Recapセクションのflush例(2番目のやつ)も同じことをしてるね。そこではレコードがソート順にファイルに書き込まれるって書いてあるのに。
この4週間くらいずっとtriple store作りに時間を費やしてたんだ!この記事がもっと早く出てたらよかったな。ここに書いてあるいくつかの洞察は、俺が理解するのにかなり時間がかかったからね :)
すごく良い記事だね。俺は開発者の活動を、各開発者がキーでコミットがバリューの時系列キーバリューシステムとしてモデリングしてるんだ。
同じ問題に直面したよ:ログがすぐ増える、インデックスが重くなる、範囲クエリが遅くなる。
セグメントを圧縮する時、何を捨てるかどう決めてる?鮮度と保持のバランスって難しいよね。
データ量はどのくらいあるの?俺は12年分の開発データを持ってるけど、レポートは数秒、いやミリ秒単位で生成されるよ。キーパターンはどうなってる?キー設計の問題に聞こえるけど。
素晴らしい投稿だし、ウェブサイトも美しいね。memtableが満杯になった時に起こるflush操作で少し混乱しちゃったんだ。新しいオンディスクセグメントが作成されるって簡単なメモがあれば助かるかな。最後のrecapでもセグメンテーションが触れられてないみたい。
最後の方で少し曖昧になるね。インデックスは別々の(部分的な)エンティティとして描かれてるけど、これらは全部別々のファイルに保存するのかな?もしそうなら、レコードを検索するためにそれら全部を開く必要があるの?
D.B. Cooperにインスパイアされたシンプルなキーバリューストアがこれだよ。~/bin/cooper-db-setと~/bin/cooper-db-getのシェルスクリプトが書いてあるね。キーとバリューを/dev/nullに書き込むってジョークかな。
/dev/nullは再起動後も永続的だしキャッシュにも優しいから、バッチリカバーしてくれるよ。
もうすでに、アクセス集中しすぎてダウンしちゃったみたいだね。
このブログ記事のレイアウト、俺だけがめちゃくちゃ気に入ってるのかな?
インタラクティブなのは素晴らしいけど、これ『Designing Data-Intensive Applications』から完全にパクってるじゃん。文字通り全部の内容が第3章のインタラクティブ版だよ。引用元を明記すべきじゃない?
やあ!記事の著者だよ。文章自体は俺自身の言葉なんだけど、論理構造と例は確かにDDIAの第3章を基にしてたんだ。これは俺のミスだね。サイトは適切な引用元表記に更新されたよ。
ありがとう、これをスレッドのトップテキストに追加したよ。
おいおい、それじゃ不十分だろ。a) 親コメントは“丸パクリ”って言ってたのに、君は“インスパイアされた”って薄めてるけど、どっちなの? b) HNでこの投稿を編集しただけで、実際の元の記事にはまだ引用元が一切書かれてないよ。
うん、その通りだね。記事の出版社と連絡を取ったよ。コミュニケーションの詳細は開示できないけど、ヘッダーテキストを更新したし(最初のコメントの疑惑を見た時に投稿した内容に)、投稿の評価も下げたよ。
“データベースは一つの問題を解決するために作られた:
“データを永続的に保存し、後で効率的に検索するにはどうすればいいか?””ってあるけど、これって二つの問題じゃないの?
俺、いつもライトオンリーなデータベースを出荷したいと思ってたんだ。超高速でね。
データを永続的に保存して、効率的に検索できるようにする*ってのは、一つの問題に聞こえるよ。
記事の文脈が分からないけど、きっと選択肢が二つあるって話だね。
それ、ログ記録にはかなり役立ちそうだね。
もし後で復元できないなら、それは永続性があるとは言えないよ。
過去のメモリ状態をどう再構築するかが根本的な問題だよね。ストレージや検索効率、信頼性、セキュリティとか、色んな要素の優先順位がデータベース設計の鍵になるんだ。
もっとコメントを表示(2)
これって、一方通行のエレベーターみたいなもんだね。
メッセージを瓶に入れて、一番都合の良いブラックホールにポイっと投げ込む感じだね。
EventStoreDBって、だいたいこんな感じの仕組みだよね。
データの完全削除は、データファイルを書き直す scavenge の時だけだよ。
ブラックホールに入れたら、瓶が復元不能なほど圧縮されちゃうんじゃないの?
あれはジョークだと思うよ。君は追記専用のLSM treeデータベースみたいに解釈したようだけど、GPは読み込みなしの書き込み専用、つまり echo $data > /dev/null みたいに言いたかったんじゃないかな。
もし書き込み専用で、読み込みが全然発生しないなら、/dev/nullに書き込んでも全然困らないよね。
過去のメモリ状態を再構築するってどうやるの?それが根本的な問題だよね。でも、過去のメモリ状態の再構築って、データベース層で対応しなきゃいけない要件になることって、めったにないし、ほぼないんじゃないかな。
80年代にさ、うちの大学の教授が「ライトオンリーメモリ」っていうコンセプトのプレゼンを、シンポジウムで採択されたんだってさ。いい時代だったな、マジで。
ただデータを保存したいだけならファイルで十分だよ。でも検索が面倒だし効率悪いよね。永続ストレージが解決済みだとして、データベースの存在意義はデータを効率的に検索することにあるって言える。永続ストレージは前提だけど、それが発明された理由なんだよ。
もう少し詳しく説明してくれない?普通のCRUDアプリだと、データを永続化して後でロードできるようにするモデルがあるよね。分析目的でデータを取り込むこともあるだろうけど、それは「過去のメモリ状態を再構築する」ってのにはあまり当てはまらない気がするな。
それは二つの小さい問題を含む一つの問題だけど、本当に難しいのは(三つ目の問題だとして)それらを一つにまとめることだよ。もし君がその二つの問題を別々に解決することに限定したら、役に立つデータベースは作れないだろうね。
「データを永続的に保存する」ってのは、「検索できる」ってことだよね。だって、検索できなかったら永続的に保存されてるかなんてわからないでしょ。ただ、「効率的に」って部分は、別の問題として考えてもいいと思うよ。
そんなに低いところから数えるの、忘れちゃったよ。ゼロゼロ — https://www.youtube.com/watch?v=3t6L-FlfeaI
「特定のやり方でデータを保存する」ってのはどうかな。そっちの方が一つの問題っぽいし、もっと大きな問題空間を含んでる気がするけどね。
バックアップにも役立つよ、ただし復元する必要がない限りね。
問題は2つに分けられるって言っても、実際は1つだよ。それはね、「未知のクライアントとアクセスパターンが、ACIDに則って、競合をブロックせずに、高速にデータを永続保存して効率的に検索できる方法」っていう問題なんだ。んで、SQLを追加すると…(痛っ!)って感じ。
この指摘がHacker Newsで真剣な議論を呼んでるのが面白いね。俺も1つか2つか考えちゃう。「AとB」ってあるから2つに見えるけど、同じコインの裏表にも思える。哲学と屁理屈の境目は微妙だね。
データベースが解決すべき問題がもし2つなら、「データを永続的に保存する」ってのもそうなる。でも、それはデータベース以前から解決済みだよね。「データを効率的に検索できるように保存する」ってのが1つの問題って言う方が公平じゃないかな?
「データを永続的に保存して、後で効率的に検索する方法?」
「それって2つの問題じゃないの?」
ライトオンリーのデータベースを作るならね。それなら/dev/nullに書き込むだけでいいじゃん。
じゃあ、寝る前に読むのにちょうど良いね。
人々が入れるようにするデータベースだね。出口は後で考えるとして、別のフロアから出るのはストレッチゴールにしよう。
それか、ただのパタノスターだね。