初めまして、中川優(すぐる)と申します!サービス開発部/プロダクト開発部門/従業員サーベイチームのプロダクトエンジニアです!
仕事で使用している主な言語はRuby・TypeScriptです。個人的にGolangあたりを最近触ったりしています。趣味はヘヴィメタルです。
今回は、当社プロダクトの一つであるミキワメウェルビーイングサーベイが過去に直面した、閲覧範囲制御機能のパフォーマンス上の課題、および改善に至るまでの事例をご紹介いたします。
ミキワメウェルビーイングサーベイとは?
心理学・行動科学の知見に基づき従業員のウェルビーイング(幸福度)を測定・分析する、実名性の”パルスサーベイ”ツールです。
- 短時間の回答(3分間)によって、即座に回答結果・アドバイスを確認できる
- 個人の性格に基づいた、ウェルビーイング向上のためのアドバイスを提供
- 組織全体の回答結果を可視化し、組織単位でのアドバイスも受けることができる
詳しくは下記もご覧ください。
『ミキワメ ウェルビーイングサーベイ』とは?社員の幸福度を高め離職・休職を防ぐ|ミキワメラボ
閲覧範囲制御機能とは?
ミキワメでは大きく分けて2つの画面を提供しています。
- 従業員向け画面:従業員が自身の回答結果を閲覧するためのページ
- 企業向け管理画面:企業担当者が組織・各従業員の回答結果を閲覧するためのページ
閲覧範囲制御は、この内の企業向け管理画面における新機能として、2024年5月30日にリリースされたアップデートです。
アップデート前
企業向け管理画面のログインユーザーでは複数の権限が存在し、その中に”マネージャー”という権限があります。マネージャーは、特定の部署・および部署に所属する従業員のサーベイ回答結果のみを閲覧することができます。 しかし、そのマネージャーが現実でその役職に任命以前の結果まで閲覧できてしまう状態でした。
- 2024年6月1日にサービス開発部のマネージャーに任命されたAさんは、任命されるより以前のサービス開発部のサーベイ回答結果も閲覧できてしまう
ミキワメウェルビーイングサーベイでは、従業員が自 由記述できるコメント機能、企業担当者が従業員に対する打ち手を記録するサポート履歴機能などもあります。 その為、誰かに見られては困る内容を、その誰かが閲覧できてしまうリスクがありました。
アップデート後
マネージャーが特定の部署のみ回答結果を閲覧することができるという条件に加え、その部署を閲覧権限を付与した以前の結果は、閲覧不可とする制御ができるようになりました。
- 2024年6月1日にサービス開発部のマネージャーに任命されたAさんは、任命されるより以前のサービス開発部のサーベイの回答結果は閲覧することができない
これによって、アップデート前のリスクを防止することができ、より安心して利用できる仕様にすることはできました。
ところが、このアップデートのリリース直後、とある問題が起きてしまいます・・・
画面の表示速度がめっちゃ遅くなっている!!!
それは、サービス開発部で毎月末に実施している、各チームの進捗報告などの定例の中での話でした(確かその初回だったと記憶)。
EM「サーベイで画面表示速度が遅くなっているらしいので、従業員サーベイチームは調査に入ってください」
わたし「!!?」
企業向け管理画面では、全社・部署単位で組織のサーベイ回答結果を閲覧できるページがあり、ミキワメウェルビーイングサーベイにおけるコア機能の一つなのですが、このページにおいて著しいパフォーマンス低下が発覚。
例:数千人分の回答結果を持つページの場合
- 初期表示までに10~20秒、あるいはそれ以上かかってしまう
- サーベイに回答した社員一覧データを取得するための非同期処理に1~3分以上かかってしまう
当時はエンタープライズ企業への導入が活発化し始めていた状況だったのですが、その矢先にこのような事態に見舞われてしまったのです・・・!!
ボトルネックを探し、仮説を立てる
この事態を受け、従業員サーベイチームではリードエンジニアの力を借りながら、とにかくやれることをやっていくこととしました。
- 不足しているeager loadingの追加
- メモ化できていない所のメモ化
- 画面表示の都度発生していた計算処理を、DBから参照する形に修正
- さらに非同期取得してよさそうな所があれば非同期化
- etc
このあたりは一定改善があったのですが、元の速度に戻るまでには至らず。そして気づけば1ヶ 月経過・・・。別の観点でも調査を継続していくこととなりました。
遅くなっている画面でrack-mini-profilerを用いたクエリ発行数の調査をしていく中で、多くのクエリが発行している箇所を確認しました。この箇所では、サーベイの回答結果が閲覧できるかどうかを以下のように制御しており、これが速度低下に影響しているのではないか?という仮説を立てることとしました。
- 回答者がサーベイに回答した日時の時点で所属していた部署が、マネージャーの閲覧可能な部署である
一人一人回答タイミングは異なることから、配信対象になった社員全員分を対象をループさせ、回答者ごとに都度閲覧可能かを判定する必要があります。
# コードはイメージ。実際のものは異なります。
# cq_recruitment_examinees: サーベイ配信対象者になった社員
# supervisor: 企業向け管理画面のログインユーザー。ここではマネージャーを想定
# division: 部署
cq_recruitment_examinees.select do |cq_recruitment_examinee|
# 社員がサーベイに回答した日を取得するメソッド
deadline = cq_recruitment_examinee.completed_time
# 部署IDと回答日を渡してマネージャーが閲覧可能かを判定
# 内部で閲覧可否判定用のデータを取得するクエリの発行をしている
supervisor.survey_permission?(deadline, division.id)
end
- ループごとにクエリが発行されN+1が発生
- 社員が多いほど処理時間が線型に増加する
上記のコード例は説明のために簡略化させていますが、もう少し色々処理が伴っていたり、類似した処理が複数箇所で実装されていたりします。これらが速度低下のボトルネックなのでは!?という話になったのです。
解決に向けたアプローチ
一定ボトルネックが明確になったので、下記の改善案を考案する形になりました。
- 配信されたサーベイの配信終了日の時点で回答者が所属していた部署が、マネージャーの閲覧可能な部署である
これにより、全社員に対して同一の時点で閲覧可否を判断することができます。
# コードはイメージ。実際のものとは異なります。
# cq_recruitment: 配信されたサーベイ。cq_recruitment->cq_recruitment_examineesで1対多のリレーション。
# サーベイが終了した日付を取得するメソッド
deadline = cq_recruitment.deadline
CqRecruitmentExaminee.none if supervisor.survey_permission?(deadline, division.id)
cq_recruitment_examinees
ボトルネックとなっていたループ処理が不要になり、回答者人数に依存することなく制御できるようになりました。 ただし元々の仕様自体を変えることになるので、PdM・カスタマーサクセスのメンバーとの合意を得る必要がありましたが、一定議論を重ね、パフォーマンス以外のUX改善も盛り込む形で上記の対策を取る方針で合意することができました!
まとめ
閲覧範囲制御の実装範囲は広く、実装自体にも約2ヶ月弱かかりましたが、概ね狙い通りにパフォーマンスを改善!
before | after | |
---|---|---|
初期表示期間 | 10〜20秒(または数分以上) | 1秒未満 |
一覧データ取得時間(非同期) | 1〜3分以上 | 数秒〜15秒程度 |
これで、エンタープライズ企業への導入の障壁を大きく下げることができました。
このアップデートのリリース時点で2024年9月半ば。3ヶ月半の長い道のりで、この間メンバーの入れ替わりなどもありましたが、無事にここまでやり遂げられたことは今でも貴重な経験だったなと思っております。特に下記は教訓となりました。
- 大規模データを想定して、アップデート前後で速度の低下が発生していないかを検証した上で実装すること。非機能要件の重要性を再認識した。
- 時にはビジネスロジックの再考も話し合える姿勢を持つこと。役割を超えてより良い開発をする機会となった。
ネクストアクション
非同期処理の中には、まだ社員がサーベイに回答した日起点で閲覧可否を制御せざるを得ないパターンがあり、10〜15秒程度かかる場合があります。 こちらも更に速度が出るように改善し、より快適なサービスにしていきたいです。
そして、実は今回の取り上げた事例以外にも表示速度が遅いページが残っています・・・!同じく企業向け管理画面にある、企業上に作成された部署の一覧表示するページです。これもエンタープライズ企業にて顕在化した課題であり、同様にパフォーマンスチューニングが必要な状況です。こちらにも積極的に関わっていきたいなと思っております。
以上です。最後までご覧いただきありがとうございました!