---
# System prepended metadata

title: 2021/04/11 メンター相談
tags: [4月, メンター相談]

---

# 2021/04/11 メンター相談

###### tags: `メンター相談`,`4月`

## 120. テーブル設計時・インデックス付与時に、インデックスの存在をアナウンスされていますか？

それとも各人が、SQL作成時、インデックス有無を確認されていますか？

https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recJKpAfGWWSwal0L?blocks=hide

### 回答
- テーブル設計時・インデックス付与時にアナウンスしていない
    - PullRequest時にORMのマイグレーションファイルの変更分で認知
- ORMを基本的に使っている (例: Prisma, flyway (Java))
    - マイグレーションを作るたびにmigration.sqlが作られる ([Prisma Migrate](https://www.prisma.io/docs/concepts/components/prisma-migrate))
    - → マイグレーションの管理がしやすい
    - → **プルリクエストの段階で気づける**
- データベースに入って直接Create indexはやらず、宣言的に記述する
    - → 再現できるようになる
    - → indexの情報をgit管理できる
- 既存のテーブルに貼られたインデックスを確認する場合は、本番のDBに接続してSHOW INDEXして確認をする。

## 121. スロークエリログを出力するタイミングについて

- サービス運用時には常に出力している
- サービスのレスポンスが遅いと感じてから出力するように設定を行う

どちらを選択することが多いでしょうか？

### 前者のメリット

- 常にログが出ているので、いつでも遅いクエリを発見することが出来る。
- MySQLにスロークエリログを出力する設定を入れる必要がなくなるため、サービスを一時的に停止させる必要がなくなる。

### 後者のメリット

- レスポンスが遅いと感じてからのスロークエリログだけが出力されるので、余計なログがなく調査しやすい。

それぞれ上記のメリットがあると考えました。

https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recjemRtjayPuxHgG?blocks=hide


### 回答

- 今までのプロジェクトではずっと取っていた
- ローンチした直後はしきい値を低く設定し、多めにログを取得
    - ローンチした直後はトラフィックがそこまでないため、問題にならない
    - 常時ONにしておき、負荷を監視しながらしきい値を調整していくのが良い
- その後、安定してきたら徐々にしきい値を上げていく
- `long_query_time` を0秒にするのは基本的にやらない (負荷が高すぎるので)
- レスポンスが遅いと感じた時には対処するのが遅いので、その前に気が付ける状態にしておく。
    - DB負荷が高い時点でログ出力を追加すると、更にDBの負荷が高くなりレスポンスが遅くなる

### 動的な変数・静的な変数

- MySQLは動的な変数と静的な変数がある
- スロークエリは動的な変数なので、サーバーの再起動などなくても反映されるはず
- 動的な変数は、セッションに依存している
    - → コンソールを起動し直したら反映される
    - → 次のコネクションから反映される
- しかし、動的な変数はあまり設定しない (変更が残らないので)
- 基本はmyconfを変更して、レビュー・確認を行う
    - その後、夜中に変更・再起動していた

### 余談 (宣言的・手続き的について)

- 宣言的 (Declarative)
    - テストしやすい、何度でも状況を再現できる、バージョンコントロールできる
- 手続き的
    - 毎回コンソールで入力する。コマンドが残らないので保守し辛い。
- 例: AWS
    - コンソールポチポチもできるが、、、
    - Teraformによる宣言的な手法が良い
- 宣言的のほうが保守しやすくなるので、流行り
- React: 宣言的, JQuery: 手続き的 (=負債を作りやすい)
- 関数型も宣言的

## 122. MySQL、PostgreSQL、それ以外だと、どのデータベースが好き、もしくはよく選択することが多いでしょうか？

また、何を基準に選択されているのか意識していることがあれば教えて頂きたいです。

https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recxw0VmLB8yHl4eB?blocks=hide

### 回答

- 基本的にはMySQLを使うことが多い
    - 組み込み系でよく使われることが多い。
    - PostgreSQLに比べて、メモリを消費し辛い。
    - 必要なところだけ機能があって、使いやすい。
- 必要なときはPostgreSQL
    - マルチテナントにしたいとき (row level security を使う)
    - マテリアルビューを使いたいとき
        - > SQLの結果をテーブルとして保持する仕組み
        - [3分でわかるマテリアライズド・ビュー -使い所と問題点を考える](https://qiita.com/wanko5296/items/61c3e6ec4561b26beb5c)
- マルチテナント
    - row level security
        - DBとのコネクションを張るときに値を設定することが出来る。
        - SaaSを作るときに嬉しい
    - SaaSはマルチテナントアーキテクチャになりやすい
    - データを企業ごとに分けたい
        - 特定のスキーマを共有するが、カラムにその企業のID(tenantId)を振る
    - ![](https://i.imgur.com/p5QP5tQ.jpg)
    - tenantIdで絞りこんだ上で、企業のデータを取得する
        - よくある事故: where句の絞り込みでtenantIdを書き忘れ、顧客の情報が漏れることによる重大障害。 -> whereを書き忘れを絶対に避けたい。
    - row level security を用いるとtenantIdによる絞り込みを強制出来る。
- [SmartHRの例](https://tech.smarthr.jp/entry/2018/04/06/100000)
    - データベースをテナント毎に作る
        - 堅牢なデータ管理が出来る
    - テナント毎にマイグレーションを実行する必要があるため、時間が掛かる
        - カラムにテナントを指定するように戻した(row level security)
- マテリアルビュー
    - PostgreSQLにはマテリアルビューがある
    - ビューを実データとして保存しておける (高速)


- 松原さん推しの[マルチテナントサービスを作るときに必読に近い良スライド](https://speakerdeck.com/purintai/builderscon-2018)
### その他

- 地理情報、座標検索はPostgreSQLのほうが優れているという噂
- JOINのアルゴリズムについて
    - MySQLはnested loop joinしかない
    - PostgreSQLは三種類選べる
    - → 複雑な集計(JOIN)をする場合はPostgreSQLのほうがチューニングしやすいかも？
- MySQLをあえて選択する理由はある？
    - MySQLに詳しい人・PostgreSQLに詳しい人 の対談によると、、
    - 新規10件を取得するようなクエリはMySQLのほうが速い
        - 最新のデータを表示するようなサービスの場合、MySQLのほうが速い?
    - アップデートはMySQLのほうが速い
        - PostgreSQLはinsertしてから消す
        - MySQLはそのままアップデート
    - (実務での検証はしていない、参考までに)

## 123. Node.jsでアプリケーションを開発する際に、おすすめのORMなどがありましたら教えていただきたいです

https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recSeYDLZBrTdDgI9?blocks=hide

### 回答

- Prisma がアツい!!!!!!
- Node.jsは主に2つの選択肢がある
- Prisma
    - 機能が充実している
        - JOIN先で絞り込む際に補完が効く(TypeORMは文字列。。)
        - Typescriptでtypo検知できる
        - SQLのエイリアスが豊富 -> 人が理解しやすい形で書けるため、間違えづらい
    - 楽観ロックのときに便利
        - 楽観ロック: バージョンを保持しておき、少しでも値が変わったらバージョン番号が変わる
        - バージョンが違った場合、処理を止める事ができる
        - Prismaには自動でバージョンをインクリメントできる機能がある
        - DDDでは楽観ロックを使用することが多い(設計課題に入ったら分かるかも？)
- TypeORM
    - 古参、あまり好きではないのでできるだけ避ける
    - カラムを編集したときに元あったカラムをDropしようとする
        - カラム長を伸ばしただけでも元データがDropされる
        - (issueによるとこれは仕様らしい)
    - 絞り込みを文字列で書かなくてはいけない (補完が効かない)
    - トランザクション管理のときにアノテーションを使う
        - → うまく動かなかった (中でもう一つトランザクションが作られて、コミットされてしまった)
        - アノテーション自体がTypescriptでは実験的な立ち位置
    - issueが放置されている

## その他

- NoSQL実務で利用しますか？もし使うのであれば、何使ったことあるか？
    - RDBと併用して、firebaseのfirestoreを使用した
    - firestoreは書き込んだ瞬間に書き込んだイベントを送信できる
    - -> リアルタイムの機能に便利
    - RDBとの使い分け
        - 検索しない、リアルタイムなデータ -> firestore
        - 決済などトランザクションが重要 -> RDB
    - CMSなどユーザーによってはカラムの型を変えたい時（情報の型が不定の時）
        - → ドキュメント志向のデータベースを使用する (firestore, mongoDB 等)
- Redisはよく使う？
    - Yes
    - キャッシュ用途で使う

## 参考記事

- オススメのORM
    - [prisma](hris.beams.io)
- MySQLとPostgreSQLの専門家がそれぞれの違いについて議論している良記事！
    - https://eh-career.com/engineerhub/entry/2017/09/05/110000
- RLSについて
    - [5.7. Row Security Policies](https://www.postgresql.org/docs/9.5/ddl-rowsecurity.html)
- SmartHRがマルチテナントアーキテクチャを変えた背景
    - https://tech.smarthr.jp/entry/2018/04/06/100000
    - 1日どころじゃなくて100時間かかってたみたいですw
- 個人的には、マルチテナントサービスを作るときに必読に近い良スライドだと思います！
    - https://speakerdeck.com/purintai/builderscon-2018
- 楽観ロックについて映画館のチケット管理を事例に説明しているページ
    - https://www.prisma.io/docs/guides/prisma-guides/prisma-client-transactions-guide#optimistic-concurrency-control
