はじめに
2021年10月2日-3日にPHPカンファレンス2021が開催されました。
前回のPHPカンファレンス2020も、当日スタッフとしてお手伝いをしていたのですが、
リモートでのお手伝いでした。(レポート記事の作成担当でした)
やったこと
今回は現場での配信サポートや司会のお手伝いをしました。
今年開催された、PHPerKaigi2021でも配信サポートのお手伝いをしたのですが、
数百人が同時視聴している環境でもあるため、何回やっても緊張します笑
開催期間内に配信トラブルに見舞われることも数回あったのですが、コアスタッフの方をはじめ
落ち着いて対処されていて凄いなと思いました。
気になったセッション
スタッフ対応をしながら視聴できた登壇で、印象に残ったものをざっくりまとめてピックアップします。
PHPのいまとこれから2021 (廣川 類さん)
PHPは高尚な言語ではなく、簡単にみんなの課題を解決するスクリプト言語です。
という挨拶から始まり、引き込まれました笑
廣川さんのアンケートでは、現時点で約7割のユーザがPHP7系を使っている結果が出ています。
PHPは初期と比較して、20年の間に50倍の高速化を実現しています。
この10年で段階的に進化しており、PHP5では実用的な機能を大幅に追加しています。
(マルチバイト対応など)
その後もPHP7,PHP8では更なる高速化を実現しており、OPCache,JITの導入を行っています。
PHP8.1では、”Fiber”という機能をサポートすることが決定しています。
これは、非同期プログラミングを実現する仕組みですが、async/await的なアプローチではなく、Fiberオブジェクトを使うものです。細かいことはこちらの記事が詳しく書いています。
https://qiita.com/rana_kualu/items/a6601b49e0591eb42200Never型がサポートされることとなりました。 これは、void型と似ていますが、その関数が呼ばれたらプログラム自体が終了することを明示的に宣言することができます。
スプレッド演算子が公式サポートされます。 これはJavaScriptやTypeScriptを書いているときに「PHPでもあったらなあ」と思っていた機能です。このサポートはかなり待っていました。
PHP8.1のアップデートを追っていませんでしたが、知ることができて勉強になる登壇でした。
PHPer が知るべき MySQL クエリチューニング
DBRE本の紹介から始まりました。(DBREという言葉すらこの時初めて知りました笑)
DB障害で調べるポイントについて下記を挙げました。 - どんなSQLか。(実行速度と実行頻度 - コードのどこか(ORMだと特定に時間がかかる - どう修正すればいいか
障害を予防する方法としては下記を挙げました。
- スローログ監視
-> メトリクスをモニタリングする
- スロークエリ改善
-> 遅いクエリを特定して改善する
- スロークエリ予防
-> コードレビュー設ける
障害につながる原因は後手に回りがちですが、障害発生は先手で対応できます。
SWE/SREやりがちな考えとして - ORMで十分という考え - 垂直スケールに頼る - たまにしか障害起こらないし修正しなくていいや
があるが、問題(スロークエリなど)を黙認していることと同じ。
品質、信用失墜により競合他社に負けてしまいます。
また、その問題がパフォーマンスに関わる場合は、攻撃者にDoS攻撃のヒントを与えることになります。
問題を改善していくことで、プロダクトの品質向上のみならず、チームのスキルアップにつながります。
DB障害時の原因特定について下記の通り解説がありました。
- リリース直後にパフォーマンスが下がる場合
- 本番と開発のサーバスペックの違いが原因の可能性。
本番/開発でレコード数は段違いなのでスロークエリが顕在化する。
- 本番と開発のサーバスペックの違いが原因の可能性。
ということで、本番を考慮してリリースできるのが理想です。
-> 開発環境ではパフォーマンスのテストまではできないので、
本番DBと同期したステージング環境DBでテストするのがベターです。
本番DBに気軽に重いクエリを投げるのはNGです。
PHPMyAdminで重いクエリを本番DBに投げた場合プロセスが残って障害の原因になるので、
ステージング環境でやるようにする。
- ある日突然レスポンスが下がった場合の対処
データ数増加により、インデックスよりフルスキャンが優先されるようになるとのことです。
(こういうことがあるのか…初耳)
対処法としては、期間指定などで絞り込み条件を追加してみるなどがあります。
BETWEEN句で期間指定されている場合、該当するデータが多すぎる場合に起こる可能性がある。
カーディナリティの偏りで対象行数が増えてると、インデックスの意味がなくなります。
カーディナリティが偏っているテーブルは別テーブルに移すのが吉です。
スロークエリを根絶する方法は下記の通りです。 1. ステージングでクエリが重くないことを確認する。 2. EXPLAINで実行計画が問題ないことを確認 3. レコード増加していくペースを監視する。
- 2. はアプリケーションエンジニアでも実践できます。
フレームワークレベルでもスロークエリを検知する方法があります。
例: CakePHPのDebugKit
https://book.cakephp.org/debugkit/3/ja/index.html
リリース後は下記のように監視を強化して既存のコードがスロークエリ化しないか監視します。 - CloudWatchでメトリクス取得 - Slackにスロークエリを投げる(アプリケーションエンジニアも意識できる - DataDogを使うとで対象コードがわかる。
もっと改善していくために
- 前述のDataDogなどを使い、スロークエリ実行箇所(コード)の特定を迅速にする。(障害発生時に特定に時間がかかるので)
- スロークエリを実行時間、実行回数の観点で分析する仕組みを導入
叩かれた回数、実行時間から効果的なものから先手を打って顕在化していない障害を予防できる。
インデックスについてもお話がありました。
EXPLAINの見方について、下記のリンクがいいよ!とのことでした。
(僕も前からお世話になっています笑
http://nippondanji.blogspot.com/2009/03/mysqlexplain.html
細かいことは上記のリンクに譲り、ざっくり説明すると上から順に改善が必要です。
ALL(クエリ改善が必要。全スキャンが動いている。)
INDEX(クエリ改善が必要。INDEXの中で大量スキャンが動いている、意味をなしていない)
RANGE(要注意)
const(安全)
複合インデックスを貼る際は、クエリの実行順に貼らないと全く無意味になってしまいます。
とはいえ、インデックスを無闇に増やすと書き込みコストの増加、ストレージ容量の増加につながるので、
定期的なメンテナンスが必要になります。
EXPLAINの結果を見る際は、 - どこかに着目せず、複合的に見る。 - インデックスの使われ方を見る。
ことが大事です!
ペアプロ、継続的なレビューに取り組むことで、視点が広がるため、問題になりそうなところを事前に洗い出すことができます。
-> 検索条件の見直し、テーブル分割できないか?そもそも論理削除であるか?など
ソフトウェアは継続的な改善が必要であり、手を抜き始めた途端に水面下で品質低下が始まります。
時には、PdM, PjMとの対話が必要になることもあります。
職種の垣根を越えた対話こそが、ソフトウェアの品質向上に向けた重要な活動です。
「本当にその機能必要?」「このままいくとこうなるよ」という対話こそが品質向上に向けた第一歩とのことです。
まみーさんは指摘と提案はセット(めっちゃわかる)ということをおっしゃっており、すごく唸ってしまいました。
SQL1つでここまで話が広がっていきました。 データベースって深いなぁと思ってしまいました!
まとめ
イベントのお手伝いを始めて3年が経ちますが、いろんなスキルを持った人が集結するので
良い体験になります。
また、PHP系のイベントに参加するのは3回目なのですが、常連スタッフの方の顔を徐々に
覚えられるようになって、お話できることもあり嬉しかったりします。
PHPerKaigiの時以来に、@takeokunn さん と @cocoeyes02 さんに 会ってお話できました。
@takeokunn さんはアプリケーションエンジニアで、普段PHPを業務で触っていないにも関わらず参加しています。 向上心を見習わなければならないです汗
@cocoeyes02 さんからはDDDへの取り組みなどをお聞きすることができました。
会社を上げてドメインモデリングへの理解に取り組んでいるらしく、キャッチアップに向けて取り組んでいるようです。 他社の取り組みを見ることができ、刺激になりました。
やったことがない人は一度でも参加してみると、世界が変わるのでおすすめです。