å°å ¥ïŒã¢ãã³åã®æåŸã®ããã«ããã¯
ãããŸã§ã®é£èŒã§ãããã³ããšã³ã (Next.js) ã®é«éåãå ç¢ãª API èšèš (Django DRF)ãå®å®ããã€ã³ãã© (Nginx/PM2) ã®æ§ç¯ã«ã€ããŠè§£èª¬ããŠããŸãããããããã·ã¹ãã ã®ã¢ãã³åã«ãããŠãæãæ ¹æ·±ãã解決ãé£ããããã«ããã¯ãäžã€æ®ãããŠããŸãããããã**ãããŒã¿è¥å€§åã«ããããŒã¿ããŒã¹ïŒDBïŒæ€çŽ¢ã®é å»¶ã**ã§ãã
ã©ãã ãããã³ããšã³ãã®è¡šç€ºé床ãäžããŠããããã¯ãšã³ããããŒã¿ããŒã¹ããããŒã¿ãååŸããã®ã«æéããããã°ããŠãŒã¶ãŒã®åŸ ã¡æéã¯é·ããªããŸããæ¬èšäºã§ã¯ãæ°åäžä»¶èŠæš¡ã«èšããã DB ã«å¯ŸããPostgreSQL ã®ç¹æ§ãš Django ORM ã®æ©èœãæå€§éã«æŽ»çšããæ€çŽ¢é床ãåçã«æ¹åããå®è·µçãªææ³ã解説ããŸãã
第1ç« ïŒããã©ãŒãã³ã¹ãèããN+1 åé¡ããšéå¹çãªããŒã¿ååŸ
1. ORM ã®è£åŽã«ãããé ããã®æ£äœ
Django ORMïŒObject-Relational MapperïŒã¯ãPython ã³ãŒãã§ããŒã¿ããŒã¹ãæäœã§ããããéåžžã«äŸ¿å©ã§ããããããäœãèããã«äœ¿ããšãããã©ãŒãã³ã¹äžã®å€§ããªåé¡ãåŒãèµ·ãããŸãããããããšã³ãžãã¢ã«ãšã£ãŠæªåé«ã**ãN+1 åé¡ã**ã§ãã
äŸãã°ããèšäºäžèЧãã衚瀺ããéã«ããåèšäºã®èè åããåæã«è¡šç€ºããããšããŸãã
- ãŸããèšäºã®ãªã¹ã 100 ä»¶ãååŸããããã« 1 ã¯ãšãªãå®è¡ããŸãã
- 次ã«ããªã¹ãå ã®åèšäºã®èè æ å ±ãååŸããããã«ãã«ãŒãå ã§ 100 ã¯ãšãªãå®è¡ããŸãã
åèš 101 ã¯ãšãªãå®è¡ãããããšã«ãªãããµãŒããŒã¯å€§éã®ç¡é§ãªéä¿¡ãšããŒã¿åŠçãè¡ãããšã«ãªããŸããããŒã¿éãå°ãªããã¡ã¯åé¡ã«ãªããŸããããDB ãè¥å€§åãããšããã®éå¹çãªããŒã¿ååŸãã¢ããªã±ãŒã·ã§ã³å šäœã®å¿çé床ãèããäœäžãããŸãã
2. é å»¶ããŒãïŒLazy LoadingïŒã®çœ
Django ORM ã®ããã©ã«ãã®æåã¯ãåºæ¬çã«**é å»¶ããŒãïŒLazy LoadingïŒ**ã§ããããã¯ãé¢é£ããŒã¿ïŒå€éšããŒã§ç¹ãããããŒã¿ãªã©ïŒãå¿ èŠã«ãªã£ãæç¹ã§ã¯ãããŠã¯ãšãªãçºè¡ããä»çµã¿ã§ãã
é å»¶ããŒãã¯ã¡ã¢ãªãç¯çŽããŸãããåè¿°ã® N+1 åé¡ã®æž©åºãšãªããŸãã倧éããŒã¿ãæ±ãã¢ãã³ãªã¢ããªã±ãŒã·ã§ã³ã§ã¯ããã®é å»¶ããŒãã®æåãæå³çã«å€æŽããå¿ èŠãªããŒã¿ãäžæ¬ã§ååŸããã¢ãããŒããå¿ é ãšãªããŸãã
第2ç« ïŒDjango ORM ã®å¥¥çŸ©ïŒã¯ãšãªæ°ãåçã«æžããæè¡
N+1 åé¡ã解決ããã¯ãšãªæ°ãæå°éã«æããã«ã¯ãDjango ORM ãæäŸãã 2 ã€ã®åŒ·åãªã¡ãœããã䜿ãåããå¿ èŠããããŸãã
1. å€éšããŒã«åŒ·ã select_related (SQL JOIN ãå©çš)
select_related ã¯ã1 察 1 ãŸãã¯ å€ å¯Ÿ 1 ã®ãªã¬ãŒã·ã§ã³ã·ããïŒForeignKey ã OneToOneFieldïŒãæã€é¢é£ããŒã¿ããSQL ã® JOIN å¥ãçšããŠãã£ã 1 åã®ã¯ãšãªã§ååŸããŸãã
- çšé: èšäºãšãã®èè æ å ±ããŠãŒã¶ãŒãšãã®ãããã£ãŒã«æ å ±ãªã©ãæç¢ºãªãªã¬ãŒã·ã§ã³ãäžã€ã«å®ãŸãå Žåã«æé©ã§ãã
- ã¡ãªãã: ããŒã¿ããŒã¹åŽã§çµååŠçãè¡ããããéåžžã«é«éã§ãã
- ã³ãŒãäŸ:Python
# é ãã³ãŒã (N+1ãçºç) articles = Article.objects.all() # éãã³ãŒã (1ã¯ãšãªã§å®äº) articles = Article.objects.select_related('author').all()ããã§ã100 ä»¶ã®èšäºãååŸããéã«ãèè ã®æ å ±ãåæã«ååŸãããã¯ãšãªæ°ã¯ 1 ã«åæžãããŸãã
2. ãªã¹ãæ§é ã«åŒ·ã prefetch_related (Python åŠçãå©çš)
prefetch_related ã¯ãå€ å¯Ÿ å€ ããªããŒã¹ ForeignKeyïŒéåŒããªã¬ãŒã·ã§ã³ïŒãªã©ãè€æ°ã®é¢é£ãªããžã§ã¯ããååŸããå Žåã«å©çšããŸãã
- çšé: ã«ããŽãªãšããã«å±ããè€æ°ã®èšäºããŠãŒã¶ãŒãæã€è€æ°ã®ã¿ã°ãèšäºã«å¯Ÿããè€æ°ã®ã³ã¡ã³ããªã©ã
- ä»çµã¿:
- ã¡ã€ã³ã®ããŒã¿ïŒäŸïŒã«ããŽãªãªã¹ãïŒã 1 ã¯ãšãªã§ååŸã
- é¢é£ããŒã¿ïŒäŸïŒã«ããŽãªããšã®å šèšäºïŒãå¥ã® 1 ã¯ãšãªã§ååŸã
- ååŸãã 2 ã€ã®ããŒã¿ã Python åŽã§å¹ççã«çµåããŸãã
- ã¡ãªãã: åèšã¯ãšãªæ°ã¯åžžã« 2ã3 çšåºŠã«åãŸããN+1 åé¡ãå®å šã«åé¿ããŸãã
- ã³ãŒãäŸ:Python
# é ãã³ãŒã (N+1ãçºç) categories = Category.objects.all() # éãã³ãŒã (ã«ããŽãªååŸ1ã¯ãšãª + é¢é£èšäºååŸ1ã¯ãšãª = åèš2ã¯ãšãª) categories = Category.objects.prefetch_related('articles').all()
ãã® 2 ã€ã®ã¡ãœããã®é©åãªäœ¿ãåãããè¥å€§åãã DB ãžã®ã¢ã¯ã»ã¹å¹çãåçã«æ¹åããéµãšãªããŸãã
第3ç« ïŒPostgreSQL ã®åãæå€§éã«åŒãåºãã€ã³ããã¯ã¹æŠç¥
ORM ã®æ¹åã¯ã³ãŒãã¬ãã«ã®æé©åã§ãããããã«æ ¹æ¬çãªé«éåã®ããã«ã¯ãããŒã¿ããŒã¹ãšã³ãžã³ïŒPostgreSQLïŒãã®ãã®ã®åãåŒãåºãç©ççãªæé©åãå¿ èŠã§ãã
1. ã€ã³ããã¯ã¹ã®åºæ¬ãšéèŠæ§
ã€ã³ããã¯ã¹ã¯ãæžç±ã®**ã玢åŒã**ã®ãããªãã®ã§ãç¹å®ã®ã«ã©ã ã§æ€çŽ¢ããããéã«ãããŒãã«å šäœãã¹ãã£ã³ããã«ããŒã¿ãé«éã«èŠã€ãåºãããã®ä»çµã¿ã§ãã
- å¿
é ã€ã³ããã¯ã¹ã®ç¢ºèª:
- å€éšããŒïŒForeignKeyïŒ: ãªã¬ãŒã·ã§ã³çµåã®å¹çãäžããããã«ãå¿ ãã€ã³ããã¯ã¹ã匵ããŸãã
- æ€çŽ¢æ¡ä»¶ã«ãã䜿ãã«ã©ã :
WHEREå¥ã§é »ç¹ã«çµã蟌ã¿ã«äœ¿ãã«ã©ã ïŒäŸïŒslugãstatusãæ¥ä»ã«ã©ã ïŒã
2. æ€çŽ¢ãçµã蟌ãéšåã€ã³ããã¯ã¹ïŒPartial IndexïŒ
ãã¹ãŠã®ããŒã¿ã«ã€ã³ããã¯ã¹ã匵ããšãããŒã¿ã®æžã蟌ã¿ïŒINSERT/UPDATEïŒãé ããªããšããå¯äœçšããããŸããããã§ãPostgreSQL ã®åŒ·åãªæ©èœã§ããéšåã€ã³ããã¯ã¹ã圹ç«ã¡ãŸãã
äŸãã°ããŠãŒã¶ãŒå
šäœã® 90% ãéã¢ã¯ãã£ãïŒis_active=FalseïŒã§ãã¢ã¯ãã£ããŠãŒã¶ãŒïŒis_active=TrueïŒã«çµã£ãæ€çŽ¢ãé »ç¹ã«è¡ãããå ŽåãèããŸãã
- éšåã€ã³ããã¯ã¹ã®é©çšäŸ:SQL
CREATE INDEX active_users_idx ON users (username) WHERE is_active = TRUE;ãã®ã€ã³ããã¯ã¹ã¯ãããŒãã«å šäœã® 10% ã®ã¢ã¯ãã£ããŠãŒã¶ãŒã«ããé©çšãããªããããã€ã³ããã¯ã¹ã®ãµã€ãºãå°ããä¿ããããã® 10% ã®ããŒã¿ã«å¯Ÿããæ€çŽ¢ãåçã«é«éåãããŸãã
3. ã¯ãšãªå®è¡èšç»ã®åæ (EXPLAIN ANALYZE)
éé²ã«ã€ã³ããã¯ã¹ã匵ãã®ã§ã¯ãªããEXPLAIN ANALYZE ã³ãã³ãã䜿ã£ãŠãPostgreSQL ãå®éã«ã©ã®ã€ã³ããã¯ã¹ã䜿ããã©ã®ãããªé åºã§ã¯ãšãªãå®è¡ããŠããããåæããããšã極ããŠéèŠã§ãããã®åæã«ãã£ãŠãããã«ããã¯ãšãªã£ãŠããéšåãç¹å®ããæå°éã®å·¥æ°ã§æå€§ã®å¹æãåŸãããšãã§ããŸãã
ãŸãšãïŒDB ç¥èŠããã Full-Stack ã®æçµå µåš
ãã®ãããžã§ã¯ãã§ãç§ã¯ Next.js ã®é«éã¬ã³ããªã³ã°æè¡ã«å ããPostgreSQL ã®æ·±ãç¥èãš Django ORM ã®å¿çšæè¡ãç¿åŸããŸããã
ããŒã¿ããŒã¹ã®ç¥èã¯ãWeb ã¢ããªã±ãŒã·ã§ã³ã®æ§èœãšä¿¡é Œæ§ãæ¯ããæåŸã®ç Šã§ããåã«ã¢ããªã±ãŒã·ã§ã³ãåããã ãã§ãªããããªãåããŠããã®ãïŒããã©ãããã°ããéããªãã®ãïŒããšããåãã«çããããã¹ãã«ããããè¥å€§åããã¢ãã³ Web ã¢ããªã±ãŒã·ã§ã³ã®éçšã«ãããŠãããã®ãšã³ãžãã¢ã«æ±ããããèªèµ°åã§ãããšç¢ºä¿¡ããŠããŸãã


ã³ã¡ã³ã