ãŸããã
ãã®äžé£ã®èšäºã§ã¯ãPostgreSQLã®ã€ã³ããã¯ã¹ã«çŠç¹ãåœãŠãŸãã
質åã¯ããŸããŸãªèгç¹ããæ€èšã§ããŸãã DBMSã䜿çšããã¢ããªã±ãŒã·ã§ã³éçºè
ãé¢å¿ãæããªããã°ãªããªããã®ãååšããã€ã³ããã¯ã¹ãPostgreSQLã«éåžžã«å€ãã®ç°ãªãã€ã³ããã¯ã¹ãããçç±ããããã䜿çšããŠã¯ãšãªãé«éåããæ¹æ³ã«ã€ããŠèª¬æããŸãã ããããããã®ãããã¯ã¯å°æ°ã®èšèã§æããã«ããããšãã§ããŸãããç¹ã«å
éšæ§é ã®è©³çްã«ãèå³ããã奜å¥å¿developerçãªéçºè
ã«ã¯ãä»ã®èª°ãã®æèŠãèãã ãã§ãªããç§ãã¡èªèº«ã®çµè«ãåŒãåºãããšãã§ãããããå
éšæ§é ã®è©³çްã«ãèå³ãæã£ãŠããŸãã
è°è«ä»¥å€ã§ã¯ãæ°ããã¿ã€ãã®ã€ã³ããã¯ã¹ã®éçºãæ®ããŸãã ããã«ã¯Cèšèªã®ç¥èãå¿
èŠã§ãããã¢ããªã±ãŒã·ã§ã³éçºè
ãããã·ã¹ãã ããã°ã©ããŒã®èœåã«é¢é£ããŠããŸãã åãçç±ã§ãå®éã«ã¯ãœãããŠã§ã¢ã€ã³ã¿ãŒãã§ã€ã¹ãèæ
®ãããããã«äœ¿çšã§ããã€ã³ããã¯ã¹ã䜿çšããããã«éèŠãªããšã ãã«çŠç¹ãåãããŸãã
ãã®ããŒãã§ã¯ãããŒã¿ããŒã¹ãšã³ãžã³ã«é¢é£ããäžè¬çãª
ã€ã³ããã¯ã¹äœæã¡ã«ããºã ãšãPostgreSQLã®æ¡åŒµæ©èœãšããŠè¿œå ã§ããåã
ã®ã€ã³ããã¯ã¹ã¢ã¯ã»ã¹æ¹æ³ãšã®éã®è²¬ä»»ã®åå²ã«ã€ããŠèª¬æããŸãã æ¬¡ã®éšåã§ã¯
ãã¢ã¯ã»ã¹æ¹æ³ã®ã€ã³ã¿ãŒãã§ã€ã¹ãšãã¯ã©ã¹ãæŒç®åæãªã©ã®éèŠãªæŠå¿µã
èŠãŠãã
ãŸã ã ãã®ãããªé·ããå¿
èŠãªå°å
¥ã®åŸãããŸããŸãªã¿ã€ãã®ã€ã³ããã¯ã¹ã®ããã€ã¹ãšã¢ããªã±ãŒã·ã§ã³ã詳现ã«èŠãŠãããŸãïŒ
Hash ã
B-tree ã
GiST ã
SP-GiST ã
GINãš
RUM ã
BRINãš
Bloom ã
ææ°
PostgreSQLã®ã€ã³ããã¯ã¹ã¯ãäž»ã«ããŒã¿ãžã®ã¢ã¯ã»ã¹ãé«éåããããã«èšèšãããç¹å¥ãªããŒã¿ããŒã¹ãªããžã§ã¯ãã§ãã ãããã¯è£å©æ§é ã§ããããŒãã«å
ã®æ
å ±ããã€ã³ããã¯ã¹ãåé€ããã³åŸ©å
ã§ããŸãã DBMSãã€ã³ããã¯ã¹ãªãã§ããã£ãããšåäœã§ãããšèãããšããããŸãã ãã ããããã¯ããã§ã¯ãããŸãããããã¯ãã€ã³ããã¯ã¹ãäžéšã®æŽåæ§å¶çŽããµããŒãããããã«ã圹ç«ã€ããã§ãã
çŸåšãPostgreSQL 9.6ã«ã¯6çš®é¡ã®ã€ã³ããã¯ã¹ãçµã¿èŸŒãŸããŠããŸããããã1ã€ã¯æ¡åŒµæ©èœãšããŠå©çšå¯èœã§ããããã¯ãããŒãžã§ã³9.6ã®éèŠãªå€æŽã«ããå¯èœã«ãªããŸããã ãã®ãããè¿ãå°æ¥ãä»ã®çš®é¡ã®ã€ã³ããã¯ã¹ã®åºçŸãæåŸ
ããå¿
èŠããããŸãã
ã€ã³ããã¯ã¹ã®ã¿ã€ãïŒ
ã¢ã¯ã»ã¹æ¹æ³ãšãåŒã°ã
ãŸã ïŒã®ãã¹ãŠã®éãã«ãããããããæçµçã«ãããã®ãããããããŒïŒããšãã°ãã€ã³ããã¯ã¹ä»ãåã®å€ïŒãšãã®ããŒãçºçããããŒãã«ã®è¡ãšã®éã®å¯Ÿå¿ã確ç«ããŸãã è¡ã¯ããã¡ã€ã«ãããã¯çªå·ãšãããã¯å
ã®è¡ã®äœçœ®ã§æ§æãããTIDïŒã¿ãã«IDïŒã䜿çšããŠèå¥ãããŸãã æ¬¡ã«ãããŒãŸãã¯ããŒã«é¢ããæ
å ±ãç¥ã£ãŠããã°ãããŒãã«å
šäœãèŠãªããŠããé¢å¿ã®ããæ
å ±ãèŠã€ããè¡ããã°ããèªãããšãã§ããŸãã
ã€ã³ããã¯ã¹ã¯ãããŒã¿ãžã®ã¢ã¯ã»ã¹ãå éãã代ããã«ãã¡ã³ããã³ã¹ã«ç¹å®ã®ã³ã¹ããå¿
èŠãšããããšãçè§£ããããšãéèŠã§ãã ããŒãã«è¡ã®æ¿å
¥ãåé€ãæŽæ°ãªã©ãã€ã³ããã¯ã¹ä»ãããŒã¿ã«å¯Ÿããæäœã§ã¯ããã®ããŒãã«çšã«äœæãããã€ã³ããã¯ã¹ã¯ãåããã©ã³ã¶ã¯ã·ã§ã³å
ã§åæ§ç¯ããå¿
èŠããããŸãã ã€ã³ããã¯ã¹ãäœæãããªãã£ãããŒãã«ãã£ãŒã«ããæŽæ°ããŠããã€ã³ããã¯ã¹ã¯åæ§ç¯ãããŸããã ãã®ã¡ã«ããºã ã¯HOTïŒããŒãã®ã¿ã®ã¿ãã«ïŒãšåŒã°ããŸãã
æ¡åŒµæ§ã«ã¯ããã€ãã®æå³ããããŸãã æ°ããã¢ã¯ã»ã¹æ¹æ³ãã·ã¹ãã ã«ç°¡åã«çµ±åã§ããããã«ãäžè¬çãªã€ã³ããã¯ã¹äœæã¡ã«ããºã ãPostgreSQLã«å²ãåœãŠãããŠããŸãã ãã®äž»ãªã¿ã¹ã¯ã¯ãã¢ã¯ã»ã¹æ¹æ³ããTIDãååŸããããããæäœããããšã§ãã
- ããŒãã«è¡ã®å¯Ÿå¿ããããŒãžã§ã³ããããŒã¿ãèªã¿åããŸãã
- åå¥ã®TIDã«ãããµã³ããªã³ã°ããŸãã¯ïŒããããããã®æ§ç¯ã䌎ãïŒTIDã®ã»ããã«ãã峿ãµã³ããªã³ã°ã
- åé¢ã¬ãã«ãèæ
®ããŠãçŸåšã®ãã©ã³ã¶ã¯ã·ã§ã³ã®è¡ããŒãžã§ã³ã®å¯èŠæ§ã確èªããŸãã
ã€ã³ããã¯ã¹äœæã¡ã«ããºã ã¯ã¯ãšãªã®å®è¡ã«é¢äžããŸãã æé©å段éã§äœæãããèšç»ã«åŸã£ãŠåŒã³åºãããŸãã ã¯ãšãªå®è¡ã®ããŸããŸãªæ¹æ³ããœãŒãããã³è©äŸ¡ãããªããã£ãã€ã¶ã¯ãé©çšãããå¯èœæ§ã®ãããã¹ãŠã®ã¢ã¯ã»ã¹æ¹æ³ã®æ©èœãçè§£ããå¿
èŠããããŸãã ã¢ã¯ã»ã¹æ¹æ³ã¯ãæ£ããé åºã§ããã«ããŒã¿ãæäŸããããšãã§ããŸããããŸãã¯ãœãŒããåå¥ã«æäŸããå¿
èŠããããŸããïŒ nullãæ€çŽ¢ããããã«ã¢ã¯ã»ã¹æ¹æ³ãé©çšããããšã¯å¯èœã§ããïŒ -ãã®ãããªè³ªåã¯ãªããã£ãã€ã¶ãŒã«ãã£ãŠåžžã«è§£æ±ºãããŸãã
ã¢ã¯ã»ã¹æ¹æ³ã«é¢ããæ
å ±ã¯ããªããã£ãã€ã¶ãŒã ãã§ãªãå¿
èŠã§ãã ã€ã³ããã¯ã¹ãäœæãããšããã·ã¹ãã ã¯ä»¥äžã決å®ããå¿
èŠããããŸããè€æ°ã®åã«ããã£ãŠã€ã³ããã¯ã¹ãæ§ç¯ããããšã¯å¯èœã§ããïŒ ãã®ã€ã³ããã¯ã¹ã¯äžææ§ãæäŸã§ããŸããïŒ
ãã®ãããåã¢ã¯ã»ã¹æ¹æ³ã¯ãããèªäœã«é¢ããå¿
èŠãªæ
å ±ããã¹ãŠæäŸããå¿
èŠããããŸãã ããŒãžã§ã³9.6ããåã§ã¯ããã®ããã«pg_amããŒãã«ã䜿çšãããŠããŸããã9.6ããã¯ãããŒã¿ã¯ç¹å¥ãªé¢æ°ã«ããæ·±ãç§»è¡ããŸããã ãã®ã€ã³ã¿ãŒãã§ã€ã¹ã«ã€ããŠã¯ãåŸã»ã©è©³ãã説æããŸãã
ã¢ã¯ã»ã¹æ¹æ³èªäœã®ã¿ã¹ã¯ã«ã¯ãä»ã®ãã¹ãŠãå«ãŸããŸãã
- ã€ã³ããã¯ã¹ãæ§ç¯ããããŒã¿ã®ããŒãžããŒã·ã§ã³ãè¡ãã¢ã«ãŽãªãºã ã®å®è£
ïŒãã¹ãŠã®ã€ã³ããã¯ã¹ããããã¡ãã£ãã·ã¥ãããŒãžã£ã«ãã£ãŠåãæ¹æ³ã§åŠçãããããã«ïŒ;
- åŒ " indexed-field operator expression "ã«ãã£ãŠã€ã³ããã¯ã¹å
ã®æ
å ±ãæ€çŽ¢ããŸãã
- ã€ã³ããã¯ã¹ã®äœ¿çšã³ã¹ãã®è©äŸ¡ã
- ããã»ã¹ã®æ£ãã䞊åå®è¡ã«å¿
èŠãªããã¯ãæäœããŸãã
- å
è¡æžã蟌ã¿ãã°ïŒWALïŒã®çæã
ãŸããäžè¬çãªã€ã³ããã¯ã¹äœæã¡ã«ããºã ã®å¯èœæ§ãæ€èšããæ¬¡ã«ããŸããŸãªã¢ã¯ã»ã¹æ¹æ³ãæ€èšããŸãã
ã€ã³ããã¯ã¹äœæã¡ã«ããºã
ã€ã³ããã¯ã¹äœæã¡ã«ããºã ã«ãããPostgreSQLã¯ãã®æ©èœãèæ
®ããŠãããŸããŸãªã¢ã¯ã»ã¹æ¹æ³ã§åçã«åäœã§ããŸãã
åºæ¬çãªã¹ãã£ã³æ¹æ³
ã€ã³ããã¯ã¹ã¹ãã£ã³
ã€ã³ããã¯ã¹ã«ãã£ãŠæäŸãããTIDãå¥ã®æ¹æ³ã§äœ¿çšã§ããŸãã äŸãèããŠã¿ãŸãããïŒ
postgres=# create table t(a integer, b text, c boolean);
CREATE TABLE
postgres=# insert into t(a,b,c)
select s.id, chr((32+random()*94)::integer), random() < 0.01
from generate_series(1,100000) as s(id)
order by random();
INSERT 0 100000
postgres=# create index on t(a);
CREATE INDEX
postgres=# analyze t;
ANALYZE
3ã€ã®ãã£ãŒã«ããæã€ããŒãã«ãäœæããŸããã æåã®ãã£ãŒã«ãã«ã¯1ãã100000ãŸã§ã®æ°åãå«ãŸãããã®äžã«ã€ã³ããã¯ã¹ãäœæãããŠããŸãïŒçŸæç¹ã§ã¯ãã©ã¡ããéèŠã§ã¯ãããŸããïŒã 2çªç®ã®ãã£ãŒã«ãã«ã¯ãå°å·ã§ããªãæåãé€ãããŸããŸãªASCIIæåãå«ãŸããŠããŸãã æåŸã«ã3çªç®ã®ãã£ãŒã«ãã«ã¯è«çå€ãå«ãŸããçŽ1ïŒ
ã®è¡ã§trueãæ®ãã®è¡ã§falseã§ãã è¡ã¯ããŒãã«ã«ã©ã³ãã ãªé åºã§æ¿å
¥ãããŸãã
æ¡ä»¶ãa = 1ãã§å€ãéžæããŠã¿ãŸãããã æ¡ä»¶ã®åœ¢åŒã¯ã
ã€ã³ããã¯ã¹ä»ããã£ãŒã«ãæŒç®ååŒ ãã§ããçãããã
æŒç®åãšããŠäœ¿çšããã
åŒ ïŒæ€çŽ¢ããŒïŒãã1ãã§ããããšã«æ³šæããŠãã ããã ã»ãšãã©ã®å Žåãæ¡ä»¶ã¯ã€ã³ããã¯ã¹ã䜿çšã§ãããããªãã®ã§ãªããã°ãªããŸããã
postgres=# explain (costs off) select * from t where a = 1;
QUERY PLAN
-------------------------------
Index Scan using t_a_idx on t
Index Cond: (a = 1)
(2 rows)
ãã®å Žåããªããã£ãã€ã¶ãŒã¯ã€ã³ããã¯ã¹ã¹ãã£ã³ã䜿çšããããšã決å®ããŸããã ã€ã³ããã¯ã¹ãäœæããããšãã¢ã¯ã»ã¹æ¹æ³ã¯ãäžèŽããè¡ãçµäºãããŸã§ãäžåºŠã«1ã€ãã€TIDå€ãè¿ããŸãã ã€ã³ããã¯ã¹ã¡ã«ããºã ã¯ãTIDãæãããŒãã«ã®ããŒãžãåç
§ããè¡ã®ããŒãžã§ã³ãåãåãããã«ãããŒãžã§ã³ã«ãŒã«ã«åŸã£ãŠãã®å¯èŠæ§ããã§ãã¯ããåãåã£ãããŒã¿ãè¿ããŸãã
ããããããã¹ãã£ã³
ã€ã³ããã¯ã¹ã¹ãã£ã³ã¯ãããã€ãã®å€ã«ã€ããŠã®ã¿æå¹ã§ãã ãã ããéžæç¯å²ãå¢ãããšãåãã¿ãããŒãžã«äœåºŠãæ»ãå¿
èŠãçããå¯èœæ§ããããŸãã ãããã£ãŠããã®å Žåããªããã£ãã€ã¶ãŒ
ã¯ããããããã¹ãã£ã³
ã䜿çšããã¹ãã£ã³ã«åãæ¿ããŸãã
postgres=# explain (costs off) select * from t where a <= 100;
QUERY PLAN
------------------------------------
Bitmap Heap Scan on t
Recheck Cond: (a <= 100)
-> Bitmap Index Scan on t_a_idx
Index Cond: (a <= 100)
(4 rows)
ãŸããã¢ã¯ã»ã¹æ¹æ³ã¯æ¡ä»¶ã«äžèŽãããã¹ãŠã®TIDïŒããããããã€ã³ããã¯ã¹ã¹ãã£ã³ããŒãïŒãè¿ãããããããè¡ããŒãžã§ã³ã®ãããããããæ§ç¯ãããŸãã æ¬¡ã«ãè¡ã®ããŒãžã§ã³ãããŒãã«ããèªã¿åãããŸãïŒããããããããŒãã¹ãã£ã³ïŒ-ãã®å ŽåãåããŒãžã¯1åã ãèªã¿åãããŸãã
2çªç®ã®ã¹ãããã§ã¯ãæ¡ä»¶ãå確èªãããå Žåãããããšã«æ³šæããŠãã ããïŒæ¡ä»¶ã®å確èªïŒã éžæã倧ããããŠãè¡ããŒãžã§ã³ã®ãããããããRAMã«å®å
šã«åãŸããªãå ŽåããããŸãïŒwork_memãã©ã¡ãŒã¿ãŒã«ãã£ãŠå¶éãããŸãïŒã ãã®å Žåãå°ãªããšã1ã€ã®é©åãªããŒãžã§ã³ã®æååãå«ã
ããŒãžã®ããããããã®ã¿ãæ§ç¯ãããŸãã ãã®ãããªã倧ãŸããªãã«ãŒãã¯ã¹ããŒã¹ãåããŸããããããŒãžãèªã¿åããšãã¯ãããã«ä¿åãããŠããåè¡ã®æ¡ä»¶ãå確èªããå¿
èŠããããŸãã ãµã³ãã«ã®å Žåã§ãïŒãã®äŸã®ããã«ïŒãRecheck Condã¹ãããã¯ãã©ã³ã«è¡šç€ºãããŸãããå®éã«ã¯å®è£
ãããŠããŸããã
ããŒãã«ã®è€æ°ã®ãã£ãŒã«ãã«æ¡ä»¶ã課ãããŠããããããã®ãã£ãŒã«ãã«ã€ã³ããã¯ã¹ãä»ããããŠããå Žåããããããããã¹ãã£ã³ãããšïŒãªããã£ãã€ã¶ãŒãæå©ã ãšå€æããå ŽåïŒãåæã«è€æ°ã®ã€ã³ããã¯ã¹ã䜿çšã§ããŸãã åã€ã³ããã¯ã¹ã«ã€ããŠãè¡ããŒãžã§ã³ã®ãããããããæ§ç¯ããããããåäœã§è«ççã«ä¹ç®ãããïŒåŒãANDå¥ã§æ¥ç¶ãããŠããå ŽåïŒããè«ççã«è¿œå ãããŸãïŒåŒãORå¥ã§æ¥ç¶ãããŠããå ŽåïŒã äŸïŒ
postgres=# create index on t(b);
CREATE INDEX
postgres=# analyze t;
ANALYZE
postgres=# explain (costs off) select * from t where a <= 100 and b = 'a';
QUERY PLAN
--------------------------------------------------
Bitmap Heap Scan on t
Recheck Cond: ((a <= 100) AND (b = 'a'::text))
-> BitmapAnd
-> Bitmap Index Scan on t_a_idx
Index Cond: (a <= 100)
-> Bitmap Index Scan on t_b_idx
Index Cond: (b = 'a'::text)
(7 rows)
ããã§ãBitmapAndããŒãã¯ããããæäœãandãã䜿çšããŠ2ã€ã®ãããããããçµåããŸãã
ããããããã䜿çšããã¹ãã£ã³ã¯ãåãããŒã¿ããŒãžãžã®ã¢ã¯ã»ã¹ã®ç¹°ãè¿ããåé¿ããŸãã ããããããŒãã«ã®ããŒãžã®ããŒã¿ãã€ã³ããã¯ã¹ãšã³ããªãšãŸã£ããåãæ¹æ³ã§ç©ççã«é åºä»ããããŠããå Žåã¯ã©ãã§ããããã ãã¡ãããããŒãžå
ã®ããŒã¿ã®ç©ççãªé åºã«å®å
šã«äŸåããããšã¯ã§ããŸããããœãŒããããããŒã¿ãå¿
èŠãªå Žåã¯ããªã¯ãšã¹ãã§ORDER BYå¥ãæç€ºçã«æå®ããå¿
èŠããããŸãã ãããããã»ãŒãã¹ãŠãã®ããŒã¿ãå®éã«é åºä»ããããŠããå ŽåããããŸããããšãã°ãè¡ãæ£ããé åºã§è¿œå ããããã®åŸããŸãã¯CLUSTERã³ãã³ãã®å®è¡åŸã«å€æŽãããªãå Žåã§ãã ãã®åŸãããããããã®æ§ç¯ã¯è¿œå ã®ã¹ãããã§ãããéåžžã®ã€ã³ããã¯ã¹ã¹ãã£ã³ã¯æªåããŸããïŒè€æ°ã®ã€ã³ããã¯ã¹ãçµã¿åãããå¯èœæ§ãèæ
®ããªãå ŽåïŒã ãããã£ãŠãã¢ã¯ã»ã¹æ¹æ³ãéžæãããšããã¹ã±ãžã¥ãŒã©ã¯ããŒã¿ã®é åºä»ãã®çšåºŠã瀺ãç¹å¥ãªçµ±èšã調ã¹ãŸãã
postgres=# select attname, correlation from pg_stats where tablename = 't';
attname | correlation
---------+-------------
b | 0.533512
c | 0.942365
a | -0.00768816
(3 rows)
絶察å€ã1ã«è¿ãå€ã¯é«åïŒåcïŒã瀺ãããŒãã«è¿ãå€ã¯ã©ã³ãã ååžïŒåaïŒã瀺ããŸãã
ã·ãŒã±ã³ã·ã£ã«ã¹ãã£ã³
å®å
šãæãããã«ãééžæçæ¡ä»¶äžã§ã¯ããªããã£ãã€ã¶ã¯ããŒãã«å
šäœã®ã€ã³ããã¯ã¹
ã·ãŒã±ã³ã·ã£ã«ã¹ãã£ã³ã䜿çšããããšã奜ã¿ãŸãã
postgres=# explain (costs off) select * from t where a <= 40000;
QUERY PLAN
------------------------
Seq Scan on t
Filter: (a <= 40000)
(2 rows)
ãããŠåœŒã¯æ£ããã§ãããã äºå®ãã€ã³ããã¯ã¹ã¯ãæ¡ä»¶ã®éžææ§ãé«ãã»ã©ãã€ãŸãæ¡ä»¶ãæºããè¡ãå°ãªãã»ã©ãããé©åã«æ©èœãããšããããšã§ãã éžæãå¢ãããšãã€ã³ããã¯ã¹ããŒãžã®èªã¿åãã®ãªãŒããŒããããå¢å ããŸãã
ç¶æ³ã¯ãã·ãŒã±ã³ã·ã£ã«èªã¿åããããŒãžããã©ã³ãã ã«ãèªã¿åããããéããšããäºå®ã«ãã£ãŠæªåããŸãã ããã¯ç¹ã«ãããŒããã©ã€ãã®å Žåã«åœãŠã¯ãŸããŸããããŒããã©ã€ãã§ã¯ããããããã©ãã¯ã«ç§»åãããæ©æ¢°çãªæäœããããŒã¿èªäœã®èªã¿åããããããªãé·ãããããŸãã SSDã§ã¯ããã®å¹æã¯ããã»ã©é¡èã§ã¯ãããŸããã ã¢ã¯ã»ã¹ã³ã¹ãã®éããèæ
®ããŠãseq_page_costãšrandom_page_costã®2ã€ã®ãã©ã¡ãŒã¿ãŒããããŸãããããã¯ã°ããŒãã«ã«èšå®ã§ããã ãã§ãªããããŒãã«ã¹ããŒã¹ã®ã¬ãã«ã§ãèšå®ã§ããç°ãªããã£ã¹ã¯ãµãã·ã¹ãã ã®ç¹æ§ãèæ
®ã«å
¥ããŸãã
ææ°ã®ã«ããŒ
ååãšããŠãã¢ã¯ã»ã¹æ¹æ³ã®äž»ãªã¿ã¹ã¯ã¯ãé©åãªããŒãã«è¡ã®èå¥åãè¿ããã€ã³ããã¯ã¹äœæã¡ã«ããºã ãå¿
èŠãªããŒã¿ãããããèªã¿åãããšãã§ããããã«ããããšã§ãã ããããã¯ãšãªã«å¿
èŠãªãã¹ãŠã®ããŒã¿ãæ¢ã«ã€ã³ããã¯ã¹ã«å«ãŸããŠããå Žåã¯ã©ãã§ããããïŒ ãã®ãããªã€ã³ããã¯ã¹ã¯ã
ã«ããªã³ã°ãšåŒã°ããŸãããã®å Žåããªããã£ãã€ã¶ã¯ã€ã³ããã¯ã¹ã¹ãã£ã³
ã®ã¿ã䜿çšã§ããŸãã
postgres=# vacuum t;
VACUUM
postgres=# explain (costs off) select a from t where a < 100;
QUERY PLAN
------------------------------------
Index Only Scan using t_a_idx on t
Index Cond: (a < 100)
(2 rows)
ãã®ååã¯ãã€ã³ããã¯ã¹äœæã¡ã«ããºã ãããŒãã«ããŸã£ããåç
§ãããã¢ã¯ã»ã¹æ¹æ³ããå¿
èŠãªãã¹ãŠã®æ
å ±ãæä»çã«åãåãããšã瀺åããŠããå ŽåããããŸãã ãã ããPostgreSQLã®ã€ã³ããã¯ã¹ã«ã¯è¡ã®å¯èŠæ§ã倿ã§ããæ
å ±ãå«ãŸããŠããªããããããã¯å®å
šã«çå®ã§ã¯ãããŸããã ãããã£ãŠãã¢ã¯ã»ã¹æ¹æ³ã¯ãçŸåšã®ãã©ã³ã¶ã¯ã·ã§ã³ã«è¡šç€ºãããŠãããã©ããã«é¢ä¿ãªããæ€çŽ¢æ¡ä»¶ã«è©²åœãããã¹ãŠã®ããŒãžã§ã³ã®è¡ãè¿ããŸãã
ãã ããã€ã³ããã¯ã¹äœæã¡ã«ããºã ãå¯èŠæ§ã倿ããããã«æ¯åããŒãã«ã調ã¹ãå¿
èŠãããå Žåããã®ã¹ãã£ã³æ¹æ³ã¯éåžžã®ã€ã³ããã¯ã¹ã¹ãã£ã³ãšå€ãããŸããã
ãã®åé¡ã¯ãPostgreSQLãããŒãã«ã®ãããã
å¯èŠæ§ãããããµããŒããããšããäºå®ã«ãã£ãŠè§£æ±ºãããŸãããã®
ãããã§ã¯ãããã¥ãŒã ããã»ã¹ã¯ãéå§æéãšåé¢ã¬ãã«ã«é¢ä¿ãªãããã¹ãŠã®ãã©ã³ã¶ã¯ã·ã§ã³ãããŒã¿ãèŠãã®ã«ååãªã»ã©é·ãå€åããŠããªãããŒãžãããŒã¯ããŸãã ã€ã³ããã¯ã¹ã«ãã£ãŠè¿ãããè¡ã®èå¥åããã®ãããªããŒãžãåç
§ããŠããå Žåãå¯èŠæ§ã¯ç¢ºèªã§ããŸããã
ãããã£ãŠã宿çãªã¯ãªãŒãã³ã°ã¯ã³ãŒãã£ã³ã°ã€ã³ããã¯ã¹ã®æå¹æ§ãé«ããŸãã ããã«ããªããã£ãã€ã¶ãŒã¯ãæªã¯ãªãŒãã³ã°ã®è¡ã®æ°ãèæ
®ããå¯èŠæ§ã®ãã§ãã¯ã§å€§ããªãªãŒããŒããããäºæž¬ãããå Žåãã€ã³ããã¯ã¹ã¹ãã£ã³ã®ã¿ã®äœ¿çšãæåŠã§ããŸãã
ããŒãã«ãžã®åŒ·å¶åŒã³åºãã®æ°ã¯ãexplain analyzeã³ãã³ãã䜿çšããŠèŠã€ããããšãã§ããŸãã
postgres=# explain (analyze, costs off) select a from t where a < 100;
QUERY PLAN
-------------------------------------------------------------------------------
Index Only Scan using t_a_idx on t (actual time=0.025..0.036 rows=99 loops=1)
Index Cond: (a < 100)
Heap Fetches: 0
Planning time: 0.092 ms
Execution time: 0.059 ms
(5 rows)
ãã®å Žåãã¯ãªãŒã³ã¢ãããå®è¡ãããã°ãããªã®ã§ãããŒãã«ã«ã¢ã¯ã»ã¹ããå¿
èŠã¯ãããŸããã§ããïŒããŒããã§ããïŒ0ïŒã äžè¬ã«ããã®æ°å€ããŒãã«è¿ãã»ã©è¯ãã§ãã
ãã¹ãŠã®ã€ã³ããã¯ã¹ããã€ã³ããã¯ã¹ä»ãã®å€èªäœãè¡èå¥åãšãšãã«ä¿åããããã§ã¯ãããŸããã ã¢ã¯ã»ã¹æ¹æ³ãããŒã¿ãè¿ããªãå Žåãã€ã³ããã¯ã¹ã¹ãã£ã³å°çšã«äœ¿çšããããšã¯ã§ããŸããã
ãã«
äžç¢ºå®ãªå€ã¯ãå€ãååšããªãããŸãã¯äžæã§ãããšããäºå®ã衚ã䟿å©ãªæ¹æ³ãšããŠããªã¬ãŒã·ã§ãã«ããŒã¿ããŒã¹ã§éèŠãªåœ¹å²ãæãããŸãã
ããããç¹å¥ãªæçŸ©ã«ã¯ãèªåèªèº«ã«å¯Ÿããç¹å¥ãªæ
床ãå¿
èŠã§ãã éåžžã®ããŒã«è«çã¯3æ¡ã«ãªããŸãã äžå®å€ãéåžžã®å€ãããå°ãããããããšã倧ããããäžæã§ãïŒãã®ãããNULLS FIRSTããã³NULLS LASTããœãŒãããããã®ç¹å¥ãªæ§æïŒã éèšé¢æ°ã§äžç¢ºå®ãªå€ãèæ
®ããå¿
èŠããããã©ããã¯æããã§ã¯ãããŸããã ã¹ã±ãžã¥ãŒã©ã«ã¯ç¹å¥ãªçµ±èšãå¿
èŠã§ã...
äžå®å€ã䜿çšããã€ã³ããã¯ã¹ãµããŒãã®èгç¹ããã¯ããããŸããããããŸãããã®ãããªå€ã«ã€ã³ããã¯ã¹ãä»ããã¹ããã©ããã nullãã€ã³ããã¯ã¹åããªãå Žåãã€ã³ããã¯ã¹ã¯ããã³ã³ãã¯ãã«ãªããŸãã ãã ããã€ã³ããã¯ã¹ãäœæãããšãã
ã€ã³ããã¯ã¹ä»ããã£ãŒã«ã IS [NOT] NULLããšãã圢åŒã®æ¡ä»¶ã«ã€ã³ããã¯ã¹ã䜿çšã§ããããã«ãªããŸãããŸããããŒãã«ã«æ¡ä»¶ããŸã£ãããªãå Žåã®ã«ããŒã€ã³ããã¯ã¹ã䜿çšã§ããŸãïŒãã®å Žåãã€ã³ããã¯ã¹ã¯ããŒãã«ã®ãã¹ãŠã®è¡ããããŒã¿ãè¿ãå¿
èŠãããããæ°å€ããã³æªå®çŸ©ã®å€ãå«ãïŒã
éçºè
ã¯ãã¢ã¯ã»ã¹æ¹æ³ããšã«ãäžå®å€ã«ã€ã³ããã¯ã¹ãä»ãããã©ãããæ±ºå®ããŸãã ããããååãšããŠããããã¯ãŸã ã€ã³ããã¯ã¹åãããŠããŸãã
è€æ°ã®ãã£ãŒã«ãã€ã³ããã¯ã¹
è€æ°
åã®ã€ã³ããã¯ã¹ã䜿çšããŠãè€æ°ã®ãã£ãŒã«ãæ¡ä»¶ããµããŒãã§ã
ãŸã ã ããšãã°ãããŒãã«ã®2ã€ã®ãã£ãŒã«ãã«ã€ã³ããã¯ã¹ãäœæã§ããŸãã
postgres=# create index on t(a,b);
CREATE INDEX
postgres=# analyze t;
ANALYZE
ãªããã£ãã€ã¶ã¯ãããããããã®çµã¿åããããããã®ãããªã€ã³ããã¯ã¹ã奜ãå¯èœæ§ãé«ãã§ãããããªããªããããã§ã¯ãè£å©ã¢ã¯ã·ã§ã³ãªãã§å¿
èŠãªTIDãããã«ååŸã§ããããã§ãã
postgres=# explain (costs off) select * from t where a <= 100 and b = 'a';
QUERY PLAN
------------------------------------------------
Index Scan using t_a_b_idx on t
Index Cond: ((a <= 100) AND (b = 'a'::text))
(2 rows)
è€æ°åã€ã³ããã¯ã¹ã䜿çšããŠãäžéšã®ãã£ãŒã«ãã®æ¡ä»¶ã«ãã£ãŠãµã³ããªã³ã°ãé«éåããããšãã§ããŸã-æåããéå§ïŒ
postgres=# explain (costs off) select * from t where a <= 100;
QUERY PLAN
--------------------------------------
Bitmap Heap Scan on t
Recheck Cond: (a <= 100)
-> Bitmap Index Scan on t_a_b_idx
Index Cond: (a <= 100)
(4 rows)
ååãšããŠãæåã®ãã£ãŒã«ãã«æ¡ä»¶ã課ãããŠããªãå Žåãã€ã³ããã¯ã¹ã¯äœ¿çšãããŸããã ãã ããå Žåã«ãã£ãŠã¯ããªããã£ãã€ã¶ãŒã¯ãã·ãŒã±ã³ã·ã£ã«ã¹ãã£ã³ãããåçæ§ãé«ããšèããå ŽåããããŸãã ãã®ãããã¯ã«ã€ããŠã¯ãbtreeã€ã³ããã¯ã¹ãèŠããšãã«è©³ãã説æããŸãã
ãã¹ãŠã®ã¢ã¯ã»ã¹æ¹æ³ãè€æ°ã®åã«ãããã€ã³ããã¯ã¹ã®äœæããµããŒãããããã§ã¯ãããŸããã
åŒã€ã³ããã¯ã¹
æ€çŽ¢æ¡ä»¶ã¯ã
ã€ã³ããã¯ã¹ä»ããã£ãŒã«ãæŒç®ååŒ ãã®åœ¢åŒã«ããå¿
èŠããããšããäºå®ã«ã€ããŠèª¬æããŸããã 以äžã®äŸã§ã¯ãã€ã³ããã¯ã¹ã¯äœ¿çšãããŸãããããã¯ããã£ãŒã«ãåèªäœã®ä»£ããã«ããããå«ãåŒã䜿çšãããããã§ãã
postgres=# explain (costs off) select * from t where lower(b) = 'a';
QUERY PLAN
------------------------------------------
Seq Scan on t
Filter: (lower((b)::text) = 'a'::text)
(2 rows)
ãã£ãŒã«ãåã®ã¿ãæŒç®åã®å·ŠåŽã«ããããã«ããã®ç¹å®ã®ã¯ãšãªãæžãæããããšã¯é£ãããããŸããã ãã ãããããäžå¯èœãªå Žåã¯ã
åŒã®ã€ã³ããã¯ã¹ïŒé¢æ°ã€ã³ããã¯ã¹ïŒã圹ç«ã¡ãŸãã
postgres=# create index on t(lower(b));
CREATE INDEX
postgres=# analyze t;
ANALYZE
postgres=# explain (costs off) select * from t where lower(b) = 'a';
QUERY PLAN
----------------------------------------------------
Bitmap Heap Scan on t
Recheck Cond: (lower((b)::text) = 'a'::text)
-> Bitmap Index Scan on t_lower_idx
Index Cond: (lower((b)::text) = 'a'::text)
(4 rows)
颿°ã€ã³ããã¯ã¹ã¯ãããŒãã«ãã£ãŒã«ãã§ã¯ãªããä»»æã®åŒã«ãã£ãŠäœæãããŸãã ãªããã£ãã€ã¶ãŒã¯ãã
indexed-expression operator expression ã
ãšãã圢åŒã®æ¡ä»¶ã®ã€ã³ããã¯ã¹ãèæ
®ããŸãã ã€ã³ããã¯ã¹ä»ãåŒã®èšç®ãã³ã¹ãã®ãããæäœã§ããå Žåãã€ã³ããã¯ã¹ã®æŽæ°ã«ã¯ããªãã®èšç®ãªãœãŒã¹ãå¿
èŠã«ãªããŸãã
ãŸããã€ã³ããã¯ã¹ä»ãã®åŒã«ã€ããŠåå¥ã®çµ±èšãåéãããããšã«ãçæããŠãã ããã ã€ã³ããã¯ã¹åããšã«pg_statsãã¥ãŒã§èŠãããšãã§ããŸãïŒ
postgres=# \dt
Table "public.t"
Column | Type | Modifiers
--------+---------+-----------
a | integer |
b | text |
c | boolean |
Indexes:
"t_a_b_idx" btree (a, b)
"t_a_idx" btree (a)
"t_b_idx" btree (b)
"t_lower_idx" btree (lower(b))
postgres=# select * from pg_stats where tablename = 't_lower_idx';
...
å¿
èŠã«å¿ããŠãéåžžã®ããŒãã«ãã£ãŒã«ãã®å Žåãšåãæ¹æ³ã§ãã¹ãã°ã©ã ãã¹ã±ããã®æ°ãå¶åŸ¡ã§ããŸãïŒååãã€ã³ããã¯ã¹åŒã«ãã£ãŠç°ãªãå Žåãããããšãèæ
®ããŠïŒã
postgres=# \d t_lower_idx
Index "public.t_lower_idx"
Column | Type | Definition
--------+------+------------
lower | text | lower(b)
btree, for table "public.t"
postgres=# alter index t_lower_idx alter column "lower" set statistics 69;
ALTER INDEX
éšåã€ã³ããã¯ã¹
å Žåã«ãã£ãŠã¯ãããŒãã«è¡ã®äžéšã®ã¿ã«ã€ã³ããã¯ã¹ãä»ããå¿
èŠããããŸãã éåžžãããã¯åŒ·ãäžåäžãªååžã«ãããã®ã§ããã€ã³ããã¯ã¹ã§ã¬ã¢ãªå€ãæ€çŽ¢ããã®ã¯çã«ããªã£ãŠããŸããããã«ããŒãã«ã¹ãã£ã³ã§é »ç¹ãªå€ãèŠã€ããæ¹ãç°¡åã§ãã
ãã¡ããããcãåã«éåžžã®ã€ã³ããã¯ã¹ãäœæããããšãã§ããæåŸ
ã©ããã«æ©èœããŸãã
postgres=# create index on t(c);
CREATE INDEX
postgres=# analyze t;
ANALYZE
postgres=# explain (costs off) select * from t where c;
QUERY PLAN
-------------------------------
Index Scan using t_c_idx on t
Index Cond: (c = true)
Filter: c
(3 rows)
postgres=# explain (costs off) select * from t where not c;
QUERY PLAN
-------------------
Seq Scan on t
Filter: (NOT c)
(2 rows)
ã€ã³ããã¯ã¹ã®é·ãã¯276ããŒãžã§ãã
postgres=# select relpages from pg_class where relname='t_c_idx';
relpages
----------
276
(1 row)
ãã ãããcãåã¯è¡ã®1ïŒ
ã®ã¿ã«åœãŠã¯ãŸããããã€ã³ããã¯ã¹ã®99ïŒ
ã¯äœ¿çšãããŸããã ãã®å Žåãéšåã€ã³ããã¯ã¹ãäœæã§ããŸãã
postgres=# create index on t(c) where c;
CREATE INDEX
postgres=# analyze t;
ANALYZE
ãã®ã€ã³ããã¯ã¹ã®ãµã€ãºã¯5ããŒãžã«æžå°ããŸããã
postgres=# select relpages from pg_class where relname='t_c_idx1';
relpages
----------
5
(1 row)
å Žåã«ãã£ãŠã¯ãããªã¥ãŒã ãšããã©ãŒãã³ã¹ã®éããéåžžã«å€§ãããªãããšããããŸãã
ä»åã
ã¢ã¯ã»ã¹æ¹æ³ããœãŒãé ã«è¡èå¥åãè¿ãå Žåããªããã£ãã€ã¶ãŒã«ã¯ãšãªãå®è¡ããããã®è¿œå ãªãã·ã§ã³ãäžããããŸãã
ããŒãã«ãã¹ãã£ã³ããŠãããããŒã¿ãäžŠã¹æ¿ããããšãã§ããŸãã
postgres=# set enable_indexscan=off;
SET
postgres=# explain (costs off) select * from t order by a;
QUERY PLAN
---------------------
Sort
Sort Key: a
-> Seq Scan on t
(3 rows)
ãŸããã€ã³ããã¯ã¹ã䜿çšããŠããœãŒãé ã§ããã«ããŒã¿ãèªã¿åãããšãã§ããŸãã
postgres=# set enable_indexscan=on;
SET
postgres=# explain (costs off) select * from t order by a;
QUERY PLAN
-------------------------------
Index Scan using t_a_idx on t
(1 row)
ãã¹ãŠã®ã¢ã¯ã»ã¹æ¹æ³ã®ãã¡ãbtreeã®ã¿ããœãŒãããã圢åŒã§ããŒã¿ãè¿ãããšãã§ããããããã®ã¿ã€ãã®ã€ã³ããã¯ã¹ãæ€èšãããŸã§ããã詳现ãªè°è«ãå»¶æããŸãã
äžŠåæ§é
éåžžãã€ã³ããã¯ã¹ãäœæããã«ã¯ãããŒãã«ã«SHAREããã¯ãèšå®ããå¿
èŠããããŸãã ãã®ãããªããã¯ã䜿çšãããšãããŒãã«ããããŒã¿ãèªã¿åãããšãã§ããŸãããã€ã³ããã¯ã¹ã®æ§ç¯äžã®å€æŽã¯çŠæ¢ãããŸãã
ããã確èªããã«ã¯ãã€ã³ããã¯ã¹ãäœæãããšãã«ãããšãã°ããŒãã«tã§ãå¥ã®ã»ãã·ã§ã³ã§ã¯ãšãªãå®è¡ããŸãã
postgres=# select mode, granted from pg_locks where relation = 't'::regclass;
mode | granted
-----------+---------
ShareLock | t
(1 row)
ããŒãã«ãååã«å€§ãããæ¿å
¥ãæŽæ°ããŸãã¯åé€ã¢ãŒãã§ã¢ã¯ãã£ãã«äœ¿çšãããŠããå Žåãããã¯åãå
¥ããããªãããšããããŸã-ã»ãã·ã§ã³ã®å€æŽã¯ãããã¯ãé·æéè§£é€ãããã®ãåŸ
ã¡ãŸãã
ãã®å Žåãã€ã³ããã¯ã¹ã®äžŠåäœæã䜿çšã§ããŸãã
postgres=# create index concurrently on t(a);
CREATE INDEX
ãã®ãããªã³ãã³ãã¯ãSHARE UPDATE EXCLUSIVEã¿ã€ãã®ããã¯ã確ç«ããããŒã¿ã®èªã¿åããšå€æŽã®äž¡æ¹ãèš±å¯ããŸãïŒããŒãã«ã®æ§é ã®å€æŽãããã³åãããŒãã«ã®å¥ã®ã€ã³ããã¯ã¹ã®ã¯ãªãŒãã³ã°ãåæããŸãã¯æ§ç¯ã®ã¿ãçŠæ¢ãããŠããŸãïŒã
ãã ããæ¬ ç¹ããããŸãã ãŸããããŒãã«ã1åééãã代ããã«2åå®è¡ããããããã€ã³ããã¯ã¹ã®æ§ç¯ãéåžžããé
ããªããŸãããŸããããŒã¿ã倿Žãã䞊åãã©ã³ã¶ã¯ã·ã§ã³ã®å®äºãåŸ
ã€å¿
èŠããããŸãã
第äºã«ãã€ã³ããã¯ã¹ã®äžŠåæ§ç¯äžã«ããããããã¯ãŸãã¯äžææ§å¶çŽéåãçºçããå ŽåããããŸãã ããã§ãã€ã³ããã¯ã¹ã¯äœæãããŸããããæ©èœããªããç¶æ
ã§ãã ãã®å Žåãåé€ããŠããåäœæããå¿
èŠããããŸãã é皌åã€ã³ããã¯ã¹ã¯ãpsql \ dã³ãã³ãã®åºåã§INVALIDãšããåèªã§ããŒã¯ãããã¯ãšãªã«ãã£ãŠå®å
šãªãªã¹ããååŸã§ããŸãã
postgres=# select indexrelid::regclass index_name, indrelid::regclass table_name from pg_index where not indisvalid;
index_name | table_name
------------+------------
t_a_idx | t
(1 row)
ç¶ç¶ãã ã