ç§ã¯ãRuby on RailsãšPostgresãããã¯ãšã³ãã®ã¡ã€ã³ãŠã§ãã³ãšããŠäœ¿çšããŠããã»ãšãã©ãã¹ãŠã®ãããžã§ã¯ãããéçºã®é床ãã³ãŒãã®å¯èªæ§/ä¿å®æ§ãããã³æ¬çªç°å¢ã§ã®ãããžã§ã¯ãã®é床ã®éã§çµ¶ããéã£ãŠãããšä¿¡ããŠããŸããå ¥ãå£ã§å¯èªæ§ãšäœæ¥é床ãäœäžããå Žåã®ãããã3é ã®ã¯ãžã©ã®ãã©ã³ã¹ã®çµéšã«ã€ããŠã話ãããŸããçµå±ãæèœã®ãããšã³ãžãã¢ãã¡ãç§ã®åã«äœãããããšããŠããããããããŸããã§ããã
å šäœã®è©±ã¯ããã€ãã®éšåã«åãããŸããããã¯ãSQLã¯ãšãªãæé©åããããã®PMDSCãšã¯äœãã«ã€ããŠè©±ããpostgresã§ã¯ãšãªããã©ãŒãã³ã¹ã枬å®ããããã®äŸ¿å©ãªããŒã«ãå ±æãããŸã é¢é£ã®ãã1ã€ã®äŸ¿å©ãªå€ãããŒãã·ãŒããæãåºãããæåã®ãã®ã§ãã
ããŠããã°ããããŠããåŸãèŠãŠããç§ã¯ãã®äºä»¶ã®å ¥ãå£ã§ãç§ãæåããããšããŸã£ããæåŸ ããŠããªãã£ãããšãç解ããŠããŸãããããã£ãŠããã®æçš¿ã¯ãçµéšè±å¯ãªéçºè ã§ã¯ãªãã倧èãªSQLã§ã¬ãŒã«ãèŠãŠããã¹ãŒããŒã·ãã¢ãããã倧èãªéçºè ã«ã¯åœ¹ç«ã¡ãŸãã
å ¥åããŒã¿
Appboosterã§ã¯ãã¢ãã€ã«ã¢ããªã宣äŒããŠããŸãã仮説ãç°¡åã«æ瀺ããŠãã¹ãããããã«ãããã€ãã®ã¢ããªã±ãŒã·ã§ã³ãéçºããŠããŸãããããã®ã»ãšãã©ã®ããã¯ãšã³ãã¯Rails APIãšPostgresqlã§ãã
ãã®åºçç©ã®ããŒããŒã¯2013幎ã®çµãã以æ¥éçºäžã§ããããã®åŸãrails 4.1.0.beta1ããªãªãŒã¹ãããŸããããã以æ¥ããããžã§ã¯ãã¯ãAmazon RDSã®åå¥ã®ããŒã¿ããŒã¹ã€ã³ã¹ã¿ã³ã¹ïŒ4ã€ã®vCPUãš16 GBã®RAMãåããdb.t3.xlargeïŒãåããAmazon EC2ã®è€æ°ã®ãµãŒããŒã§å®è¡ãããå®å šã«ããŒãããããŠã§ãã¢ããªã±ãŒã·ã§ã³ã«æé·ããŸãããããŒã¯è² è·ã¯25k RPMãå¹³åæ¥è² è·ã¯8-10k RPMã«éããŸãã
ãã®è©±ã¯ãããŒã¿ããŒã¹ã€ã³ã¹ã¿ã³ã¹ããŸãã¯ããããã®ã¯ã¬ãžããæ®é«ããå§ãŸããŸããã
Amazon RDSã§Postgresã¿ã€ãã®ãtãã€ã³ã¹ã¿ã³ã¹ãã©ã®ããã«æ©èœãããïŒããŒã¿ããŒã¹ãç¹å®ã®å€ãäžåãå¹³åCPUæ¶è²»ã§å®è¡ãããŠããå Žåãã¢ã«ãŠã³ãã«ã¯ã¬ãžãããèç©ããŸããããã«ãããã€ã³ã¹ã¿ã³ã¹ã¯é«è² è·æã«CPUæ¶è²»ã«è²»ããããšãã§ããŸã-ããã«ãããéæããç¯çŽã§ããŸããµãŒããŒå®¹éãšé«è² è·ã«å¯Ÿå¿ããããã AWSã䜿çšããŠäœãã©ã®ãããæ¯æããã«ã€ããŠã®è©³çŽ°ã¯ãCTOã®èšäºãåç §ããŠãã ããã
ããæç¹ã§ã®ããŒã³ã®æ®é«ããªããªããŸãããããŒã³ã®æ®é«ã«ãéãè£å ã§ããããããã°ããã®éãããã¯ããã»ã©éèŠã§ã¯ãããŸããã§ãããæã«çŽ20ãã«ããããŸããããã¯ãã³ã³ãã¥ãŒãã£ã³ã°ãã¯ãŒã®ã¬ã³ã¿ã«ã®ç·ã³ã¹ããšããŠã¯ããŸãç®ç«ã¡ãŸããã補åéçºã§ã¯ãããžãã¹èŠä»¶ããå®åŒåãããã¿ã¹ã¯ã«äž»ã«æ³šæãæãã®ãéäŸã§ããããŒã¿ããŒã¹ãµãŒããŒã®å¢å ããCPUæ¶è²»ã¯æè¡çãªè² åµã«é©åããã¯ã¬ãžããæ®é«ãè³Œå ¥ããããã®å°ããªã³ã¹ãã«ãã£ãŠçžæ®ºãããŸãã
ããæŽããæ¥ãç§ã¯æ¯æ¥ã®èŠçŽã«ããããžã§ã¯ãã®ããŸããŸãªéšåã«å®æçã«çŸãããç«ããæ¶ãã®ã«éåžžã«ç²ããŠãããšæžããŠããŸããããããç¶ãå Žåãçãå°œããéçºè ã¯æéãããžãã¹ã¿ã¹ã¯ã«è²»ãããŸããåãæ¥ã«ãç§ã¯ã¡ã€ã³ãããžã§ã¯ããããŒãžã£ãŒã«è¡ããé 眮ã説æããå®æçãªç«çœãšä¿®çã®åå ã調æ»ããæéãæ±ããŸãããåæ ŒããåŸãç§ã¯ããŸããŸãªç£èŠã·ã¹ãã ããããŒã¿ãåéãå§ããŸããã
Newrelicã䜿çšããŠã1æ¥ãããã®åèšå¿çæéã远跡ããŸããç»åã¯æ¬¡ã®ããã«ãªã£ãŠããŸã
ãPostgresãåãå¿çæéã®äžéšãã°ã©ãã§é»è²ã§åŒ·èª¿è¡šç€ºãããŠããŸããã芧ã®ããã«ãå¿çæéã1000ããªç§ã«éããå Žåããããã»ãšãã©ã®å Žåãå¿çãæ€èšããã®ã¯ããŒã¿ããŒã¹ã§ããããããã£ãŠãSQLã¯ãšãªã§äœãèµ·ãã£ãŠãããã確èªããå¿ èŠããããŸãã
PMDSCã¯ãéå±ãª SQLæé©åãžã§ãã®ããã®ã·ã³ãã«ã§ç°¡åãªæ¹æ³ã§ãã
ããããã¬ã€ïŒ
枬å®ããŠãã ããïŒ
ãããæãïŒ
ãããæ³å®ããŠãã ããïŒ
確èªããŠãã ããïŒ
ããããã¬ã€ïŒ
ããããå šäœã®ç·Žç¿ã®äžã§æãéèŠãªéšåã誰ãããSQLã¯ãšãªãæé©åããããšãããã¬ãŒãºãèšããšã倧å€æ°ã®äººã ã¯ãããããã³ãšéå±ã®çºäœãåŒãèµ·ãããŸããããªãããæ¢åµã®èª¿æ»ãšå±éºãªæªåœ¹ãæ¢ãããšèšããšã-ããã¯ããªããããé åçã«ããããªãèªèº«ãæ£ããæ°åã«ãããŸãããããã£ãŠãã²ãŒã ã«åå ããããšãéèŠã§ããç§ã¯æ¢åµãããã®ã楜ããã ãããŒã¿ããŒã¹ã®åé¡ã¯å±éºãªç¯çœªè ãçããç æ°ã®ã©ã¡ããã ãšæããŸããããããŠåœŒã¯ãã·ã£ãŒããã¯ããŒã ãºãã³ãã³ãäžå°ããŸãã¯ãã¯ã¿ãŒããŠã¹ãšããŠã®åœ¹å²ãæ³åããŸãããããªãã®å¥œã¿ã«åã£ãããŒããŒãéžãã§è¡ã£ãŠãã ããïŒ
枬å®ããŠãã ããïŒ
ãªã¯ãšã¹ãã®çµ±èšãåæããããã«ãPgHeroãã€ã³ã¹ããŒã«ããŸãããããã¯ãpg_stat_statements Postgresæ¡åŒµæ©èœããããŒã¿ãèªã¿åãéåžžã«äŸ¿å©ãªæ¹æ³ã§ãã /ã¯ãšãªã«ç§»åããéå»24æéã®ãã¹ãŠã®ã¯ãšãªã®çµ±èšã確èªããŸããããã©ã«ãã§[åèšæé]å-ããŒã¿ããŒã¹ãã¯ãšãªãåŠçããåèšæéã®å²å-容çè ãèŠã€ããããã®è²Žéãªæ å ±æºã«åŸã£ãŠã¯ãšãªã䞊ã¹æ¿ããŸããå¹³åæé-èŠæ±ãå®è¡ãããå¹³ååæ°ãåŒã³åºã-éžæããæéäžã«è¡ããããªã¯ãšã¹ãã®æ°ã PgHeroã¯ããªã¯ãšã¹ãã1æ¥ã«100å以äžå®è¡ãããå¹³åã§20ããªç§ä»¥äžããã£ãå Žåããªã¯ãšã¹ããé ããšèŠãªããŸããéè€ããã€ã³ããã¯ã¹ã®ãªã¹ãã®çŽåŸã«ãããæåã®ããŒãžã®é ãã¯ãšãªã®ãªã¹ãã
ãªã¹ãã®æåã®1ã€ãåããã¯ãšãªã®è©³çŽ°ã確èªããŸããããã«ãåæã®èª¬æãèŠãããšãã§ããŸããèšç»æéãå®è¡æéãããã¯ããã«çãå Žåã¯ããã®ãªã¯ãšã¹ãã«äœãåé¡ãããããã®å®¹çè ã«æ³šæãåããŠããŸãã
PgHeroã«ã¯ç¬èªã®èŠèŠåæ¹æ³ããããŸãããexplain.depesz.comãããã«äœ¿çšããŠãexplainããããŒã¿ãã³ããŒããŠããã«åæããŸããã
çãããã¯ãšãªã®1ã€ã¯ãã€ã³ããã¯ã¹ã¹ãã£ã³ã䜿çšããŠããŸããèŠèŠåã¯ããã®ã€ã³ããã¯ã¹ãå¹æçã§ã¯ãªãã匱ç¹ã§ããããšã瀺ããŠããŸã-èµ€ã§åŒ·èª¿è¡šç€ºãããŠããŸãããããïŒç§ãã¡ã¯å®¹çè ã®è¶³è·¡ã調ã¹ãéèŠãªèšŒæ ãèŠã€ããŸããïŒæ£çŸ©ã¯é¿ããããªãïŒ
ãããæãïŒ
ã¯ãšãªã®åé¡ã®ããéšåã§äœ¿çšããã倧éã®ããŒã¿ãæç»ããŠã¿ãŸããããã€ã³ããã¯ã¹ãã«ããŒããããŒã¿ãšæ¯èŒãããšäŸ¿å©ã§ãã
å°ãã³ã³ããã¹ããã¢ããªã±ãŒã·ã§ã³ã§ãªãŒãã£ãšã³ã¹ãç¶æããæ¹æ³ã®1ã€ããã¹ãããŸãã-çŸå°é貚ãç²åŸã§ããå®ããã®ãããªãã®ã§ããè³ãããã0ãã100ãŸã§ã®æ°åãæšæž¬ããä¹±æ°ãžã§ãã¬ãŒã¿ãåãåã£ãæ°åã«æãè¿ãå Žåã¯ããããå šäœãåããŸããç§ãã¡ã¯ããããã¢ãªãŒãããšåŒã³ãéäŒããããã«ããšåŒã³ãŸããã
調æ»æã®ããŒã¿ããŒã¹ã«ã¯ãçŽ50äžä»¶ã®æŠéèšé²ãå«ãŸããŠããŸãããªã¯ãšã¹ãã®åé¡ã®ããéšåã§ã¯ãã¬ãŒãããŠãŒã¶ãŒã®ãã©ã³ã¹ãè¶ ããŠããããããã«ã®ã¹ããŒã¿ã¹ããã¬ã€ã€ãŒãåŸ ã£ãŠããããã«ãæ¢ããŠããŸããã»ããã®äº€å·®éšåïŒãªã¬ã³ãžè²ã§åŒ·èª¿è¡šç€ºïŒãéåžžã«å°æ°ã®ã¬ã³ãŒãã§ããããšãããããŸãã
ãªã¯ãšã¹ãã®çãããéšåã§äœ¿çšãããã€ã³ããã¯ã¹ã¯ãcreated_atãã£ãŒã«ãã§äœæããããã¹ãŠã®æŠéãã«ããŒããŠããŸãããªã¯ãšã¹ãã¯ãããã40ãéžæãã505330ã¬ã³ãŒããééãã505290ã¯æé€ããŸããããã¯éåžžã«ç¡é§ã«èŠããŸãã
ãããæ³å®ããŠãã ããïŒ
仮説ãç«ãŠãŸããããŒã¿ããŒã¹ã50äžä»¶ã®ã¬ã³ãŒããã40件ãèŠã€ããã®ã«åœ¹ç«ã€ãã®ã¯äœã§ããïŒã¬ãŒããã£ãŒã«ããã«ããŒããã€ã³ããã¯ã¹ãäœæããŠã¿ãŸããããããã¬ãŒã€ãŒãåŸ ã£ãŠããŸããã¹ããŒã¿ã¹ã®æŠéã®ã¿ãéšåã€ã³ããã¯ã¹ãäœæããŸãã
add_index :arena_battles, :bet,
where: "status = 'waiting_for_players'",
name: "index_arena_battles_on_bet_partial_status"
éšåã€ã³ããã¯ã¹ -æ¡ä»¶ã«äžèŽããã¬ã³ãŒãã«ã®ã¿ååšããŸããã¹ããŒã¿ã¹ãã£ãŒã«ãã¯ããã¬ãŒã€ãŒãåŸ æ©äžãã«çãããã¬ãŒããã£ãŒã«ãã«ã€ã³ããã¯ã¹ãä»ããŸã-ã¯ãšãªæ¡ä»¶ã«æ£ç¢ºã«ãããã®ããã®ç¹å®ã®ã€ã³ããã¯ã¹ã䜿çšããããšã¯éåžžã«æçã§ãã40ãããã€ãããããããããã§ã«ãã¬ã€ãããæŠéãã«ããŒããŠããªãããããµã³ãã«ãååŸããå¿ èŠã¯ãããŸãããæ¯èŒã®ããã«ã容çè ã«ãã£ãŠäœ¿çšãããindex_arena_battles_on_created_atã€ã³ããã¯ã¹ã¯çŽ40 MBãèŠããæŠéã®ããŒãã«ã¯çŽ70 MBã§ãããã®ã€ã³ããã¯ã¹ã¯ãä»ã®ã¯ãšãªã§äœ¿çšãããŠããªãå Žåã¯å®å šã«åé€ã§ããŸãã
確èªããŠãã ããïŒ
æ°ããã€ã³ããã¯ã¹ã䜿çšãã移è¡ãæ¬çªç°å¢ã«å±éããæŠéã«ãããšã³ããã€ã³ãã®å¿çãã©ã®ããã«å€åãããã芳å¯ããŸãã
ã°ã©ãã¯ã移è¡ãå±éããæéã瀺ããŠããŸãã12æ6æ¥ã®å€æ¹ã«ãå¿çæéãçŽ500ããªç§ããçŽ50ããªç§ã«çŽ10åã«æžå°ããŸãããæ³å»·ã§å®¹çè ã¯å人ã®å°äœãåããçŸåšã¯ååæã«ããããããïŒ
è±ç
æ°æ¥åŸãç§ãã¡ã¯ç§ãã¡ãæ©ã幞ãã§ããããšã«æ°ä»ããŸãããå人ã¯å ±ç¯è ãèŠã€ããè±åºèšç»ãéçºãå®æœããããã§ãã
12æ11æ¥ã®æãpostgresã¯ãšãªã¹ã±ãžã¥ãŒã©ã¯ãæ°ãã解æãããã€ã³ããã¯ã¹ã䜿çšããããšã¯ãã¯ãæçã§ã¯ãªããšå€æããå€ãã€ã³ããã¯ã¹ãåã³äœ¿çšãå§ããŸããã
Suppose itã¹ããŒãžã«æ»ããŸããïŒããŠã¹å士ã®ç²Ÿç¥ã«åºã¥ããŠéå¥èšºæããŸãšããïŒ
- postgresèšå®ãæé©åããå¿ èŠããããããããŸããã
- å€åãpostgresããã€ããŒãªçšèªã§æ°ããããŒãžã§ã³ã«ã¢ããã°ã¬ãŒãããŸãïŒ9.6.11-> 9.6.15ïŒã
- ãããŠãããããããäžåºŠãã©ã®SQLã¯ãšãªãRailsã圢æããŠãããã泚ææ·±ã調ã¹ãŸããïŒ
3ã€ã®ä»®èª¬ãã¹ãŠããã¹ãããŸãããåŸè ã¯ç§ãã¡ãå ±ç¯è ã®éãžãšå°ããŸããã
SELECT "arena_battles".*
FROM "arena_battles"
WHERE "arena_battles"."status" = 'waiting_for_players'
AND (arena_battles.bet <= 98.13)
AND (NOT EXISTS (
SELECT 1 FROM arena_participations
WHERE arena_battle_id = arena_battles.id
AND (arena_profile_id = 46809)
))
ORDER BY "arena_battles"."created_at" ASC
LIMIT 10 OFFSET 0
ãã®SQLãäžç·ã«èŠãŠãããŸããããã¹ããŒã¿ã¹ãããã¬ãŒã€ãŒãåŸ ã£ãŠããŸããã«çãããã¬ãŒããç¹å®ã®æ°å€ä»¥äžã§ãããã¹ãŠã®æŠå Žãããã«ããŒãã«ããéžæããŸãããããŸã§ã®ãšããããã¹ãŠãæ確ã§ããç¶æ ã®æ¬¡ã®çšèªã¯äžæ°å³ã«èŠããŸãã
NOT EXISTS (
SELECT 1 FROM arena_participations
WHERE arena_battle_id = arena_battles.id
AND (arena_profile_id = 46809)
)
ååšããªããµãã¯ãšãªçµæãæ¢ããŠããŸããããã«IDãäžèŽããåå è ã®ãããã¡ã€ã«ããã¬ã€ã€ãŒã«å±ããŠããããã«åå ããŒãã«ããæåã®ãã£ãŒã«ããååŸããŸãããµãã¯ãšãªã§èšè¿°ãããã»ãããæç»ããŠã¿ãŸãã
ç解ããã®ã¯é£ããã§ãããçµå±ããã®ãµãã¯ãšãªã䜿çšããŠããã¬ã€ã€ãŒããã§ã«åå ããŠããããã«ãé€å€ããããšããŸãããã¯ãšãªã®äžè¬çãªèª¬æãèŠãŠãèšç»æéïŒ0.180ããªç§ãå®è¡æéïŒ12.119ããªç§ãåç §ããŸããå ±ç¯è ãèŠã€ããïŒ
2008幎ããã€ã³ã¿ãŒãããã§å©çšãããŠãããç§ã®ãæ°ã«å ¥ãã®ããŒãã·ãŒãã®æéã§ããããã«ãããŸãïŒ
ã¯ãïŒã¯ãšãªãå¥ã®ããŒãã«ã®ããŒã¿ã«åºã¥ããŠç¹å®ã®æ°ã®ã¬ã³ãŒããé€å€ããå¿ èŠãããäœãã«ééãããšããã«ãã²ããšã«ãŒã«ã®ãããã®ããŒã ãã¡ã¢ãªã«ãããã¢ãã衚瀺ãããŸãã
å®éãããã¯ç§ãã¡ãå¿ èŠãšãããã®ã§ãïŒ
ãã®åçãèªåçšã«ä¿åããããå°å·ããŠãªãã£ã¹ã®ããã€ãã®å Žæã«æããŸãã
ãµãã¯ãšãªãLEFT JOIN WHERE B.key IS NULLã«æžãæãããšã次ã®ããã«ãªããŸãã
SELECT "arena_battles".*
FROM "arena_battles"
LEFT JOIN arena_participations
ON arena_participations.arena_battle_id = arena_battles.id
AND (arena_participations.arena_profile_id = 46809)
WHERE "arena_battles"."status" = 'waiting_for_players'
AND (arena_battles.bet <= 98.13)
AND (arena_participations.id IS NULL)
ORDER BY "arena_battles"."created_at" ASC
LIMIT 10 OFFSET 0
ä¿®æ£ãããã¯ãšãªã¯ã2ã€ã®ããŒãã«ã§åæã«å®è¡ãããŸãããå·Šãã®æŠéãžã®ãŠãŒã¶ãŒã®åå ã®èšé²ãå«ãããŒãã«ãè¿œå ããåå èå¥åãååšããªããšããæ¡ä»¶ãè¿œå ããŸãããåãåã£ãã¯ãšãªãåæããŠèª¬æãèŠãŠã¿ãŸãããïŒèšç»æéïŒ0.185ããªç§ãå®è¡æéïŒ0.337ããªç§ããããïŒããã§ãã¯ãšãªãã©ã³ããŒã¯éšåã€ã³ããã¯ã¹ã䜿çšããããšãããããããšãªããæéã®ãªãã·ã§ã³ã䜿çšããŸããé亡ããå人ãšãã®å ±ç¯è ã¯ãå³æ Œãªæ¿æš©æ©é¢ã§çµèº«åã宣åãããã圌ããè±åºããã®ã¯ãã£ãšé£ããã§ãããã
æŠèŠã¯ç°¡åã§ãã
- NewrelicãŸãã¯ä»ã®åæ§ã®ãµãŒãã¹ã䜿çšããŠãªãŒããèŠã€ããŸããåé¡ã¯ããŒã¿ããŒã¹ã¯ãšãªã«ããããšã«æ°ã¥ããŸããã
- PMDSCãã©ã¯ãã£ã¹ã䜿çšããŠãã ãããããã¯æ©èœãããããã«ããŠãéåžžã«é åçã§ãã
- PgHeroã䜿çšããŠã容çè ãèŠã€ããSQLã¯ãšãªçµ±èšã®æãããã調æ»ããŸãã
- Explain.depesz.comã䜿çšããŠãã ãã-ããã§Explainåæã¯ãšãªãèªãã®ã¯ç°¡åã§ãã
- ãªã¯ãšã¹ããæ£ç¢ºã«äœãããŠãããããããªãå Žåã¯ã倧éã®ããŒã¿ãæç»ããŠã¿ãŠãã ããã
- å¥ã®ããŒãã«ã«ãªããã®ãæ¢ããŠãããµãã¯ãšãªãèŠã€ãããšããé ã®åšãã«ã«ãŒã«ãããã¿ããªç·ãèããŠãã ããã
- æ¢åµãæŒããŠãã ãããããªãã¯ãããžãåŸããããããŸããã