Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
20220319[Laravel]想定外のN+1アラート
Search
kuma
March 14, 2022
Programming
200
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
20220319[Laravel]想定外のN+1アラート
kuma
March 14, 2022
More Decks by kuma
See All by kuma
エンジニアの輪スライド
kumainataku
0
290
20220730[PHP]デザインパターン色々学んでみた
kumainataku
0
140
20220227 可読性って大事
kumainataku
0
86
20211027_僕の転職活動の振り返り.pdf
kumainataku
0
120
オブジェクト指向(超基礎)
kumainataku
0
160
20210516 LT資料(PHP echo print)
kumainataku
0
59
20210425 LT会(基本情報技術者)
kumainataku
0
49
202104 読書LT会
kumainataku
0
210
Other Decks in Programming
See All in Programming
Foundation Models frameworkで画像分析
ryodeveloper
1
120
【やさしく解説 設計編 #1】「ドメイン駆動」と「実装駆動」ってなに? 〜設計の考え方を、たとえ話で学ぼう〜
panda728
PRO
1
120
Hatena Engineer Seminar #37「言語モデルの活用に関する研究」
slashnephy
0
520
分散システム、なんですぐ死んでしまうん?耐障害性を高めたいあなたのためのレジリエンスパターン入門
mshibuya
7
6k
1B+ /day規模のログを管理する技術
broadleaf
0
140
【やさしく解説 設計編・中級 #1】一つの車に、運転手は一人 ~ある倉庫システムの事例から~
panda728
PRO
0
170
言語を使う側から、作る側へ。 自作 Lisp で得た新たな気づき。
andpad
0
120
LaravelLive Japan の裏方のすべて — 第188回 PHP勉強会@東京 (2026-06-24)
suguruooki
2
150
初めてのKubernetes 本番運用でハマった話
oku053
0
120
なぜ関数型プログラミングで「型」と「証明」が語られるのか #fp_matsuri
kajitack
3
910
symfony/aiとlaravel/boost
77web
0
130
才能?センス?知らん、 続けたもん勝ちだ。-- 結婚・出産・癌を越えてなお、私がプロダクトを創り続ける理由
16bitidol
2
850
Featured
See All Featured
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
270
SEO for Brand Visibility & Recognition
aleyda
0
4.6k
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
170
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.8k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.8k
Prompt Engineering for Job Search
mfonobong
0
370
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
330
So, you think you're a good person
axbom
PRO
2
2.1k
Between Models and Reality
mayunak
4
370
Test your architecture with Archunit
thirion
1
2.3k
BBQ
matthewcrist
89
10k
Transcript
[Laravel]想定外のN+1アラート 2022 / 3 / 19 クマ
自己紹介 • 実務入って半年 • PHP(Laravel)、JavaScript(Vue)を書いてます。 • 好き↓ • タガが外れたように満腹まで食べる •
ラーメン屋のハシゴ、二郎系マシマシ…etc • 甘いもの • ミスド食べ放題いったり、パンケーキ食らったり • スイパラ行くのが直近目標 P-01
目次 • 話すこと • 前提(こっから本題) • やりたいこと • 起きたこと •
原因 • やったこと(本題おわり) • おわりに P-01
話すこと P-01
話す事 LaravelにてN+1が発生していないように見えたのだが、アラート が出たときの対応方法 ↓こんなの ※Laravel経験がないとイメージつきにくい内容かもです。。。 P-01
前提 P-01
前提 バージョン • PHP 8.0.2 • Laravel 8.5.0 P-01
前提 テーブル構成 P-01 blockedプロパティをチェックしてBANす るか否かをチェックする想定
前提 リレーション ↓Userモデル P-01 UserとUserAttributeで1対1のリレーションを構築
やりたいこと P-01
やりたいこと いわゆる「垢BAN機能」を実装したい 特定ユーザーをログインできなくする、アレです。 ※ちなみに、この機能自体は本題と関係ないです。 P-01
やりたいこと <?php namespace App¥Http¥Middleware; use Closure; use Illuminate¥Http¥Request; use Illuminate¥Support¥Facades¥Auth;
class CheckBlockedUser { public function handle(Request $request, Closure $next) { if (Auth::check() && $user = Auth::user()) { $userAttribute = $user->userAttribute; // ※ if ($userAttribute && $userAttribute->blocked == 1) { Auth::logout(); $request->session()->regenerateToken(); Log::notice('Block user from login status. '.$user->id); return redirect()->route('login') ->withErrors(['error' => 'アカウントは凍結されています。']); } } return $next($request); } } P-01 App/Middleware/CheckBlockedUser userAttributeを取得 ➡ここでクエリが発行 (SELECT * FROM user_attribute …) ※補足 ここでblockedプロパティをチェックして BANするか否かをチェック
起きたこと P-01
起きたこと • ブロックユーザーで動作テスト ➡垢BAN機能は実装done(よしよし。) • 正常ユーザー(非ブロックユーザー)での動作テスト ➡ログインできるが、以下アラート発生(おん!?) P-01
起きたこと • このアラートはN+1を勝手に検出して教えてくれるライブラリ 「laravel-query-detector」によるもの • 要約:「User経由でUserAttributeを取得するクエリが必要以 上に実行されているからEager Loadingしてね!」 P-01
やりたいこと class CheckBlockedUser { public function handle(Request $request, Closure $next)
{ if (Auth::check() && $user = Auth::user()) { $userAttribute = $user->userAttribute; // ※ if ($userAttribute && $userAttribute->blocked == 1) { Auth::logout(); $request->session()->regenerateToken(); Log::notice('Block user from login status. '.$user->id); return redirect()->route('login') ->withErrors(['error' => 'アカウントは凍結されています。']); } } return $next($request); } } P-01 App/Middleware/CheckBlockedUser(再掲) ここでしかクエリ発行していないんですが、、、 ただ、、、 ➡原因調査
原因 P-01
原因 P-01 おなじみのLaravel-debugbarで確認したところすぐに判明
原因 P-01 原因はMiddlewareと別でControllerでも同じようなuserAttribute の取得(クエリの実行)をしていた $user = User::find(Auth::id()); // ココでuserAttributeを取得するSQLが発行 $userAttribute
= $user->userAttribute; App/Controller/TestController(実際のコード)
原因 P-01 Laravelとしては 「Middlewareで$userAttributeを取得するよ」 「あれ、Controllerでも取得しているね。だったらN+1だね」 と判断しちゃうんだな。。。 ↓アラート発生時のクエリ(イメージ) SELECT * FROM
use_attribute; … … SELECT * FROM use_attribute; // 2回同じクエリが発行
やったこと P-01
やったこと 案は2つ。 1, Middlewareで取得した$userAttributeをControllerまで渡す? ➡現実的ではない。 2, アラートを表示させない ➡これで行く P-01
やったこと 特定条件下でN+1を検出してもアラートを表示させないようにする ➡具体的にはlaravel-query-detector をインストールした時に入っ てくるconfig/querydetector.phpのexceptの箇所に以下記述 ➡無事アラートは発生しなくなった! P-01 'except' => [
User::class => [ UserAttribute::class, 'userAttribute', ], ] App/Controller/TestController(追加したコード) 今回はUser➡userAttributeの際にN+1が発生し たので、このように記述
おわりに P-01
おわりに • 自分はdevelopとの差分だけ見て「N+1起こるわけな い!」と決めつけた結果痛い目にあった。。。 • どんなことでも共通するのは「自分の修正した差分だ けに問題が潜んでいるとは限らない」ということ →ある程度問題に取り組んで解決しなければ、視野を広 げる(抽象度を上げる)ことの重要性を痛感 P-01
ご清聴ありがとうございました。 P-01