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
84
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
AI駆動開発で崩れていくコードベースを立て直す
kyoko_nr_nr
1
450
The Arts and Crafts of Work in the AI Era — Toward Mastery in Software Development
kuranuki
1
750
AI 時代のソフトウェア設計の学び方
masuda220
PRO
29
12k
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
0
210
気づいたらRubyで100作品 ー クリエイティブコーディングが生活の一部になるまで / 100 Ruby Sketches Later: How Creative Coding Became Part of My Life
chobishiba
3
560
AI時代のUIはどこへ行く?その2!
yusukebe
21
7k
技術記事、 専門家としてのプログラマ、 言語化
mizchi
4
2.6k
TSKaigi Night Talks 2026_TypeScriptでサプライチェーンの整合性を型に閉じ込める
geekplus_tech
0
330
The NotImplementedError Problem in Ruby
koic
1
710
ローカルLLMでどこまでコードが書けるか -拡張版 / How much code can be written on a local LLM Extended
kishida
2
1.2k
CSC307 Lecture 17
javiergs
PRO
0
320
Modding RubyKaigi for Myself
yui_knk
0
920
Featured
See All Featured
It's Worth the Effort
3n
188
29k
Chasing Engaging Ingredients in Design
codingconduct
0
220
Paper Plane (Part 1)
katiecoart
PRO
0
8.8k
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
770
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
420
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.5k
Being A Developer After 40
akosma
91
590k
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
200
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
200
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
56k
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
200
The Pragmatic Product Professional
lauravandoore
37
7.3k
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