はじめに
プログラミングをRailsから始めた僕なのですが、Railsのアクティブレコード(Active Record)の優しさに甘やかされDBのことをなんとなくしか理解していませんでした。。。(Railsをディスりたいわけじゃなく、単純に)
インデックスとかトランザクションとか、、、なんとなく言葉では知ってたり雰囲気は知ってるけど、正直なにしてるかよくわからん、、、
と思っていたのですが、最近割と就活をちゃんとやっているとその辺の基礎のことをめちゃめちゃ聞かれることが多くて、その質問をされるたびにめちゃめちゃ萎えるので一気に勉強して備忘録としても残しちゃおう!っていうのがこの記事が生産された理由となっておりますw
インデックス(早く検索できるようにするやつ)
ざっくりインデックスって?
イメージの広辞苑の目次みたいなものだと思ってもらえるといいと思います!
例えば辞書で「プログラミング」って調べようと思った時に辞書を1ページ目から引かないと思います
多分「は」の行まで飛ばしてそこからめくっていくと思うんですけど、ざっくりとはそんな感じです
じゃあ、カラムの全てにインデックス貼ったほうがいいんじゃないの?って言う割と当たり前の疑問があると思うのですがそれはダメです。
それについては↓で説明します。
ちゃんとインデックスを考える
ID | name | age |
---|---|---|
1 | kimura | 20 |
2 | anndo | 35 |
3 | sato | 24 |
4 | nakamuura | 18 |
例えば上記のようなUserテーブルがあるとします。 | ||
そこでUserのnameカラムにインデックスを貼ると以下のようなテーブルが通常のテーブルとは別に作成されます。 |
ID | name |
---|---|
2 | anndo |
1 | kimura |
4 | nakamura |
3 | sato |
もともとあったUserテーブルとは異なり、カラムがIDとNameのみとなり、nameカラムの値も昇順(a→zの順番)に並び替えてデータを保存しています。
インデックスはこれを用いることで検索を早くしているのです。
ここで
カラムの全てにインデックス貼ったほうがいいんじゃないの?
って言う疑問に対して
「それはダメだよ!」
って言うための説明ができます。
つまりインデックスをはると言うことは通常テーブルとは別にインデックス用ののテーブルとの2箇所にテーブルに対してデータが保存することになります。なのでインデックスは検索の時は早くなるのですが、データを2箇所に保存する分処理が多くなってしまうという欠点があります。
なので、全てにインデックスはるのはよくないことです。(もちろんケースバイケースであると言うことは前提の上でですが)
一般的にインデックスを貼ったほうがいい条件について
- 検索対象の行数が多い
- 検索対象表において検索項目の重複や重なりが少ない(例:外部キーなど)
- 検索対象の更新が少ない
- 検索対象の追加・削除が少ない
この4項目がインデックスをはる条件になってます(なんども言いますが、ケースバイケースではあります😓)
トランザクション
ざっくりトランザクションって?
親のA子さんは子供のB君に1000円おこずかいをあげようとしました
その時データベース上では、、、- A子さんの財布から1000円減らす処理
- Bくんの財布に1000円増やす処理
しかしなにかしらの理由でAさんの財布から1000円減らす処理はすることはできましたが、B君の財布に1000円増やすことができなくなりました。
この時1000円はデータベース的には消えて無くなってしまっている状態です。(これはとてもまずい、、、)
1000円はどこにいったんだ〜!!!!
ここで登場するのがトランザクションです。
トランザクションっていうのは今回の場合
- A子さんの財布から1000円減らす処理
- Bくんの財布に1000円増やす処理
という2つの関連する処理が正確に実行が完了されなかった場合
そもそも取引自体が無かったことにするというものです
つまり、A子さんの財布からは1000円は減りませんし、B君の財布にも1000円増えることはありません。
これがトランザクションです。
ちゃんトランザクションを考える
ざっくりとトランザクションがわかったところで具体的にはどうやってトランザクションが行われているのでしょうか?
トランザクションには、、、
- 一連の処理が正常に完了し処理を確定させる
COMMIT
- 何かしらの異常があったときに処理をなかったことにする
ROLLBACK
の2つが存在します。
こんな感じでトランザクションがスタート→コミットされていきます
ROLLBACKが走り、処理をのものがなかったことになります。
これらの機能は
ACID特性
と呼ばれ標準規格となっています
1. 原子性(Atomicity)
トランザクションが終わった時に、そこに含まれていた更新処理は全て実行されるか、全て実行されない状態で終わることを保証する性質。
COMMITで更新が確定されるか、ROLLBACKで元に戻されるかの二択というイメージです。
2. 一貫性(Consistency)
トランザクションに含まれる処理はそれぞれの制約を満たすという性質。
トランザクションの途中で制約違反の処理があった場合、処理を中断してトランザクション実行前に戻すことでデータの一貫性が保たれる。そのため、あるデータは更新されているが、その他のデータは更新されないというような状態を持たないということ。
3. 独立性(Isolation)
あるトランザクションが実行中の場合、もう一方のその他のトランザクションの影響を受けないという性質。
トランザクション実行中に、その他のトランザクションがデータの更新を行ったとしても実行中のトランザクションはその更新結果の影響を受けないというイメージ。
4. 永続性(Durability)
トランザクションが完了した後、そのデータ状態が保存され失われることは無いという性質。
この性質の保証のために、一般的にはトランザクションのログを記録しておき、障害が起きた場合はログを使用して障害発生前の状態に復旧する。
デッドロック
ざっくりデッドロックって?
いつもおこずかいをもらってたB君はたまには自分もA子さんにお返しをしようと考えていました。しかし、タイミング悪くA子さんとBくんは全く同じタイミングでお互いにお金を渡そうとしてしまいました。
現実の世界なら普通に1000円を交換すればいいのですが、、、
これがデータベース上で起こってしまうと大変です、、、なぜ大変なのかというと、、、
上の図のようにAさんの処理もBさんの処理も両方ともお互いの処理の終了を待っているせいで処理が進まなくなってしまっている状態のことを指します。
#まとめ
ざっくりと、インデックス・トランザクション・デッドロックをまとめてみましたが、それぞれDBを触る時の基礎知識となっているのでまずはざっくりベースで覚えておくといいと思います