完全一致の場合、中間テーブルの処理は高速化するか。

先日、データを正規化しない場合でも、中間テーブルを作成する方がいいのかとういう記事を書きました。

https://qiita.com/The_Past_of_Dice/items/b6c5aae8665dde6561d8

その後、「そういえば、完全一致だとまた挙動が変わるのかな」と疑問に思ったので、完全一致で今回はテストをしてみました。

注：ソースコードは[前回の記事](https://qiita.com/The_Past_of_Dice/items/b6c5aae8665dde6561d8)を参考にしてください。

## 実際にテスト

前回同様、企業のデータベースというテーマでデータを作成します。
作成した結果は下記のようになりました。

```
企業数: 3,000,000
タグ数: 20
1企業あたりのタグ数:
    平均: 1.029
    標準偏差: 0.172
    最頻値: 1
    中央値: 1.0
```

完全一致検索を10回行ったテスト結果が下記のようになっています。
検索での該当件数が多い方と、中間テーブルがあることでデータの取得が早くなります。


| 該当企業数  | 検索方法                      | 実行回数 | 平均処理時間 (秒) | 最小処理時間 (秒) | 最大処理時間 (秒) |
|--------|-----------------------------|--------|----------------|----------------|----------------|
| 17559  | 中間テーブルなし     | 10     | 0.08341        | 0.07068        | 0.14418        |
| 17559  | 中間テーブルあり   | 10     | 0.10514        | 0.09418        | 0.15091        |
| 8806   | 中間テーブルなし     | 10     | 0.04489        | 0.04064        | 0.06138        |
| 8806   | 中間テーブルあり   | 10     | 0.04247        | 0.03999        | 0.04921        |
| 20257  | 中間テーブルなし     | 10     | 0.08072        | 0.07658        | 0.08768        |
| 20257  | 中間テーブルあり   | 10     | 0.11412        | 0.10791        | 0.11777        |

分かりやすく平均値だけを比較してみましょう。
検索での該当件数が8806軒の時は、中間テーブルがない方が速くなっています。
この結果から、システムの仕様によっては中間テーブルがなくても良いのかもしれません。

### 平均処理時間の比較

| 企業数  | 中間テーブルなし(秒) | 中間テーブルあり (秒) | 差分 (秒) | 性能差 (%) |
|--------|-----------------------------|-----------------------------|---------|---------|
| 17559  | 0.08341    | 0.10514                      | 0.02173  | +20.67%  |
| 8806   | 0.04489    | 0.04247                      | -0.00242 | -5.39%  |
| 20257  | 0.08072    | 0.11412                      | 0.03340  | +29.26%  |


## 2回目のテスト

「検索該当件数が少なければ中間テーブルがない方が早い」ということを書きましたが、そもそものデータ量が多くて検索多少件数が増えると変わるかなと思ったので、追加でテストをしてみます。

```
企業数: 3,000,000
タグ数: 220
1企業あたりのタグ数:
    平均: 1.415
    標準偏差: 0.677
    最頻値: 1
    中央値: 1.0
```

企業数はそのままに、タグの数を増やしい１企業あたりに紐づくタグ数を増やしました。


| 企業数  | 検索方法                      | 実行回数 | 平均処理時間 (秒) | 最小処理時間 (秒) | 最大処理時間 (秒) |
|--------|-----------------------------|--------|----------------|----------------|----------------|
| 17559  | 中間テーブルなし     | 10     | 0.13674        | 0.12893        | 0.17512        |
| 17559  | 中間テーブルあり   | 10     | 0.10586        | 0.09892        | 0.12202        |
| 8806   | 中間テーブルなし     | 10     | 0.06965        | 0.06461        | 0.07695        |
| 8806   | 中間テーブルあり   | 10     | 0.06561        | 0.06283        | 0.07292        |
| 20257  | 中間テーブルなし     | 10     | 0.14182        | 0.13868        | 0.14882        |
| 20257  | 中間テーブルあり   | 10     | 0.11897        | 0.11430        | 0.12619        |

### 平均処理時間の比較

| 企業数  | 中間テーブルなし(秒) | 中間テーブルあり (秒) | 差分 (秒) | 性能差 (%) |
|--------|-----------------------------|-----------------------------|---------|-------------|
| 17559  | 0.13674  | 0.10586                      | 0.03088  | -22.58%   |
| 8806   | 0.06965 | 0.06561                      | 0.00404  | -6.16%    |
| 20257  | 0.14182  | 0.11897                      | 0.02285  | -19.21%   |

検索対象が増えた結果、検索該当件数が8806件でも中間テーブルありの方が処理が早くなりました。
データの全体量の影響もかなりあるようです。

## 結論

検索されるテーブルの情報量が増えると、中間テーブルがある方が処理が早くなる。
ただし一致する検索結果の数にもよる。

個人的にはデータを正規化しないが、一定の共通性がある場合
検索をするなら中間テーブルを作成する
検索をしないならリスト型で保存する

という感じがいいのではないかと思います。

データが増えすぎることを考えるとリスト型で1つのテーブルに入れてしまうと、新しい問題が起きるのでデータベースは奥が深いです。