goroumaru41gou

遊んでいる中でインプットした内容をアウトプットする場

DBにおけるインデックス付与について

データベースを扱うとき、インデックスの付け方について記載する。併せて、GORMでどのように扱うかも記載する。

取り扱うもの

  • データベースのインデックス
  • GORMのインデックス
  • 検索が遅いときの調査方法

カーディナリ(濃度)とは?

ざっくりいうと、重複しないデータの量のこと。

(絶対量ではなく、データを相対的に見たときの高低が重要となる)

この例だと・・・

  • "性別"は、カーディナリが低い(2種類)
  • "名前"は、カーディナリが高い(名字の種類だけ)

    性別 名前
    山田
    佐藤
    田中

インデックス付与の考え方

結論として・・・

  • カーディナリの高い項目に付与すること
  • 複合インデックスは、カーディナリの高い順に付与すること

そもそも、なぜインデックスが必要なの?

検索速度が速くなるから。

DB内部では、検索しやすい並び順にして、その並び順を保持する。最適化された並び順に対して、2分木探索など適用すれば、検索が高速になる。

この例だと・・・

  • 保存されているデータ

    性別 名前
    山田
    佐藤
    田中
  • DBの中では、名前を昇順として並び順を保持する

    性別 名前
    佐藤
    田中
    山田

複合インデックスってなに?

参考ページがとてもわかり易いので割愛する。

プライマリキーインデックスとインデックスの違いは?

参考ページがとてもわかり易いので割愛する。

GORMにおけるインデックス付与

GORMでは、構造体タグとしてインデックスを与えられる。 インデックス名称は任意だけれど、命名規則として「IXカラム1カラム2」とするのが良いらしい。

  • ケース1:インデックス2つ

    この場合、RoleAddresは別々のインデックスとなる

type User struct {
  Email        string
  Role         string  `gorm:"index:IX_role"`
  Num          int     
  Address      string  `gorm:"index:IX_address"`
}
  • ケース2:複合インデックス1つ

    この場合、RoleAddressが複合インデックスとなる

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の優先順位が高くなる。

Email Role Num Address
~ IX_role_address(優先) ~ IX_role_address

詳細は、参考ページへ!

検索が遅いときの原因の調査方法について

実行結果の読み方は、参考ページを参照のこと。

  • explainを実行する explain select * from tableName;

  • 実行結果を解析する

参考

カーディナリとインデックス付与の関係について

インデックスの効果とは?

複合インデックスの適用順と有効な検索方法

MySQLのexplainの読み方