ç¶è¡ããåã«ãã¢ããªã±ãŒã·ã§ã³åŽã®ããŒãžããŒã·ã§ã³ã«èšåããŠãã ããã äžéšã®ã¢ããªã±ãŒã·ã§ã³ã¯ããµãŒããŒæ å ±ã®ãã¹ãŠïŒãŸãã¯ã»ãšãã©ïŒãã¯ã©ã€ã¢ã³ãã«è»¢éããããã®ããŒãžã§å ±æããŸãã å°éã®ããŒã¿ã®å Žåãã¢ããªã±ãŒã·ã§ã³åŽã®ããŒãžããŒã·ã§ã³ãé©åãªéžæãšãªããHTTPåŒã³åºãã®æ°ãæžããŸãã ã¬ã³ãŒããæ°åã«ãªãå§ãããšããã®ã¢ãããŒãã¯å®çšçã§ã¯ãªããªããŸãã ãµãŒããŒåŽã®ããŒãžããŒã·ã§ã³ã«ã¯æ¬¡ã®å©ç¹ããããŸãã
- ã¹ã¿ãŒãããŒãžã®èªã¿èŸŒã¿ãé«éå
- å ±æããŒã¿ãå€æŽããããšãã®ããé«ã粟床
- 倧éã®ããŒã¿ã®é«éæäœ
- ããžãã¹ããžãã¯ã®ã«ãã»ã«å
- éããããªãœãŒã¹ã®ã¯ã©ã€ã¢ã³ãã§ã®ããã©ãŒãã³ã¹ã®åäž
PostgreSQLã¯ãç¹å®ã®ããŒãžã®ã¢ã¯ã»ã¹ãã¿ãŒã³ã®ãµããŒããšåæ§ã«ãé床ãæŽåæ§ïŒã¬ã³ãŒãã倱ããªãïŒãç°ãªãããµãŒããŒåŽã®ç¹å®ã®ããŒãžããŒã·ã§ã³æè¡ãæäŸããŸãã ãã¹ãŠã®ã¡ãœããããã¹ãŠã®ç¶æ³ã§æ©èœããããã§ã¯ãªããäžéšã®ã¡ãœããã¯ç¹å¥ãªããŒã¿ãŸãã¯ã¯ãšãªãå¿ èŠãšããŸãã ã¡ãœãããäžè¬çãªé åºã§æ€èšããŸãããã¹ãŠã®ã¯ãšãªã§æ©èœããã¡ãœããããéå§ããé åºä»ããããããŒã¿ãå¿ èŠãšããã¡ãœããã§ç¶ç¶ããŸãã æçµçã«ãå éšã®PostgreSQLããã€ã¹ã«åºã¥ããããã€ãã®ãšããŸããã¯ãªæ¹æ³ã«ãªããŸãã
ã«ã¹ã¿ã ã¯ãšãªã®åå²
éçãªãã»ãã
æãåçŽãªããŒãžããŒã·ã§ã³æ¹æ³ã§ãããªããããªãã»ãããæãå±éºã§ãã æ®å¿µãªãããããã¯Webéçºãã¥ãŒããªã¢ã«ã®åºç€ã®1ã€ã§ãã ãªããžã§ã¯ããªã¬ãŒã·ã§ãã«ãããã³ã°ïŒORMïŒã©ã€ãã©ãªã«ãããSQLAlchemy .sliceïŒ1ã3ïŒããActiveRecord .limitïŒ1ïŒ.offsetïŒ3ïŒããSequelize .findAllïŒ{ãªãã»ããïŒ3ãå¶éïŒ1}ïŒ ã ã©ãã§ãlimit-offsetã䜿çšãããããšã¯å¶ç¶ã§ã¯ãããŸããããã以äžã®å€æŽãããã«ããªã¯ãšã¹ãã«æ·»ä»ã§ããŸãã
å¶éãšãªãã»ããã®ORMã¡ãœããã¯1ã€ã§ãããããŒãžããŒã·ã§ã³ã®è£å©ã©ã€ãã©ãªã¯ããã«æ¬ºãããšãã§ããŸãã ããšãã°ã人æ°ã®ããKaminari Rubyã©ã€ãã©ãªã¯ããã©ã«ãã§limit-offsetã䜿çšããé«ã¬ãã«ã®ã€ã³ã¿ãŒãã§ãŒã¹ã®èåŸã«é ããŠããŸãã
ãã®ææ³ã«ã¯ãçµæã®äžè²«æ§ãšãã€ã¢ã¹ã®éå¹çæ§ãšãã2ã€ã®å€§ããªåé¡ããããŸãã äžè²«æ§ã¯ãçµæãæž¡ãããšã§ãçç¥ãç¹°ãè¿ããããã«åèŠçŽ ãå³å¯ã«1ååãåãå¿ èŠããããšããäºå®ã«ãããã®ã§ãã ãã€ã¢ã¹ã®éå¹çæ§ã¯ãçµæã倧ããªãã€ã¢ã¹ã«ã·ãããããšãã«çºçããé 延ã«é¢é£ããŠããŸãã
ãªããããªãã»ããããŒãžããŒã·ã§ã³ãççŸããå¯èœæ§ãããæ¹æ³ã次ã«ç€ºããŸãã ãŠãŒã¶ãŒãããŒãžnããããŒãžn + 1ã«ç§»åããåæã«æ°ããèŠçŽ ãããŒãžnã«æ¿å ¥ããããšããŸãã ããã«ãããè€è£œïŒããŒãžnã®æåŸã®èŠçŽ ãããŒãžn + 1ã«æŒãåºãããïŒãšã¹ãããïŒæ°ããèŠçŽ ïŒã®äž¡æ¹ãçºçããŸãã ãããã¯ããŠãŒã¶ãŒãããŒãžn + 1ã«ç§»åããæç¹ã§èŠçŽ nãåé€ããããšããŸãã ããŒãžn + 1ã®ããªããŒããããéå§èŠçŽ ã¯ããŒãžnã«ç§»åããã¹ããããããŸãã
ä»ãéå¹çæ§ã®ãããã¯ã«ã€ããŠã 倧ããªã·ããã¯æ¬åœã«é«äŸ¡ã§ãã ã€ã³ããã¯ã¹ãããå Žåã§ããããŒã¿ããŒã¹ã¯è¡å šäœãã«ãŠã³ãããŠã¹ãã¬ãŒãžå šäœãã¹ãã£ã³ããå¿ èŠããããŸãã ã€ã³ããã¯ã¹ã䜿çšããã«ã¯ãå€ã§åããã£ã«ã¿ãªã³ã°ããå¿ èŠããããŸããããã®å Žåãåã®å€ã«é¢ä¿ãªããç¹å®ã®è¡æ°ãå¿ èŠã§ãã ããã«ãè¡ã¯ä¿åäžã«åããµã€ãºã§ããå¿ èŠã¯ãªãããããã®äžéšã¯ãã£ã¹ã¯äžã«ååšããå ŽåããããŸãããåé€æžã¿ãšããŠããŒã¯ãããŠãããããããŒã¿ããŒã¹ã¯åçŽãªç®è¡ã䜿çšããŠãã£ã¹ã¯é åãèŠã€ããçµæã®èªã¿åããéå§ã§ããŸããã ã¹ããŒããŠã³ã枬å®ããŸãããã
-- CREATE TABLE medley AS SELECT generate_series(1,10000000) AS n, substr(concat(md5(random()::text), md5(random()::text)), 1, (random() * 64)::integer + 1) AS description; -- VACUUM ANALYZE; -- EXPLAIN ANALYZE SELECT * FROM medley LIMIT 100;
æšå®ã³ã¹ãã¯éåžžã«äœãã§ãã
QUERY PLAN -------------------------------------------------------------------------------------------------------------------- Limit (cost=0.00..1.85 rows=100 width=38) (actual time=0.008..0.036 rows=100 loops=1) -> Seq Scan on medley (cost=0.00..185460.60 rows=9999660 width=38) (actual time=0.007..0.017 rows=100 loops=1) Planning time: 0.040 ms Execution time: 0.059 ms (4 rows)
ãªãã»ãã= 1000ãéžæãããšãã³ã¹ãã19ã«ãã©ã³ã¿ã€ã ã0.609ããªç§ã«å€æŽãããŸãã ãªãã»ãã= 5000000ã«ãªããšããã«ãã³ã¹ãã¯ãã§ã«92734ã«ãªããå®è¡æéã¯758.484ããªç§ã«ãªããŸãã
ãããã®åé¡ã¯ããªããããªãã»ããæ¹åŒãããªãã®å Žåã«é©çšã§ããªãããšãå¿ ãããæå³ããŸããã äžéšã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ããŠãŒã¶ãŒã¯éåžžãçµæå ã®å€ãã®ããŒãžãééããŸããããŸãããµãŒããŒåŽã®ããŒãžå¶éã䜿çšããããšãã§ããŸãã ã¢ããªã±ãŒã·ã§ã³ã§ããŒã¿ã®äžæŽåãšããŒãžå¶éãåé¡ã«ãªããªãå Žåã¯ãlimit-offsetã¡ãœãããéåžžã«é©ããŠããŸãã
䜿çšããå ŽåïŒLimit-Offsetã å¶éãããããŒãžããŒã·ã§ã³ã®æ·±ããšäžè²«æ§ã®èš±å®¹ç¯å²ãæã€ã¢ããªã±ãŒã·ã§ã³ã
ã«ãŒãœã«
æ¬ ç¹ã«ãããããããlimit-offsetã¡ãœããã«ã¯ããµãŒããŒã«åœ±é¿ããªããšãã圢ã§ãã©ã¹ããããŸãã ãã®ã¢ãããŒããšã¯å¯Ÿç §çã«ãããŒãžããŒã·ã§ã³ã®å¥ã®æ¹æ³ã§ããã«ãŒãœã«ããããŸãã ãã€ã¢ã¹ãšåæ§ã«ãã«ãŒãœã«ã¯ã©ã®ãªã¯ãšã¹ãã§ã䜿çšã§ããŸããããµãŒããŒãšHTTPã¯ã©ã€ã¢ã³ããä»ãããã©ã³ã¶ã¯ã·ã§ã³ããã®åå¥ã®æ¥ç¶ãå¿ èŠã§ãããšããç¹ã§ç°ãªããŸãã
ã«ãŒãœã«ã®äœ¿çšæ¹æ³ã¯æ¬¡ã®ãšããã§ãã
-- BEGIN; -- DECLARE medley_cur CURSOR FOR SELECT * FROM medley; -- 10 FETCH 10 FROM medley_cur; -- ... -- 10 , , FETCH 10 FROM medley_cur; -- COMMIT;
ã«ãŒãœã«ã«ã¯ãã¯ãšãªã®ããŒãžããŒã·ã§ã³ã®äžè²«æ§ãšããæãŸããããããã£ãããããã©ã³ã¶ã¯ã·ã§ã³ã®éå§æã«ããŒã¿ããŒã¹ã«ååšããçµæã瀺ããŸãã ãã©ã³ã¶ã¯ã·ã§ã³åé¢ã¬ãã«ã«ãããããŒãžåå²ãããçµæãå€ãããªãããšãä¿èšŒãããŸãã
åããŒãžããŒã·ã§ã³ã¢ãããŒãã«ã¯åŒ±ç¹ããããã«ãŒãœã«ãäŸå€ã§ã¯ãããŸããããããã¯ãªãœãŒã¹ã®äœ¿çšãšã¯ã©ã€ã¢ã³ã/ãµãŒããŒãã³ãã«ã«äŸåããŠããŸãã éããŠããåãã©ã³ã¶ã¯ã·ã§ã³ã¯ãããŒã¿ããŒã¹ã«å²ãåœãŠããããªãœãŒã¹ãæ¶è²»ããå€æ°ã®ã¯ã©ã€ã¢ã³ãã«å¯Ÿå¿ã§ããŸããã ãã¡ããããã©ã³ã¶ã¯ã·ã§ã³ã®å€éšã«ååšããå¯èœæ§ã®ããWITH HOLDã«ãŒãœã«ããããŸãããããŒã¿ãå ·äœåããå¿ èŠãããããããããã®ãšã©ãŒã«ãããã«ãŒãœã«ã¯å éšãããã¯ãŒã¯ãªã©ã®çãç¯å²ã®ç¶æ³ã«ã®ã¿é©ããŠããŸãã
ã«ãŒãœã«ãžã®HTTPéä¿¡ã®è¿œå ã¯è€éã§ãã ãµãŒããŒã¯ãããŒã¯ã³ãéããŠããŸãã¯ã»ãã·ã§ã³å ã®ã¯ã©ã€ã¢ã³ãã®IPã¢ãã¬ã¹ãªã©ã®èå¥åãä¿åããããšã«ãã£ãŠããªã¯ãšã¹ãéã§ã¯ã©ã€ã¢ã³ããèå¥ããå¿ èŠããããŸãã ãµãŒããŒã¯ãããŠã³ã¿ã€ã ã®ããã«ãã©ã³ã¶ã¯ã·ã§ã³ããã€è§£æŸãããã決å®ããå¿ èŠããããŸãã æåŸã«ãã¯ã©ã€ã¢ã³ãã¯æ¯åç¹å®ã®ãµãŒããŒã«æ¥ç¶ããå¿ èŠãããããããµãŒããŒã®è² è·ãåæ£ããããšã¯å°é£ã«ãªããŸãã
䜿çšããå ŽåïŒã«ãŒãœã«ã ç¹ã«çµæã®äžè²«æ§ãéèŠãªå Žåã«ããªã¯ãšã¹ããå€æ°ãšå€æ°ã®é åºã§ããŒãžã«åå²ãããåäžãµãŒããŒäžã®ãããã¯ãŒã¯å ã®ã¢ããªã±ãŒã·ã§ã³ã
é åºä»ãã¯ãšãªã®ããŒãžããŒã·ã§ã³
ããŒããŒãžããŒã·ã§ã³
äžèšã®ææ³ã¯ãé åºä»ããããŠããªãã¯ãšãªãå«ããããããã¿ã€ãã®ã¯ãšãªçµæãããŒãžåå²ã§ããŸãã ãã®ã³ãã¥ããã£ãæŸæ£ããæºåãã§ããŠããã°ãæé©åã®ã¡ãªããã享åã§ããŸãã ç¹ã«ãã€ã³ããã¯ã¹åã§ãœãŒãããå ŽåããŠãŒã¶ãŒã¯çŸåšã®ããŒãžã®å€ã䜿çšããŠã次ã®ããŒãžã«è¡šç€ºãããªããžã§ã¯ããéžæã§ããŸãã ããã¯ãããŒã»ããããŒãžããŒã·ã§ã³ãšåŒã°ããŸãã
ããšãã°ãäŸã«æ»ããŸãããã
-- (btrees ) CREATE INDEX n_idx ON medley USING btree (n); SELECT * FROM medley ORDER BY n ASC LIMIT 5;
ç§ã®ã©ã³ãã ããŒã¿ã§ã¯ã次ã®çµæãè¿ãããŸãã
n | description ---+------------------------------------------------------------- 1 | 74f70e009396 2 | 8dac5a085eb670a29058d 3 | fce303a32e89181bf5df1601487 4 | fddcced2c12e83516b3bd6cc94f23a012dfd 5 | f51ae548dd27f51147e53e839eeceb6b0c92922145276d668e73d4a6621 (5 rows)
ããã§ããŠãŒã¶ãŒã¯çµæããæ倧nãèŠãŠãããã䜿çšããŠæ¬¡ã®ããŒãžãåŒã³åºãããšãã§ããŸãã
SELECT * FROM medley WHERE n > 5 ORDER BY n ASC LIMIT 5;
n> 5000000ã§ãã£ã«ã¿ãªã³ã°ããå Žåã§ããlimit-offsetã®äŸãããé«éã«æ©èœããŸãã
QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------- Limit (cost=0.43..0.62 rows=5 width=38) (actual time=0.101..0.103 rows=5 loops=1) -> Index Scan using n_idx on medley (cost=0.43..185579.42 rows=5013485 width=38) (actual time=0.100..0.102 rows=5 loops=1) Index Cond: (n > 5000000) Planning time: 0.071 ms Execution time: 0.119 ms (5 rows)
ãã®ããŒãžããŒã·ã§ã³ã¯é«éã§ãããŒã¿ã®æŽåæ§ãä¿èšŒããŸãã çŸåšã®ããŒãžã«è¿œå /åé€ããŠããçµæã¯å€æŽãããŸããã ãã®æ¹æ³ã®2ã€ã®åŒ±ç¹ã¯ãã©ã³ãã ã¢ã¯ã»ã¹ã®æ¬ åŠãšãã¯ã©ã€ã¢ã³ããšãµãŒããŒéã®æ¥ç¶ã®å¯èœæ§ã§ãã
äžè¬ã«ãåã®ããŒãžã«ã¢ã¯ã»ã¹ããŠæ倧èŠçŽ ã決å®ããã«ãéžæããããŒãžã«ç§»åããæ¹æ³ã¯ãããŸããã ãã ããç¹å®ã®æ¡ä»¶äžã§ã¯ãããè¯ãçµæãåŸãããŸãã ã€ã³ããã¯ã¹ä»ãåã®å€ãåçã«åæ£ããŠããå ŽåïŒãŸãã¯ã¹ããŒã¹ãå«ãŸãªãé£æ¥ããæ°å€ã®æ¹ãè¯ãå ŽåïŒããŠãŒã¶ãŒã¯æ°åŠçãªèšç®ãå®è¡ããŠç®çã®ããŒãžãèŠã€ããããšãã§ããŸãã
EXPLAIN ANALYZE SELECT max(n) FROM medley; QUERY PLAN ------------------------------------------------------------------------------------------------------------ Result (cost=0.46..0.47 rows=1 width=0) (actual time=0.021..0.021 rows=1 loops=1) InitPlan 1 (returns $0) -> Limit (cost=0.43..0.46 rows=1 width=4) (actual time=0.018..0.018 rows=1 loops=1) -> Index Only Scan Backward using n_idx on medley (cost=0.43..284688.43 rows=10000000 width=4) (actual time=0.017..0.017 rows=1 loops=1) Index Cond: (n IS NOT NULL) Heap Fetches: 0 Planning time: 0.087 ms Execution time: 0.042 ms (8 rows)
ããŒå€ã®æ¹ããŒãžã®å¥ã®åé¡ã§ããã¯ã©ã€ã¢ã³ã/ãµãŒããŒæ¥ç¶ã«ã¯æ³šæãå¿ èŠã§ãã æåã¯ããŠãŒã¶ãŒã¯ã©ã®åã«ã€ã³ããã¯ã¹ãä»ããããŠããããç¥ããŸããã ãµãŒããŒã¯ãã¯ã©ã€ã¢ã³ãã«å泚æãèš±å¯ããã®ã§ã¯ãªãããšã³ããã€ã³ãã«äžå®ã®çµæãæäŸããå¯èœæ§ããããŸãã ã¯ã©ã€ã¢ã³ãã«æäŸãããã³ãŒãã¯ãã©ã®åãé åºä»ããããŠããããç¥ããªãå ŽåãããããµãŒããŒã¯æ¬¡ã®ããŒãžãèŠæ±ããæ¹æ³ã«é¢ãããã³ããæäŸããå¿ èŠããããŸãã RFC5988ã¯ãåãšæ¬¡ã®HTTPãªã³ã¯ã®é¢ä¿ãå®çŸ©ããŠããŠãŒã¶ãŒãåŸããªã³ã¯ããšã³ã³ãŒãããŸãã
éåžžããŠãŒã¶ãŒã¯æ å ±ããŒãžã«çŽç·çã«ã¢ã¯ã»ã¹ãããããéåžžãè² è·ã®é«ãWebãµãŒããŒäžã®ã¬ã³ãŒãã®ããŒãžä»ãã«ã¯ããŒå€ã®ããŒãžä»ããåªå ãããŸãã
䜿çšããå ŽåïŒããŒå€ã«ããããŒãžããŒã·ã§ã³ã æ¯èŒã®ããã«ã€ã³ããã¯ã¹ãä»ããããåããé çªã«ããŒã¿ãæäŸããã¹ã±ãŒã©ãã«ãªã¢ããªã±ãŒã·ã§ã³ã ãã£ã«ã¿ãªã³ã°ããµããŒãããŸãã
颚å€ããã§å°éçãªããŒãžããŒã·ã§ã³
ã¯ã©ã¹ã¿ãŒåTIDã¹ãã£ã³
äœã¬ãã«ã®PostgreSQLé¢æ°ã䜿çšããŠãç¹å¥ãªç¶æ³åãã®ã«ã¹ã¿ã ããŒãžããŒã·ã§ã³ã¡ãœãããååŸã§ããŸãã ããšãã°ã次ã®å ŽåãããŒã¿ã«æ¬åœã«ã©ã³ãã ã«ã¢ã¯ã»ã¹ã§ããŸãã
- ããŒãžãåããµã€ãºã«ããå¿ èŠã¯ãããŸãã
- ããŒãžåºåãæååã®åäžæ³šæã®ã¿ããµããŒãããŸã
ç§Theã¯ããã£ã¹ã¯äžã®ããŒã¿ããŒã¹ã®ããŒãžããŸãã¯ãã£ã¹ã¯äžã®ãããã®ããŒãžã®ç¹å®ã®éšåã«ãªã³ã¯ãããŠããè¿ãããããŒãžãéžæããããšã§ãã PostgreSQLããŒã¿ããŒã¹ã®åããŒãã«ã«ã¯ãctidãšåŒã°ããç§å¯ã®åãå«ãŸãããã®è¡ãèå¥ããŸãã
SELECT ctid, * FROM medley WHERE n <= 10; ctid | n | description --------+----+------------------------------------------------------------- (0,1) | 1 | 74f70e009396 (0,2) | 2 | 8dac5a085eb670a29058d (0,3) | 3 | fce303a32e89181bf5df1601487 (0,4) | 4 | fddcced2c12e83516b3bd6cc94f23a012dfd (0,5) | 5 | f51ae548dd27f51147e53e839eeceb6b0c92922145276d668e73d4a6621 (0,6) | 6 | eb9fe1dfe1e421903f96b3b5c5dfe1ee1253582d728c35b4ee7330b (0,7) | 7 | e95202d7f5c612f8523ae705d (0,8) | 8 | 6573b64aff262a2b940326 (0,9) | 9 | a0a43 (0,10) | 10 | 82cdc134bd249a612cfddd3088dd09e32de5f4fa33 (10 rows)
åctidã¯æ¬¡ã®ãšããã§ãïŒïŒããŒãžãè¡ïŒã PostgreSQLã¯ctidã«ãã£ãŠéåžžã«è¿ éã«è¡ãååŸã§ããŸããå®éããããã€ã³ããã¯ã¹ã®ä»çµã¿ã§ããåå€ãctidã«ãã€ã³ãããŸãã
PostgreSQLã¯tidåã«åºã¥ããŠé åºé¢ä¿ãå®çŸ©ããŸãããäžçåŒããctidãå¹ççã«ååŸã§ããªãããšã«æ³šæããŠãã ãã
EXPLAIN ANALYZE SELECT count(1) FROM medley WHERE ctid >= '(0,1)'::tid AND ctid < '(1,0)'::tid; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------- Aggregate (cost=235589.00..235589.01 rows=1 width=0) (actual time=1241.851..1241.852 rows=1 loops=1) -> Seq Scan on medley (cost=0.00..235464.00 rows=50000 width=0) (actual time=477.933..1241.802 rows=116 loops=1) Filter: ((ctid >= '(0,1)'::tid) AND (ctid < '(1,0)'::tid)) Rows Removed by Filter: 9999884 Planning time: 0.047 ms Execution time: 1241.889 ms (6 rows)
ã¬ã³ãžã³ã°ã¯æ©èœããŸãããããã£ã¹ã¯äžã®ããŒãžãããã¹ãŠã®è¡ãå¹ççã«ç §äŒããæ¹æ³ããŸã ãããŸãã åããŒãžã«ã¯ãcurrent_settingïŒ 'block_size'ïŒããŒã¿ãã€ãïŒéåžž8kïŒãå«ãŸããŸãã è¡ã¯32ããããã€ã³ã¿ãŒã«ãã£ãŠãªã³ã¯ãããŠãããããã»ãšãã©ã®å Žåãblock_size /ããŒãžããã4è¡ãå¿ èŠã§ãã ïŒå®éãéåžžãè¡ã¯æå°ãµã€ãºãããåºãããããã¯ãµã€ãºã®4åã®1ãããŒãžäžã®è¡ã®äžéšå¢çãæäŸããŸããïŒæ¬¡ã®ã·ãŒã±ã³ã¹ã¯ãjçªç®ã®ããŒãžã§ãã¹ãŠã®ctidãçæããŸãã
SELECT ('(' || j || ',' || si || ')')::tid FROM generate_series(0,current_setting('block_size')::int/4) AS s(i);
ããã䜿çšããŠããŒãããŒãžã®äŸã®ãã¹ãŠã®è¡ãååŸããŸãã
SELECT * FROM medley WHERE ctid = ANY (ARRAY (SELECT ('(0,' || si || ')')::tid FROM generate_series(0,current_setting('block_size')::int/4) AS s(i) ) );
ã¹ã±ãžã¥ãŒã©ã¯ããã®ãªã¯ãšã¹ããå®è¡ããã³ã¹ããcost = 25.03..65.12ã«æ±ºå®ãã2.765msã§å®è¡ããŸãã ããŒãžçªå·10000ããªã¯ãšã¹ãããŠãåãã³ã¹ãã«ãªããŸãã ãããã£ãŠãç§ãã¡ã¯æ¬åœã«ã©ã³ãã ã¢ã¯ã»ã¹ãååŸããŸãããªããããæããŸãããïŒ
3ã€ã®ããã«ããã¯ããããŸãã
- è¡ãåé€ããããšãããŒãžã«ç©Žãæ®ããŸãã
- è¡ã®é åºã¯éèŠã§ã¯ãããŸããã ããŒã¿ããŒã¹ã¯ãè¡ãåé€ããŠæ®ã£ãç©Žã«è¡ãæ¿å ¥ããŸããããã«ãããè¡ãé åºã©ããã«ãªããŸããã
- ãµããŒããããŠããªãå Žæ
ç¶æ³ã«ãã£ãŠã¯ãããã¯åé¡ã§ã¯ãããŸããã 1ã€ã®ã±ãŒã¹ã¯ããŒã¿ã§ãããèªç¶ãªé åºã¯ãæéééã®å¢åããŒã¿ã®ã¿ãªã©ãããŒã¿ããŒã¹ã«è¿œå ããé åºãšçžé¢ããŠããŸãã ãã1ã€ã¯ãé »ç¹ã«å€æŽãããªãããŒã¿ã§ãã ããã¯ãCLUSTERã³ãã³ãã䜿çšããŠããŒãžäžã®è¡ã®ã¬ã€ã¢ãŠããå¶åŸ¡ã§ãããšããäºå®ã«ãããã®ã§ãã
äŸã«æ»ããŸãããã ãã£ã¹ã¯äžã®ãã®è¡ã¯ãããŒã¿ããŒã¹ã«è¿œå ããé åºã§ãããããæé ã§nåããšã«äžŠã¹ãããŸãã ãããã説æåã§äžŠã¹æ¿ããå Žåã¯ã©ãã§ããããïŒ ãããè¡ãã«ã¯ã説æåã«ã€ã³ããã¯ã¹ãäœæããã¯ã©ã¹ã¿ãªã³ã°ããŠããŒãã«ãç©ççã«åæ§ç¯ããå¿ èŠããããŸãã
CREATE INDEX description_idx ON medley USING btree (description); CLUSTER medley USING description_idx;
æåã®ããŒãžãããã¹ãŠã®è¡ããã§ãããããšã説æåã§ã¢ã«ãã¡ãããé ã«ãœãŒããããããŒã¿ãè¿ãããŸãã ããŒãã«ãå€æŽããããšãæ°ããè¡ã¯ã¢ã«ãã¡ãããé ã®ãªã¹ãããåé€ãããŸãããããŒãã«ãå€æŽãããŠããªãéããè¿ããããªããžã§ã¯ãã¯å®å šãªé åºã«ãªããŸãã ããã«ããã®æäœã¯ããŒãã«ããããã¯ãããŠãŒã¶ãŒãã¢ã¯ã»ã¹ããå¿ èŠãããå Žåã¯å®è¡ã§ããªããšããäºå®ã«ãããããããå€æŽåŸã«å®æçã«åã¯ã©ã¹ã¿ãŒåã§ããŸãã
æåŸã«ããã€ãåäœã®åèšãµã€ãºã䜿çšããŠãããŒãã«ã®ããŒãžã®åèšæ°ã決å®ã§ããŸãã
SELECT pg_relation_size('medley') / current_setting('block_size')::int;
䜿çšããå ŽåïŒTIDã¹ãã£ã³ã é«éã©ã³ãã ã¢ã¯ã»ã¹ãå¿ èŠã§ããã£ã«ã¿ãªã³ã°ãäžèŠãªå Žåã å®è³ªçã«å€åããªãã©ã€ã³å¹ ã§ãå¢å ããæéããŒã¿ã®ã¿ã§ç¹ã«ããŸãæ©èœããŸãã
è©äŸ¡ã¿ãä»ãããŒã»ãã
ãããŸã§èŠãŠããããã«ãããŒã»ããã®éåžžã®ããŒãžããŒã·ã§ã³ã§ã¯ããŠãŒã¶ãŒãæšæž¬ããå Žåãé€ããç¹å®ã®ããŒãžã«ç§»åã§ããŸããã ãã ããPostgreSQLçµ±èšæ å ±ã³ã¬ã¯ã¿ãŒã¯åååžãã¹ãã°ã©ã ããµããŒãããŸãã ãããã®æšå®å€ãå¶éãšå°ããªãªãã»ãããšçµã¿åãããŠäœ¿çšââããŠããã€ããªããã¢ãããŒãã«ããé«éã©ã³ãã ã¢ã¯ã»ã¹ã®ããŒãžããŒã·ã§ã³ãååŸã§ããŸãã
æåã«ããã®äŸã®çµ±èšãèŠãŠã¿ãŸãããã
SELECT array_length(histogram_bounds, 1) - 1 FROM pg_stats WHERE tablename = 'medley' AND attname = 'n';
ç§ã®ããŒã¿ããŒã¹ã§ã¯ãånã«ã¯101ã®å¢çææ°ããããŸãã ãããã®éã®100ã®ç¯å²ã ããŒã¿ãåçã«åæ£ãããŠãããããç¹å®ã®å€ã¯æ··éããŠããŸããã
{719,103188,193973,288794, ⊠,9690475,9791775,9905770,9999847}
æ°å€ã¯æŠç®ã§ãã æåã®æ°åã¯æ£ç¢ºã«0ã§ã¯ãªããæåŸã®æ°åã¯æ£ç¢ºã«1,000äžã§ã¯ãããŸããã ç¯å²ã¯ãæ å ±ããµã€ãºB = 10,000,000 / 100 = 100,000è¡ã®ãããã¯ã«åå²ããŸãã
PostgreSQLçµ±èšã³ã¬ã¯ã¿ã®ãã¹ãã°ã©ã ç¯å²ã䜿çšããŠã確ççã«æ£ããããŒãžãååŸã§ããŸãã ã¯ã©ã€ã¢ã³ãåŽã§WãšçããããŒãžãµã€ãºãéžæããå Žåãiçªç®ã®ããŒãžãååŸããã«ã¯ã©ãããã°ããã§ããïŒ ãããã¯IW / Bã«ããããªãã»ããIWïŒ Bãæã¡ãŸãã
W = 20ãéžæããŠããã¹ããã¿ãŒã³ãã270,000ããŒãžãèŠæ±ããŸãããã
WITH bookmark AS ( SELECT (histogram_bounds::text::int[])[((270000 * 20) / 100000)+1] AS start, (histogram_bounds::text::int[])[((270000 * 20) / 100000)+2] AS stop FROM pg_stats WHERE tablename = 'medley' AND attname = 'n' LIMIT 1 ) SELECT * FROM medley WHERE n >= (select start from bookmark) AND n < (select stop from bookmark) ORDER BY n ASC LIMIT 20 OFFSET ((270000 * 20) % 100000);
ããã¯è¶ é«éã§ãïŒãã®å Žåãã·ããã¯ãŒãã«è¿ãæéã§çºçããããšã«æ³šæããŠãã ããïŒã ã¯ãšãªã¯ãn = 5407259ãã5407278ã®è¡ãè¿ããŸããããŒãž270,000ã®çã®å€ã¯ãn = 5400001ãã5400020ã«çãããªããŸãããã¹ã¯7239ãã€ãŸãçŽ0.1ïŒ ã§ãã
ãã®å Žåã®ããŒãžã®éžæã¯å¹žéã§ããã å¯Ÿç §çã«ã74999ããŒãžã«ã¯99980ã®ãªãã»ãããå¿ èŠã§ãããªãã»ããã¯100,000ãè¶ ããªãããšãããã£ãŠããŸãã劥åãããå Žåã¯ãäžéãå¶åŸ¡ã§ããŸãã PostgreSQLçµ±èšæ å ±ã³ã¬ã¯ã¿ãŒãèšå®ããããšã«ãããããæ£ç¢ºãªåãã¹ãã°ã©ã ãååŸã§ããŸãã
ALTER TABLE medley ALTER COLUMN n SET statistics 1000; VACUUM ANALYZE;
ããã§ã100åã®ãã¹ãã°ã©ã å€ã§ã¯ãªãã1000åã«ãªããŸããã ç§ã®ããŒã¿ããŒã¹ã§ã¯ã次ã®ããã«ãªã£ãŠããŸãã
{10,10230,20863, âŠ, 9980444,9989948,9999995}
åæã«ãã·ããã®ã¹ãããã¯10000以äžã«ãªããŸãããã¬ãŒããªãã¯ãã¹ã±ãžã¥ãŒã©ãããå€ãã®å€ãã¹ãã£ã³ããããã«ãªããŸãããé床ãäœäžããããšã§ãã ãããã£ãŠãããã¯ãã€ã¢ã¹ã®éå¹çæ§ãšçµ±èšæ å ±ã³ã¬ã¯ã¿ã®ãªãŒããŒãããã®äº€å·®ç¹ã§ãã
ãã®ãã€ããªãããªãããŒã»ãã/ãªãã»ãããæ¹åŒã¯ãããããå€ãã®å®éã®ããŒãžããŒã·ã§ã³ã¢ããªã±ãŒã·ã§ã³ã«ã¯é©ããŠããŸããã ãããŠãããã§ã¯ãã©ããæ¡ä»¶ã¯æ©èœããŸããã ããã«ãããŒãã«ãå€æŽãããšããããã³çµ±èšã³ã¬ã¯ã¿ãŒãé·æéèµ·åãããŠããªãå Žåãäžæ£ç¢ºã§ããããŸããŸãäžæ£ç¢ºã«ãªããŸãã
䜿çšããå ŽåïŒè©äŸ¡ããã¯ããŒã¯ä»ãã®ããŒã®ã»ããã ãŠãŒã¶ãŒãè¿œå ã®ãã£ã«ã¿ãªã³ã°ãªãã§ãæ·±ãããããããã®ã©ã³ãã ã¢ã¯ã»ã¹ãå¿ èŠãšããå Žåã
çµè«
ä»ã®å€ãã®ãšã³ãžãã¢ãªã³ã°ãœãªã¥ãŒã·ã§ã³ãšåæ§ã«ãããŒãžããŒã·ã§ã³æè¡ãéžæããã«ã¯åŠ¥åãå¿ èŠã§ãã ããŒã»ããã®ããŒãžããŒã·ã§ã³ã¯ãç·åœ¢ã¢ã¯ã»ã¹ãé åºä»ããããäžèŠæš¡ãµã€ãã«æãé©ããŠãããšç¢ºä¿¡ã§ããŸãã ãã ããå¶é/ãªãã»ããæ¹åŒã«ãç¬èªã®é·æãããããããšããŸããã¯ãªæ¹åŒã¯ç¹å®ã®ã¿ã€ãã®ããŒã¿ã«å¯ŸããŠç¹å¥ãªããã©ãŒãã³ã¹ç¹æ§ãæäŸããŸãã ã芧ã®ãšãããããªãã®æ°ã®å¯èœæ§ããããŸãã ãžã§ãã«é©ããããŒã«ãéžæããããŒãžããŒã·ã§ã³ãéããæ¬ã«ããªãã§ãã ããã