ããããã log_lock_waitsãšã®ãããã¯ã®ç«¶åãæ¢ããŠããããã¬ãŒã¯ãã€ã³ãã®åäœãç£èŠããŠããããªã©ã
ãããããããã¯ãŒã¯é 延ã«ã€ããŠèããããšã¯ãããŸããïŒ ãã¬ãŒã€ãŒã¯ãããç¥ã£ãŠããŸãããããã¯ã¢ããªã±ãŒã·ã§ã³ã䜿çšãããµãŒããŒã«é¢é£ããŠããŸããïŒ
é 延ã®åœ±é¿
äžè¬çãªã¯ã©ã€ã¢ã³ã/ãµãŒããŒãªã³ã°ãããã¯ãŒã¯ã®é 延ã¯ã0.01ããªç§ïŒããŒã«ã«ïŒããã¹ã€ããããããã¯ãŒã¯ã§ã0.5ããªç§ãWiFiã§5ããªç§ãADSLã§20ããªç§ã倧éžéã«ãŒãã£ã³ã°ã§300ããªç§ãè¡æãWWANãªã©ã§ããã«å€åããŸããªã³ã¯ã
äºçŽ°ãªSELECTã¯ããµãŒããŒåŽã§å®è¡ããã®ã«çŽ0.1 msããããŸãã èªæãªæ¿å ¥ 0.5ããªç§ã
ã¢ããªã±ãŒã·ã§ã³ãèŠæ±ãå®è¡ãããã³ã«ãæå/ãšã©ãŒãå Žåã«ãã£ãŠã¯çµæãèŠæ±ã¡ã¿ããŒã¿ãªã©ãå«ããµãŒããŒããã®å¿çãåŸ æ©ããå¿ èŠããããŸãã ããã«ã¯ããããã¯ãŒã¯äžã§å°ãªããšã1ã€ã®åŸåŸ©é 延ã䌎ããŸãã
äž»ã«å°èŠæš¡ã§åçŽãªã¯ãšãªã䜿çšããå ŽåãããŒã¿ããŒã¹ãšã¢ããªã±ãŒã·ã§ã³ãç°ãªããµãŒããŒäžã«ãããšããããã¯ãŒã¯é 延ãå®è¡æéã«å€§ãã圱é¿ããå¯èœæ§ããããŸãã
ã»ãšãã©ã®ã¢ããªã±ãŒã·ã§ã³ãç¹ã«ORMã¯ãéåžžã«åçŽãªã¯ãšãªãå€æ°å®è¡ããåŸåããããŸãã ããšãã°ãHibernateã¢ããªã±ãŒã·ã§ã³ããé 延ããŠæœåºããã1000åã®åãªããžã§ã¯ããžã®@OneToManyãªã¬ãŒã·ã§ã³ãä»ããŠãšã³ãã£ãã£ãååŸããå Žåãn + 1ãã§ããã®åé¡ã«ããããããã1001ãªã¯ãšã¹ããå®è¡ããäºå®ã§ãã ããã¯ãåŸ æ©äžã®åŸåŸ©ãã¹ã§ãããã¯ãŒã¯ãæ°ååé 延ãããããšãæå³ããŸãã ãããåé¿ããããã«å·Šçµåãã§ããã䜿çšã§ããŸããããã®åŸã芪èŠçŽ ã1000åJOINã«æž¡ããéè€æé€ããå¿ èŠããããŸãã
åæ§ã«ãORMãä»ããŠããŒã¿ããŒã¹ã«ããŒã¿ãå ¥åããå Žåãããããæ°åäžã®éåžžã®INSERTãå®è¡ãããµãŒããŒããã®åã ã®INSERTã®ç¢ºèªããã¹ãŠå®äºããããšãåŸ æ©ããŸãã
ã¯ãšãªã®å®è¡æéã«éäžããŠæé©åãè©Šã¿ãã®ã¯ååç°¡åã§ãããæãåçŽãªINSERT INTO ... VALUES ...ã§ã§ããããšã«ã¯å€æ°ã®ãªãã·ã§ã³ããããŸãã ããã€ãã®ã€ã³ããã¯ã¹ãšå¶çŽãåé€ãããã©ã³ã¶ã¯ã·ã§ã³å ã«ããããšã確èªããã°ãã»ãŒå®äºã§ãã
ãããããããã¯ãŒã¯ã®ãã¹ãŠã®æåŸ ãåãé€ãã®ã¯ã©ãã§ããïŒ ããŒã«ã«ãããã¯ãŒã¯äžã§ãã£ãŠãã1000åã®ãªã¯ãšã¹ãã®åŸãæé·ãå§ããŸãã
ã³ããŒ
é 延ãåé¿ãã1ã€ã®æ¹æ³ã¯ã COPYã䜿çšããããšã§ãã PostgreSQlã®COPYãµããŒãã䜿çšããã«ã¯ãã¢ããªã±ãŒã·ã§ã³ãŸãã¯ãã©ã€ããŒãCSVã®ãããªæååã®ã»ãããçæããé£ç¶ããã·ãŒã±ã³ã¹ã§ãµãŒããŒã«ãããŒããã£ã¹ãããå¿ èŠããããŸãã ãŸãã¯ããµãŒããŒãã¢ããªã±ãŒã·ã§ã³ã«CSVã®ãããªã¹ããªãŒã ãéä¿¡ããããã«æ±ããããå ŽåããããŸãã
ãããã®å Žåã§ããã¢ããªã±ãŒã·ã§ã³ã¯COPYãä»ã®ã¯ãšãªãšåãæ¿ããããšã¯ã§ãããã³ããŒãšè²Œãä»ããå®å ããŒãã«ã«çŽæ¥ããŒãããå¿ èŠããããŸãã äžè¬çãªã¢ãããŒãã¯ãCOPYãäžæããŒãã«ã«äœæãããã®ããŒãã«ãããã§ã«INSERT INTO ... SELECT ...ãUPDATE ... FROM ....ãDELETE FROM ... USING ...ãªã©ã䜿çšããŠã 1ã€ã®æäœã§ã¡ã€ã³ããŒãã«ãå€æŽããããã®ã³ããŒãããããŒã¿ã
ããã¯ãç¬èªã®SQLãçŽæ¥èšè¿°ããå Žåã«äŸ¿å©ã§ããããã¬ãŒã ã¯ãŒã¯ãšORMã¯ããããµããŒãããŠããŸãããããã«ãåçŽãªæ¿å ¥ã®ã¿ãçŽæ¥çœ®ãæããããšãã§ããŸãã ã¢ããªã±ãŒã·ã§ã³ããã¬ãŒã ã¯ãŒã¯ããŸãã¯ãŠãŒã¶ãŒãã©ã€ããŒã¯ãCOPYã«å¿ èŠãªç¹å¥ãªãã¬ãŒã³ããŒã·ã§ã³ãåŠçãããã®ããã«å¿ èŠãªã¡ã¿ããŒã¿ãæ¢ãå¿ èŠããããŸãã
ïŒCOPYãå®éã«ãµããŒãããããç¥ãããŠãããã©ã€ããŒã«ã¯ãlibpqãPgJDBCãpsycopg2ãPg gemãªã©ããããŸããããããã«åºã¥ããŠæ§ç¯ããããã¬ãŒã ã¯ãŒã¯ãšORMSãCOPYããµããŒãããå¿ èŠã¯ãããŸãããïŒ
PgJDBC-ã°ã«ãŒãåã¢ãŒã
PostgreSQLã®JDBCãã©ã€ããŒã«ã¯ããã®åé¡ã«å¯Ÿãã解決çããããŸãã JDBCãã©ã€ããŒAPIã®ã°ã«ãŒãåã®æ©èœã«åºã¥ããŠããŸãããµãŒããŒã«èŠæ±ã®ã°ã«ãŒããéä¿¡ãããã®åŸãã»ããå šäœãæåããããšã確èªããã®ã1åã ãåŸ æ©ããŸãã
å°ãªããšãçè«çã«ã¯ã å®éãããã€ãã®å®è£ äžã®åé¡ã«ããããã®ãã¹ãŠãäžåºŠã«ãã³ãã«ããšã«æ°çŸã®ãªã¯ãšã¹ãã«å¶éãããŸãã ãŸãããã©ã€ããŒã¯ãçµæãæéã®çµéãšãšãã«ã©ãã ã倧ãããªãããå€æã§ããå Žåã«ãçµæãã»ãããšããŠè¿ãã¯ãšãªã®ã¿ãå®è¡ã§ããŸãã ãããã®å¶éã«ããããããã Statement.executeBatchïŒïŒã䜿çšãããšããªã¢ãŒãããŒã¿ããŒã¹ã€ã³ã¹ã¿ã³ã¹ããã®ããŒã¿ã®ãã«ã¯ããŒããªã©ã®ã¿ã¹ã¯ãå®è¡ããã¢ããªã±ãŒã·ã§ã³ã®ããã©ãŒãã³ã¹ãå€§å¹ ã«åäžããŸãã
ããã¯æšæºAPIã§ãããããè€æ°ã®DBMSã§å®è¡ãããã¢ããªã±ãŒã·ã§ã³ã§äœ¿çšã§ããŸãã ããšãã°ãHibernateã¯JDBCã°ã«ãŒãåã䜿çšã§ããŸãããããã©ã«ãã§ã¯ãããè¡ããŸããã
libpqãšã°ã«ãŒãå
ä»ã®ã»ãšãã©ã®ïŒãã¹ãŠïŒïŒPostgreSQLãã©ã€ããŒã¯ã°ã«ãŒãåããµããŒãããŠããŸããã PgJDBCã¯PostgreSQLãããã³ã«ãå®å šã«ç¬ç«ããŠäœ¿çšããŸãããä»ã®ã»ãšãã©ã®ãã©ã€ããŒã¯PostgreSQLã®äžéšãšããŠæäŸãããC libpqã©ã€ãã©ãªã䜿çšããŸãã
libpqã«ã¯éåæã®éããããã³ã°APIããããŸããããŠãŒã¶ãŒã¯äžåºŠã«1ã€ã®ã¯ãšãªã®ã¿ãå®è¡ã§ããŸãã 次ã®ã¯ãšãªãéä¿¡ããåã«ããã®ã¯ãšãªã®çµæãåä¿¡ãããã®ãåŸ ã€å¿ èŠããããŸãã
PostgreSQLãµãŒããŒã¯ã°ã«ãŒãåãããŸããµããŒãããŠãããPgJDBCã¯ãã§ã«ããã䜿çšããŠããŸãã ãã®ç¹ã§ã ç§ã¯libpqã®ã°ã«ãŒãåãµããŒããäœæã ãPostgreSQLã®æ¬¡ã®ããŒãžã§ã³ã§ææ¡ããŸãã ã 確èªãããå Žåãã¯ã©ã€ã¢ã³ããå€æŽããã ããªã®ã§ãå€ããµãŒããŒã«æ¥ç¶ãããšãã®ããã»ã¹ãããã«é«éåããŸãã
èè ããã³libpqããŒã¹ã®ãŠãŒã¶ãŒãã©ã€ããŒã®äžçŽãŠãŒã¶ãŒãšlibpqããŒã¹ã®ã¢ããªã±ãŒã·ã§ã³ã®éçºè ããã®ãã£ãŒãããã¯ã«éåžžã«èå³ããããŸãã ãããã¯ãè©ŠããŠã¿ããå Žåã«PostgreSQLããŒãžã§ã³9.6ããŒã¿1ã«æ£åžžã«é©çšãããŸãã 詳现ãªããã¥ã¡ã³ããšå æ¬çãªãµã³ãã«ããã°ã©ã ãçšæãããŠããŸã ã
æ§èœ
RDSãŸãã¯Heroku Postgresã«åºã¥ããDBMSãµãŒããŒã¯ã説æãããŠããæ©èœãæçšãªå¥œäŸã§ãã ç¹ã«ãèªåã®ãããã¯ãŒã¯ã®å€éšãããããã«ã¢ã¯ã»ã¹ãããšãé 延ãã©ã®ããã«æå·ããå¯èœæ§ãããããå®å šã«ç€ºããŠããŸãã
ã320ããªç§ã®ãããã¯ãŒã¯é 延ïŒ
- ã°ã«ãŒãåãªãã®500æ¿å ¥ïŒ167.0ç§
- ã°ã«ãŒãåã«ãã500ã®æ¿å ¥ïŒ1.2ç§
...ããã¯çŽ120åé«éã§ãã
ååãšããŠãã¢ããªã±ãŒã·ã§ã³ãé 眮ãããŠãããµãŒããŒãšããŒã¿ããŒã¹ãé 眮ãããŠãããµãŒããŒéã§å€§éžéæ¥ç¶ã䜿çšããªãã§ãã ããããããã®åããµãŒããŒã䜿çšããŠãé 延ã®åœ±é¿ã瀺ããŸãã ããŒã«ã«ãã¹ãäžã®Unixãœã±ããã䜿çšããŠãã10,000åã®æ¿å ¥ã§ããã©ãŒãã³ã¹ã50ïŒ åäžããŸããã
æ¢åã®ã¢ããªã±ãŒã·ã§ã³ã®ã°ã«ãŒãå
æ®å¿µãªãããæ¢åã®ã¢ããªã±ãŒã·ã§ã³ã®ã°ã«ãŒãåãèªåçã«æå¹ã«ããããšã¯ã§ããŸããã äžé£ã®èŠæ±ãéä¿¡ããŠããçµæãèŠæ±ããå Žåããããã«ç°ãªãã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšããå¿ èŠããããŸãã
ç¹ã«ãéããããã³ã°ã¢ãŒããšselectïŒïŒ/ pollïŒïŒ/ epollïŒïŒ/ WaitForMultipleObjectsExã«ãŒãã䜿çšããå Žåã¯ãéåælibpqã€ã³ã¿ãŒãã§ãŒã¹ãæ¢ã«äœ¿çšããŠããã¢ããªã±ãŒã·ã§ã³ãé©å¿ãããã®ã¯ç°¡åã§ã ã åælibpqã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšããã¢ããªã±ãŒã·ã§ã³ã§ã¯ãããã«å€æŽãå¿ èŠã«ãªããŸãã
ä»ã®ã«ã¹ã¿ã ãã©ã€ããŒã®ã°ã«ãŒãå
åæ§ã«ããŠãŒã¶ãŒãã©ã€ããŒããã¬ãŒã ã¯ãŒã¯ãããã³ORMã¯éåžžãã°ã«ãŒãåãå¯èœã«ããããã«ã€ã³ã¿ãŒãã§ã€ã¹ãšå éšå€æŽãå¿ èŠãšããŸãã æ¢ã«ã€ãã³ãã«ãŒããšãã³ããããã³ã°I / Oã䜿çšããŠããå Žåã¯ãããªãç°¡åã«å€æŽã§ããŸãã
PythonãRubyãããã³ãã®æ©èœã䜿çšã§ããä»ã®ãŠãŒã¶ãŒã«äŒããŠå¬ããã®ã§ã誰ãèå³ãæã£ãŠããããç¥ãããã§ãã ãããã§ãããšæ³åããŠãã ããïŒ
import psycopg2 conn = psycopg2.connect(...) cur = conn.cursor() # this is just an idea, this code does not work with psycopg2: futures = [ cur.async_execute(sql) for sql in my_queries ] for future in futures: result = future.result # waits if result not ready yet ... process the result ... conn.commit()
éåæã®ã°ã«ãŒãåã¯ããŠãŒã¶ãŒãè€éã«ããå¿ èŠã¯ãããŸããã
COPYã¯æéã§ã
å®çšçãªé¡§å®¢ã¯ãŸã ã³ããŒã奜ãã ããã«ç§ã®ã©ãããããããã®ããã€ãã®çµæããããŸãïŒ
inserting 1000000 rows batched, unbatched and with COPY batch insert elapsed: 23.715315s sequential insert elapsed: 36.150162s COPY elapsed: 1.743593s Done.
äœæ¥ãã°ã«ãŒãåãããšãããŒã«ã«UNIXãœã±ããã§ãé©ãã»ã©å€§ããªããã©ãŒãã³ã¹ãåäžããŸãããCOPYã§ã¯ãåã ã®INSERTã¢ãããŒãã®äž¡æ¹ãã¯ããã«é ããŠããŸãã
COPYã䜿çšããŸãã
ç»å
ãã®èšäºã®ç»åã¯ã西ãªãŒã¹ãã©ãªã¢ã®ããŒã¹è¿ãã®ãã³ããªã³ã°ãŠã£ã¢ãŒããå éšïŒç æŒ ïŒã®éé±å±±ãŸã§ã®ãŽãŒã«ããã£ãŒã«ãºçµŠæ°Žã¹ããŒã ãã€ãã©ã€ã³ã§ãã 圌女ã¯ãã®èšäºã«ã¢ãããŒãããŸãããªããªãããã®å»ºèšã®é·ããšæ¹å€ã®ããã§ããã®åµå§è ã§ããäž»ãªåµå§è ã§ããCY O'Connorã¯ããã€ãã©ã€ã³ãå§èšããã12ã¶æåã«èªæ®ºããããã§ãã å°å ã®äººã ã¯ããã€ãã©ã€ã³ãéãããåŸã«åœŒã亡ããªã£ããšãã°ãã°ïŒééã£ãŠïŒèšããŸãããæ°Žã¯æµããŸããã§ãã-ãã€ãã©ã€ã³ãããžã§ã¯ãã倱æã§ãããšèª°ããèããã»ã©æéãããããŸããã ããããæ°é±éåŸãæ°Žã¯è¡ããŸããã