DBにおけるインデックス付与について
データベースを扱うとき、インデックスの付け方について記載する。併せて、GORMでどのように扱うかも記載する。
取り扱うもの
- データベースのインデックス
- GORMのインデックス
- 検索が遅いときの調査方法
カーディナリ(濃度)とは?
ざっくりいうと、重複しないデータの量のこと。
(絶対量ではなく、データを相対的に見たときの高低が重要となる)
この例だと・・・
- "性別"は、カーディナリが低い(2種類)
"名前"は、カーディナリが高い(名字の種類だけ)
性別 名前 男 山田 女 佐藤 女 田中 〜 〜
インデックス付与の考え方
結論として・・・
- カーディナリの高い項目に付与すること
- 複合インデックスは、カーディナリの高い順に付与すること
そもそも、なぜインデックスが必要なの?
検索速度が速くなるから。
DB内部では、検索しやすい並び順にして、その並び順を保持する。最適化された並び順に対して、2分木探索など適用すれば、検索が高速になる。
この例だと・・・
保存されているデータ
性別 名前 男 山田 女 佐藤 女 田中 〜 〜 DBの中では、名前を昇順として並び順を保持する
性別 名前 女 佐藤 女 田中 男 山田 〜 〜
複合インデックスってなに?
参考ページがとてもわかり易いので割愛する。
プライマリキーインデックスとインデックスの違いは?
参考ページがとてもわかり易いので割愛する。
GORMにおけるインデックス付与
GORMでは、構造体タグとしてインデックスを与えられる。 インデックス名称は任意だけれど、命名規則として「IXカラム1カラム2」とするのが良いらしい。
ケース1:インデックス2つ
この場合、
Role
とAddres
は別々のインデックスとなる
type User struct { Email string Role string `gorm:"index:IX_role"` Num int Address string `gorm:"index:IX_address"` }
ケース2:複合インデックス1つ
この場合、
Role
とAddress
が複合インデックスとなる
type User struct { Email string Role string `gorm:"index:IX_role_address"` Num int Address string `gorm:"index:IX_role_address"` }
複合インデックスの優先順位はどうなるの?
結論としては・・・
DBに保持されるカラムの順番で優先される。
この場合だと・・・
type User struct { Email string Role string `gorm:"index:IX_role_address"` //優先度高 Num int Address string `gorm:"index:IX_role_address"` //優先度低 }
この構造体だと、DBへ保存したとき、以下のようなテーブルとなるため、Role
の優先順位が高くなる。
Role | Num | Address | |
---|---|---|---|
~ | IX_role_address(優先) | ~ | IX_role_address |
詳細は、参考ページへ!
検索が遅いときの原因の調査方法について
実行結果の読み方は、参考ページを参照のこと。
explainを実行する
explain select * from tableName;
実行結果を解析する