---
# System prepended metadata

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

---

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

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

## 107.実装理由を知りたい
【実装理由を知りたい】課題：web脆弱性
コマンドインジェクションは、ｗｅｂ画面からOSへ命令が出せる事を悪用した攻撃だとわかました。
しかし、そもそも画面からシステムコールを実施したい状況がわかりませんでした。
どういった想定の元、実装されるのでしょうか。

[質問全文]
https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recktgKzoZrNAKeCV

[回答]
例えばherokuとかはユーザから任意のコマンドを受け取って実行するので、
こういう時にサニタイズしておかないとユーザの権限を大きく上回る権限で実行されてしまう事があるのではないでしょうか？
主にPaaS系のサービスが検討すべきことかもしれませんね・・・
それか、hackeroneで事例を調べてみた感じだと結構ライブラリ周りの事例は多いですね
[参考]
https://hackerone.com/reports/661959
https://hackerone.com/reports/871071
https://hackerone.com/reports/685447

大体セキュリティ系の問題を調べる時はcveで検索してます
https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=command+injection
oktaでもコマンドインジェクションの事例があったみたいですね！
https://www.okta.com/security-advisories/cve-2021-28113/

## 108.SQLインジェクションは使用するフレームワーク、システムに依存しますか
【SQLインジェクションは使用するフレームワーク、システムに依存しますか】
IPAが発表した２０２０年のSQLインジェクションの脆弱性（問題箇所）報告が約１３０件ほどだそうです（目測）

[質問全文]
https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recADtESUbvQ1DNs5

[回答]
多くの場合はフレームワークが提供しているさにライズ機能を使用しているが、
自分でそのほかの外部ライブラリを導入したり、各層（コントローラーやモデル (ドメイン層) ）で自分でサニタイジングを実装するなどを組み合わせれば、フレームワークに依存することは無いと思います。

各層で防御策をこうじることは防御的プログラミング

## 109.「jestで単体テストを書こう」の課題で
「依存性の注入を実施することで、モジュール同士の結合度の強さはどのように変化したでしょうか？」という課題がありましたが、
結合度の定義とは一体なんでしょうか。

[質問全文]
https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/rec4idrkEcXRt0WT2

[回答]
厳密な結合度の定義では変わっていない。
ただ、プログラマーが抽象的な概念イメージとしての結合度は下がっている。

例えば、依存性をコンストラクタを別のクラス内でnewすると依存していると呼べる、
そうではなくインターフェースを介して具象化をすることで依存性は下がっていると呼べる。

厳密な結合度の定義は、メンターも最近まで知らなかった。
同様なイメージとしては似たようなことを考えているが、具体的な業務（レビューなど）で厳密な定義を持ち出して指摘などをしたことは無い。

Schoolクラス/Studentクラスでの例
例えば、Studentクラス内で直接Schoolクラスのgetterを呼ぶことを考えた時、
引数で渡しても、importしても、どちらも他のオブジェクトの内部を参照しているパターンで結合度は変わっていない。
ただ、インターフェースにすることで結合度は変わるが、その場合、結合度の定義の中でどれに当たるかと言うと、どれにも当てはまらない気がする。

課題は、そこまで厳密な定義を考えていなかったため、課題の書き方を見直す。

## 110.どのような場合に複合インデックスを採用・検討するのか教えて頂きたいです。
単一インデックスに比べて、WHERE句で指定するカラムの順番を注意したり、
インデックスの最初のカラムに範囲指定をすると上手く複合インデックスが活用出来ないなど、とても扱い辛いと感じました。
また、データベースに対して、気軽にインデックスを貼ったり消したりするのは難しいと思うので、普段の業務では基本的には単一インデックスだけで十分なのではないかと考えました。

[質問全文]
https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recQRdFjI60fb6jyV

[回答]
基本的には単一INDEXでほとんど絞り込めない、
単一INDEXだと足りない場合（Where句を複数指定しなければならない時など）は複合INDEXを指定している。

whereのあとでグルーピングするときによく使うかも。

例えば、クラスとそこに所属する生徒の情報を扱うアプリがあった場合、
クラス名で絞った後に、各生徒の成績で並べ替えるときは、複合INDEXを使用する。
１つ目のINDEXでクラスで絞り込み、２つ目のINDEXで成績順に並び替えるなど。
絞り込みと並び替えを同時に行うときは、僕は複合INDEXを使っている。

## 111.普段の業務で、SQLのパフォーマンスを測定する際に使用しているツールなどがありましたら、教えて頂きたいです。

普段の業務で、SQLのパフォーマンスを測定する際に使用しているツールなどがありましたら、教えて頂きたいです。

[質問全文]
https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recDws4nfaRaxqt7Z

[回答]

実務で使ったことがある -> datadog
古めのサービス -> zabbix
rdsには備え付けのinsightsがついている、RDSを使うときには基本的にこちらを使う


RDSじゃ無いときはダンプを出力した上で、pt-query-digestを使います。
スロークエリを読み込んで、ランキング(※)付けしてくれた結果などを見ます。
※pt-query-digestを使えば、待ち時間が長いとか、実行回数など色々なランキングを出せる

## 112.MySQLのperformance_schemaについて。
パフォーマンス測定の際に使用するテーブルや設定などがありましたら、教えて頂きたいです。

[質問全文]
https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recI87Ond89B7Bbu0

[回答]
使われていないINDEXが無いかなどは、パフォーマンススキーマを使って探すときがある。
INDEXの使用度合いごとに集計するテーブルなどがあったりする。
スロークエリログとどちらを使うかと言うと大体スロークエリログを使う。
スロークエリをEXPLAINして原因分析・アプローチしているため、パフォーマンススキーマより、スローログをみることの方が多い。

実務では遅く無いクエリを見に行くことが無いため、遅くなければ特に問題ないかなと放置していることが多いです。
もう少し上級レベルのDBAであれば、パフォーマンススキーマまで見ているかもしれないが、
新規のWebシステム開発をしている上では、このレベルで問題ない。

## 113.データベースでNULLが発生させないような設計のコツなどはあったりするでしょうか

またNULLがどうしても発生してしまう場合は、アプリケーション側で対処していたりするでしょうか（何か別の値に置換するなど）

[質問全文]
https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/reczBwoEEnhzhRt7N

[回答]
発生させないコツとしては、別のテーブルを作るしかない。
以前別チームでNULLを許容するか、別テーブルにするかの判断基準について質問されたとき、下記のように回答しました。
概念として同じようなものであればNULLを許容する、概念として別のものであれば別テーブルにする。


例: マッチングアプリで、いいねに加えてメッセージ付きいいね機能をつけたかった
アプリケーション的にはどちらも同じような扱いなので(使用する側の見え方は一緒・いいね数のカウントもまとめてカウントされる等)、別のテーブルに分けずにNULL許容の「メッセージ」カラムを追加した


（回避策としてNULL以外の値に置換するのはどうか？
　業務でデータを送ってくる側がメインフレームで型がないのでアプリ側で対処していた。
　この場合、データベースでは全く想定していないbitずれの値が来たりしていた。）

Webアプリケーションの開発としては、データがない場合は純粋にNULLを入れるようにしていた。
もし、別の違う値を使った場合は、エンジニア側が覚えておく（暗黙のルールとしておく）必要があるため、
仮にエンジニアが変わってしまった時にわからなくなってしまう。
これはアンチパターンとしても紹介されており、上記のような暗黙のルールは作らないようNULLをそのまま使用するのが良い。

## 114.外部結合のユースケースにはどのようなものがあるでしょうか

分析用途であれば、ユーザーとその購入履歴を調べる際に何も購入していないユーザーを想定して外部結合を使うなどの事例があるかと思います

過去に外部結合を使用した事例などがあれば教えていただきたいです

[質問全文]
https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/rec0lAshbvSSNcxib

[回答]
１つめJoinする情報がそんなに大事ではないとき。
例えば、セミナーに招待されていないユーザーでもセミナーに参加できるような仕様のとき。
招待元ユーザーが存在しなくても集計したいので、外部結合をつかってすべての参加ユーザーを集計する。
（あってもなくても困らないとき）

内部結合の方が早くはなるので、どちらでも使えるときは、内部結合を使っている。

## 115.効果のあるインデックスを張る場合にはカーディナリティがが高いだけではなく、(1)カーディナリティが高い、かつデータの偏りが少ないであったり、(2)カーディナリティが低い、かつデータの偏りがある、といったパターンなどもあるかと思います。

[質問全文]
https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recAkb2lHTW5KP9lm

[回答]
INDEXの設計に関して、真っ先に考えるのは、そのクエリがどれだけ呼び出されているか、
自分がインデックスを張ろうとしているテーブルがどれだけ更新されるか。

OLTP -> データの書き込みメイン
OLAP -> データの参照がメイン（BIツールなど）

INDEXをはるのに向いているのはOLAP。

UBER EATSは、基本OLTPだと思う。この場合は決算などの書き込みメインなのでINDEXは重要ではない。
クックパッドなどは、読み込むことの方が多い。この場合は、INDEXが重要。

なので、まずは自分が作っているアプリがどちらなのか、と言うのを考える。
そのあと、遅くなっているクエリを探して、EXPLAINなどで分析する。
そして、クエリの改善が無理ならINDEXを検討する。（ここでカーディナリティを考慮する）

INDEX検討時は、クエリがSELECT/UPDATEどちらが多いかを比べる。
SELECTが多いとなった場合、そこで初めてカーディナリティなどを確認する。
確認は、本番データベースからデータをダンプしてみて、ローカルのmysqlに入れ、INDEXを張ったり、削除したりしながら、実際のクエリを流しながら見ることが多い。
特にオプティマイザがデータによって実行計画を変えるため、実際にやってみないとわからないことが多い。

データの偏りは意識したことはない、なぜならデータが偏っていると言うことはカーディナリティは低いと思うので。
見るのであれば、MySQL8から"ANALYZE TABLE ~ HISTGRAM"と言うデータの偏りをヒストグラムとして出してくれる機能がある。
ただ、偏りはアプリの使われ方やお客さんの変化によって変わってくるものなので、あまり見ない。もし、大規模なシステムになってくると、見ているのかも。

[OLTP and OLAP: a practical comparison](https://www.stitchdata.com/resources/oltp-vs-olap/)

## 116. クエリの実行時間を計測する場合には、performance_schemaとスロークエリログのどちらを使うことが多いでしょうか

[質問全文]
https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recI87Ond89B7Bbu0

[回答]
だいたい最初は３秒とかに設定して、３秒以上のスロークエリがなくなったら、２秒にして、、、などちょっとずつ下げていくアプローチが多い気がします。

## 117.クエリの実行速度を改善する判断や基準はどのように設けているでしょうか

実務だとエンドユーザーまでのレイテンシなどが設定されているかと思いますが、クエリの改善をする判断に至るまでの流れや調査方法などがあれば教えていただきたいです。

[質問全文]
https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recWyh6swP1v0J3Ds

[回答]
フロントエンド：
googleのLightHouseを真っ先に見ます。
LightHouseでは、そのサイトのパフォーマンスを測ることができる。
これはChromeの拡張などについているので、好きなページに行って、レポート生成をすると、フロントエンドのパフォーマンスを出してくれる。
このレポートのアドバイスにしたがってチューニングしていくことが多いです。
[lighthouse](https://github.com/GoogleChrome/lighthouse)

バックエンド：
十中八九データベースのスロークエリであることが多いので、スロークエリを見に行きます。RDSならperformance insightsなどを確認しチューニングをする。

アプリケーション自体がボトルネックになっていると言うケースに今まであったことはない。大体、フロントエンドやクエリの書き方がよくなかったと言うケースがほとんど。

ユーザーが情報を受け取るまでの時間(mearningfull contents)が3秒を越えると、大体のユーザが離脱すると言うデータがある。（walmart)
そのため、3秒以内を目指しているエンジニアさんが多いように思う。
サイトによって、お客サマが求める情報は違う。

https://rigor.com/wp-content/uploads/2012/03/Slide2.png

> クエリの改善をする判断に至るまでの流れや調査方法などがあれば教えていただきたいです。

有意義な情報は提供できない。
PrAhaでは、エンジニア間で口頭でのコミュニケーションで完結してしまっている。

## 118.効果的なインデックスを貼れているかどうかはどのように判断しますか？

[質問全文]
https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recAJliZCmaDjZ7vJ

[回答]

これはダンプをとって、手元で回してみるのが一番早い。
やはり、本番データでやってみないとわからないことが多い。
（データの偏りなどもあるため）

INDEX HINTを使っているクエリがあるときは、削除の時に注意が必要。
INDEX HINTを使用することで強制的にINDEXを使用させることができる。
この場合、INDEXを削除するとクエリが落ちる場合がある。
こう言うときは、INDEXをINVISIBLE（オプティマイザから見えなくする）にして、試してみて、問題がなければ削除すると言うパターンはありかなと思います。

それ以外のケースでは気軽に消しちゃってもいいのかなと、僕は思ったりします。
消したらクエリが動かなくなると言うケースはないはずなので（遅くなることはある）、試しに消してダメだったら、戻すなども実務でもやったりしている。

本番環境でCreateIndexなどをするとDBが止まってしまったりするので、基本はダンプをローカルに持ってくるのが良い。

消せそうなINDEXを探すとき。PERCONAのツールを使うのが便利です。
[pt-index-usage](https://www.percona.com/doc/percona-toolkit/LATEST/pt-index-usage.html)
pt-duplicate-key-checker

PERCONA内のブログをみるのも勉強になります。

[13.2.9.3 インデックスヒントの構文](https://dev.mysql.com/doc/refman/5.6/ja/index-hints.html)

[8.3.12 Invisible Indexes](https://dev.mysql.com/doc/refman/8.0/en/invisible-indexes.html)

## 119.複数テーブルをJOINするようなクエリの高速化にはどのような方法があるでしょうか？

[質問全文]
https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recvkKntpDOXvV2oa

[回答]

JOINを書くときは、以下を気にすることが多い。
駆動表と内部表と言う考え方があって、MYSQLのJOINには３種類ある。
その中でnest loop joinをする時に大切になるのが駆動表と内部表と言う考え方です。
　駆動表：最初に処理をする
　内部表：駆動表の処理結果をもとに処理する
これらを検知するにはEXPLAINを使用するのが多い。
 
 [余談]
 最初に正規化を学んだりするが、敢えて重複させることもよくある。
 例えばデータ規模が大きい場合、導出表にしておくと負荷が高いなど。
 上記はINSERTしかない場合などで使用している。
 
 マッチングアプリだと、ユーザーリレーションというテーブルを用意して、
 両思い、片想い、いいねなしの情報を持っておく。（バッチで作成）
 いちいち、いいねされているかを全ユーザ分検索しに行くととても遅くなってしまう。
 
 [参考]
 https://qiita.com/yuku_t/items/208be188eef17699c7a5