ãã®ã·ãªãŒãºã®ä»¥åã® æçš¿ã§ã¯ãExplainåæã®åºåã®1è¡ã解éããæ¹æ³ãšãã®æ§é ã«ã€ããŠæžããããŒã¿ïŒExplainããªãŒã®ããŒãïŒãååŸããããã®åºæ¬æäœã«ã€ããŠã説æããŸããã
ä»æ¥ã¯ãããè€éãªæäœã«é²ã¿ãŸãã

æ©èœã¹ãã£ã³
äŸïŒ
$ explain analyze select * from generate_Series(1,10) i; QUERY PLAN --------------------------------------------------------------------------------------------------------------------- Function Scan on generate_series i (cost=0.00..10.00 rows=1000 width=4) (actual time=0.012..0.013 rows=10 loops=1) Total runtime: 0.034 ms (2 rows)
æŠããŠãããã¯éåžžã«åçŽãªã®ã§ãäœãã説æããå¿ èŠã¯ç¹ã«ãããŸããã ãããããã®æäœã¯æ¬¡ã®äŸã§äœ¿çšããããããå°ã説æããŸãã
é¢æ°ã¹ãã£ã³ã¯éåžžã«åçŽãªã¢ã»ã³ããªã§ãã ã¬ã³ãŒãã»ãããè¿ãé¢æ°ãå®è¡ããããã ãã§ãã ãlowerïŒïŒãã®ãããªé¢æ°ã¯å®è¡ããŸããããå€ãã®è¡ãŸãã¯åãè¿ãå¯èœæ§ãããé¢æ°ã®ã¿ãå®è¡ããŸããé¢æ°ãè¡ãè¿ããšããããã¯ãã©ã³ããªãŒã®Function Scanãã1ã¬ãã«é«ãããŒããŸãã¯ã¯ã©ã€ã¢ã³ãã«è»¢éãããŸãFunction Scanãã«ãŒãããŒãã®å Žåã
ããã§çºçããå¯èœæ§ãããå¯äžã®è¿œå ããžãã¯ã¯ã次ã®ããã«ãåä¿¡ããåç·ããã£ã«ã¿ãªã³ã°ããæ©èœã§ãã
$ explain analyze select * from generate_Series(1,10) i where i < 3; QUERY PLAN ------------------------------------------------------------------------------------------------------------------- Function Scan on generate_series i (cost=0.00..12.50 rows=333 width=4) (actual time=0.012..0.014 rows=2 loops=1) Filter: (i < 3) Rows Removed by Filter: 8 Total runtime: 0.030 ms (4 rows)
䞊ã¹æ¿ã
ããã¯éåžžã«ç解ãããããšæããŸã-ãœãŒãã¯éžæããã¬ã³ãŒããååŸããç¹å®ã®æ¹æ³ã§ãœãŒãããŠè¿ããŸãã
äŸïŒ
$ explain analyze select * from pg_class order by relname; QUERY PLAN --------------------------------------------------------------------------------------------------------------- Sort (cost=22.88..23.61 rows=292 width=203) (actual time=0.230..0.253 rows=295 loops=1) Sort Key: relname Sort Method: quicksort Memory: 103kB -> Seq Scan on pg_class (cost=0.00..10.92 rows=292 width=203) (actual time=0.007..0.048 rows=295 loops=1) Total runtime: 0.326 ms (5 rows)
ç°¡åã§ãããèå³æ·±ãããžãã¯ãæœãã§ããŸãã ãŸãããœãŒãã«å¿ èŠãªã¡ã¢ãªãwork_memã®å€ããã倧ããå Žåããã£ã¹ã¯ãœãŒããžã®åãæ¿ããçºçããŸãã
$ explain analyze select random() as x from generate_series(1,14000) i order by x; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ Sort (cost=62.33..64.83 rows=1000 width=0) (actual time=16.713..18.090 rows=14000 loops=1) Sort Key: (random()) Sort Method: quicksort Memory: 998kB -> Function Scan on generate_series i (cost=0.00..12.50 rows=1000 width=0) (actual time=2.036..4.533 rows=14000 loops=1) Total runtime: 18.942 ms (5 rows) $ explain analyze select random() as x from generate_series(1,15000) i order by x; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ Sort (cost=62.33..64.83 rows=1000 width=0) (actual time=27.052..28.780 rows=15000 loops=1) Sort Key: (random()) Sort Method: external merge Disk: 264kB -> Function Scan on generate_series i (cost=0.00..12.50 rows=1000 width=0) (actual time=2.171..4.894 rows=15000 loops=1) Total runtime: 29.767 ms (5 rows)
äžèšã®äŸã®ãœãŒãæ¹æ³ã®å€æŽã«æ³šç®ããŠãã ããã
ãã®ãããªå ŽåãPostgresã¯$ PGDATA / base / pgsql_tmp /ãã£ã¬ã¯ããªã«ä¿åãããŠããäžæãã¡ã€ã«ã䜿çšããŸãã ãã¡ããããããã®å¿ èŠæ§ããªããªããšããã«åé€ãããŸãã
å¥ã®è¿œå ã®ããããã£ã¯ã次ã®ããã«ãLimitæäœã«ãã£ãŠåŒã³åºãããå ŽåãSortãäœæ¥ã¡ãœãããå€æŽã§ããããšã§ãã
$ explain analyze select * from pg_class order by relfilenode limit 5; QUERY PLAN --------------------------------------------------------------------------------------------------------------------- Limit (cost=15.77..15.78 rows=5 width=203) (actual time=0.119..0.120 rows=5 loops=1) -> Sort (cost=15.77..16.50 rows=292 width=203) (actual time=0.118..0.118 rows=5 loops=1) Sort Key: relfilenode Sort Method: top-N heapsort Memory: 26kB -> Seq Scan on pg_class (cost=0.00..10.92 rows=292 width=203) (actual time=0.005..0.047 rows=295 loops=1) Total runtime: 0.161 ms (6 rows)
éåžžãéžæããããŒã¿ã»ããã䞊ã¹æ¿ããã«ã¯ãããŒã¿ã»ããå šäœãåŠçããå¿ èŠããããŸãã ããããPostgresã¯ãå¿ èŠãªè¡æ°ãå°ãªãå ŽåãããŒã¿ã»ããå šäœã䞊ã¹æ¿ããå¿ èŠã¯ãªããæåã®å€ã®ã¿ãååŸããã°ååã§ããããšãç¥ã£ãŠããŸãã
Big Oè¡šèšã§ã¯ãäžè¬çãªäžŠã¹æ¿ãã«ã¯è€é床OïŒm * logïŒmïŒïŒããããŸãããTop-Nã«ã¯è€é床OïŒm * logïŒnïŒïŒããããŸããããã§ãmã¯ããŒãã«å ã®è¡æ°ãnã¯è¿ãããè¡æ°ã§ãã ãã®äžŠã¹æ¿ãæ¹æ³ã¯ã䜿çšããã¡ã¢ãªãã¯ããã«å°ãªãããšãç¥ã£ãŠããããšãéèŠã§ãïŒæçµçã«ã䞊ã¹æ¿ããããè¡ããããŒã¿ã»ããå šäœãåéããå¿ èŠã¯ãªããæ°è¡ããã°ååã§ãïŒããããã£ãŠãäžæãã¡ã€ã«ã«äœéã®ãã£ã¹ã¯ã䜿çšããå¯èœæ§ã¯äœããªããŸãã
å¶é
limitã¯éåžžã«åçŽãªã®ã§ç¹°ãè¿ã䜿çšããŸããããããã§ã詳现ã«èª¬æããŸãã å¶éæäœã¯ãµãæäœãéå§ãããµãæäœãè¿ããæåã®Nè¡ã®ã¿ãè¿ããŸãã éåžžããã®åŸããµããªãã¬ãŒã·ã§ã³ã¯åæ¢ããŸãããå Žåã«ãã£ãŠã¯ïŒããšãã°ãpl / PgSQLé¢æ°ã®åŒã³åºãïŒããµããªãã¬ãŒã·ã§ã³ã¯æåã®è¡ãè¿ããŸã§ã«äœæ¥ããã§ã«å®äºããŠããŸãã
ç°¡åãªäŸïŒ
$ explain analyze select * from pg_class; QUERY PLAN --------------------------------------------------------------------------------------------------------- Seq Scan on pg_class (cost=0.00..10.92 rows=292 width=203) (actual time=0.008..0.047 rows=295 loops=1) Total runtime: 0.096 ms (2 rows) $ explain analyze select * from pg_class limit 2; QUERY PLAN ------------------------------------------------------------------------------------------------------------- Limit (cost=0.00..0.07 rows=2 width=203) (actual time=0.009..0.010 rows=2 loops=1) -> Seq Scan on pg_class (cost=0.00..10.92 rows=292 width=203) (actual time=0.008..0.009 rows=2 loops=1) Total runtime: 0.045 ms (3 rows)
ã芧ã®ãšããã2çªç®ã®ã±ãŒã¹ã§å¶éã䜿çšãããšããã¹ããããSeqã¹ãã£ã³æäœã2è¡ãæ€åºããçŽåŸã«ãã®äœæ¥ãå®äºãããšããäºå®ã«è³ããŸããã
ããã·ã¥éèš
ãã®æäœã¯äž»ã«ãGROUP BYããã³sumïŒïŒãavgïŒïŒãminïŒïŒãmaxïŒïŒãªã©ã®äžéšã®éèšã䜿çšããå Žåã«äœ¿çšãããŸãã
äŸïŒ
$ explain analyze select relkind, count(*) from pg_Class group by relkind; QUERY PLAN ------------------------------------------------------------------------------------------------------------- HashAggregate (cost=12.38..12.42 rows=4 width=1) (actual time=0.223..0.224 rows=5 loops=1) -> Seq Scan on pg_class (cost=0.00..10.92 rows=292 width=1) (actual time=0.008..0.053 rows=295 loops=1) Total runtime: 0.273 ms (3 rows)
HashAggregateã¯æ¬¡ãå®è¡ããŸããåä¿¡ããåè¡ã«å¯ŸããŠãGROUP BYâããŒâïŒãã®å Žåã¯relkindïŒãèŠã€ããŸãã 次ã«ãããã·ã¥ïŒé£æ³é åãèŸæžïŒã§ããã®ããŒã瀺ããã¹ã±ããã«éžæããè¡ãé 眮ããŸãã
ãã¹ãŠã®è¡ãåŠçãããåŸãããã·ã¥ãã¹ãã£ã³ããããŒå€ããšã«1è¡ãè¿ããå¿ èŠã«å¿ããŠé©åãªèšç®ïŒåèšãæå°ãå¹³åãªã©ïŒãè¡ããŸãã
HashAggregateã¯ãå°ãªããšã1è¡ãè¿ãåã«ãã¹ãŠã®è¡ãã¹ãã£ã³ããå¿ èŠãããããšãç解ããããšãéèŠã§ãã
ãããç解ããŠããå Žåãæœåšçãªåé¡ãçºçããŠããå¯èœæ§ããããŸããæ°çŸäžè¡ããç¶æ³ã§äœããã¹ããã ããã·ã¥ã¯å€§ããããŠã¡ã¢ãªã«åãŸããŸããã ãããŠãããã§åã³work_memã䜿çšããŸã ã çæãããããã·ã¥ã倧ããããå Žåããã£ã¹ã¯ã«ããŒãžãããŸãïŒåã³$ PGDATA / base / pgsql_tmpã«ãããŸãïŒã
ããã¯ããã©ã³ã«HashAggregateãšSortã®äž¡æ¹ãããå Žåãæ倧2 * work_memã䜿çšã§ããããšãæå³ããŸãã ãã®ãããªèšç»ã¯ç°¡åã«å ¥æã§ããŸãã
$ explain analyze select relkind, count(*) from pg_Class group by relkind order by relkind; QUERY PLAN ------------------------------------------------------------------------------------------------------------------- Sort (cost=12.46..12.47 rows=4 width=1) (actual time=0.260..0.261 rows=5 loops=1) Sort Key: relkind Sort Method: quicksort Memory: 25kB -> HashAggregate (cost=12.38..12.42 rows=4 width=1) (actual time=0.221..0.222 rows=5 loops=1) -> Seq Scan on pg_class (cost=0.00..10.92 rows=292 width=1) (actual time=0.006..0.044 rows=295 loops=1) Total runtime: 0.312 ms (6 rows)
å®éã«ã¯ãwork_memã¯æäœã«å¯Ÿããå¶çŽã§ããããã1ã€ã®èŠæ±ã§work_memãäœåºŠã䜿çšã§ããŸãã ãããã£ãŠããªã¯ãšã¹ãã1000åã®HashAggregatesãšSortsïŒããã³work_memã䜿çšããä»ã®æäœïŒã䜿çšããå Žåãåèšã¡ã¢ãªæ¶è²»éãéåžžã«å€§ãããªãå¯èœæ§ããããŸãã
ããã·ã¥çµå/ããã·ã¥
HashAggregateã«ã€ããŠèª¬æããã°ãããªã®ã§ãHash Joinã«é²ãã®ãè«ççã§ãã
ãã®æäœã«ã¯ãåã®æäœãšã¯ç°ãªãã 2ã€ã®ãµãæäœããããŸãã ãããã®1ã€ã¯åžžã«ãããã·ã¥ãã§ã2ã€ç®ã¯å¥ã®ãã®ã§ãã
ååã瀺ãããã«ãããã·ã¥çµåã¯2ã»ããã®ã¬ã³ãŒããçµåããããã«äœ¿çšãããŸãã ããšãã°ã次ã®ããã«ïŒ
$ explain analyze select * from pg_class c join pg_namespace n on c.relnamespace = n.oid; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------- Hash Join (cost=1.14..16.07 rows=292 width=316) (actual time=0.036..0.343 rows=295 loops=1) Hash Cond: (c.relnamespace = n.oid) -> Seq Scan on pg_class c (cost=0.00..10.92 rows=292 width=203) (actual time=0.007..0.044 rows=295 loops=1) -> Hash (cost=1.06..1.06 rows=6 width=117) (actual time=0.012..0.012 rows=6 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 1kB -> Seq Scan on pg_namespace n (cost=0.00..1.06 rows=6 width=117) (actual time=0.004..0.005 rows=6 loops=1) Total runtime: 0.462 ms (7 rows)
ããã¯æ¬¡ã®ããã«æ©èœããŸãïŒæåã«ãHash JoinããHashããåŒã³åºãã次ã«å¥ã®äœãïŒãã®å Žåã¯pg_namespaceã«ããSeq ScanïŒãåŒã³åºããŸãã次ã«ãHashã¯ããã·ã¥ãã¡ã¢ãªå ïŒãŸãã¯ãµã€ãºã«å¿ããŠãã£ã¹ã¯äžïŒã«äœæããŸã/ããŒã¿ãçµåããããã«äœ¿çšããããã®ã䜿çšããŠããã·ã¥åããããœãŒã¹ããã®æååãæã€é£æ³é å/èŸæžïŒãã®å Žåãããã¯pg_namespaceã®OIDåã§ãïŒã
ãã¡ãããæå®ãããçµåããŒã«å¯ŸããŠå€ãã®è¡ãæã€ããšãã§ããŸãïŒäž»ããŒãšçµåããŠããããããã®å Žåã¯ããã§ã¯ãããŸããããäžè¬çã«ã¯ã1ã€ã®ããã·ã¥ããŒã«å¯ŸããŠå€ãã®è¡ãããã§ãããïŒã
Perlè¡šèšã§ã¯ãããã·ã¥åºåã¯æ¬¡ã®ããã«ãªããŸãã
{ '123' => [ { data for row with OID = 123 }, ], '256' => [ { data for row with OID = 256 }, ], ... }
次ã«ãHash Joinã¯2çªç®ã®ãµããªãã¬ãŒã·ã§ã³ïŒãã®å Žåã¯pg_classã«ããã·ãŒã±ã³ã¹ã¹ãã£ã³ïŒãéå§ããããããã®åè¡ã«å¯ŸããŠæ¬¡ã®ããšãè¡ããŸãã
- çµåããŒïŒãã®å Žåã¯pg_class.relnamespaceïŒãããã·ã¥æäœã«ãã£ãŠè¿ãããããã·ã¥ã«ãããã©ããã確èªããŸãã
- ããã§ãªãå Žåããµããªãã¬ãŒã·ã§ã³ã®ãã®è¡ã¯ç¡èŠãããŸãïŒè¿ãããŸããïŒã
- ããŒãååšããå Žåãããã·ã¥çµåã¯ããã·ã¥ããè¡ãååŸãããã®è¡ã«åºã¥ããŠäžæ¹ã§ããã¹ãŠã®ããã·ã¥è¡ã§è¡åºåãçæããŸãã
çµåã®äž¡åŽãäžåºŠã ãå®è¡ãããããšã«æ³šæããããšãéèŠã§ãïŒãã®å Žåãäž¡æ¹ãšãseqã¹ãã£ã³ã§ãïŒãæåã«ãããã·ã¥æäœã«ãã£ãŠåŒã³åºããããã®ã¯ããã·ã¥ã«æ ŒçŽããããã¹ãŠã®è¡ãè¿ãã2çªç®ã¯è¡ããšã«åŠçãããŸãããã¡ãŒã¹ãããŒãã£ããã·ã¥ã«ååšããªãè¡ã¯ã¹ããããããŸãïŒããã·ã¥ãè±å¯ã§ããã«ããããããããã®æãæ確ã§ããããšãé¡ã£ãŠããŸãïŒã
äž¡æ¹ã®ãµãã¹ãã£ã³ã¯ä»»æã®ã¿ã€ãã®æäœã§ããå¯èœæ§ãããããããã£ã«ã¿ãŒãã€ã³ããã¯ã¹ã¹ãã£ã³ããŸãã¯æ³åã§ãããããããã®ã«ãªãå¯èœæ§ããããŸãã
Hash Join / Hashã«é¢ããŠæåŸã«èšåãã䟡å€ãããã®ã¯ãHashæäœã¯ãSortãHashAggregateãšåæ§ã«ãwork_memãŸã§ã®ã¡ã¢ãªã䜿çšããããšã§ãã
ããã·ã¥çµå/ããã·ã¥
çµåã«ã€ããŠè©±ããŠããã®ã§ããã¹ãã«ãŒãã«ã€ããŠè°è«ãã䟡å€ããããŸãã äŸïŒ
$ explain analyze select a.* from pg_class c join pg_attribute a on c.oid = a.attrelid where c.relname in ( 'pg_class', 'pg_namespace' ); QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------- Nested Loop (cost=0.28..52.32 rows=16 width=203) (actual time=0.057..0.134 rows=46 loops=1) -> Seq Scan on pg_class c (cost=0.00..11.65 rows=2 width=4) (actual time=0.043..0.080 rows=2 loops=1) Filter: (relname = ANY ('{pg_class,pg_namespace}'::name[])) Rows Removed by Filter: 291 -> Index Scan using pg_attribute_relid_attnum_index on pg_attribute a (cost=0.28..20.25 rows=8 width=203) (actual time=0.007..0.015 rows=23 loops=2) Index Cond: (attrelid = c.oid) Total runtime: 0.182 ms
ããã¯ãéžæããæäœãè€æ°åå®è¡ã§ãããããéåžžã«èå³æ·±ãèšç»ã§ãã
ããã·ã¥çµåãšåæ§ã«ããã¹ããããã«ãŒãã«ã¯2ã€ã®ãåå«ãããããŸãã ãŸãããSeq Scanããèµ·åãïŒãã®äŸã§ã¯æåã«æåã®ããŒããèµ·åããŸãïŒã次ã«è¿ãããåè¡ïŒãã®äŸã§ã¯2è¡ã®ã¿ïŒã§2çªç®ã®æäœãéå§ããŸãïŒãã®äŸã§ã¯pg_attributeã«ããã€ã³ããã¯ã¹ã¹ãã£ã³ïŒã
ã€ã³ããã¯ã¹ã¹ãã£ã³ã®å®éã®ã¡ã¿æ å ±ã«ãã«ãŒã= 2ããããããšã«æ°ã¥ãããããããŸãããã€ãŸãããã®æäœã¯2åå®è¡ãããä»ã®å€ïŒè¡ãæéïŒã¯ãã¹ãŠã®å®è¡ã®å¹³åå€ã§ãã
Explain.depesz.comãã次ã®èšç»ãèŠãŠã¿ãŸãããã ã«ããŽãªã®ãã¹ãŠã®ã€ã³ããã¯ã¹ã¹ãã£ã³æäœã®å®éã®å®è¡æéã¯0.002ã0.003ããªç§ã§ããããšã«æ³šæããŠãã ããã ãã ãããã®ã€ã³ããã¯ã¹ã¹ãã£ã³ã¯26kå以äžå®è¡ãããããããã®ããŒãã§è²»ããããåèšæéã¯78.852msã§ãã
ãããã£ãŠãåŠçã¯æ¬¡ã®ããã«ãªããŸãã
- ãã¹ããããã«ãŒãã¯ããŠããªã³ã®æåã®ãµã€ããäžåºŠèµ·åããŸãã 圌女ããAããšåŒã³ãŸãããã
- ãAãããã®åè¡ã«ã€ããŠã2çªç®ã®æäœãéå§ãããŸãïŒãBããšåŒã³ãŸãããïŒã
- ãBããåäžã®è¡ãè¿ããªãã£ãå ŽåããAãããã®ããŒã¿ã¯ç¡èŠãããŸãã
- ãBããè¡ãè¿ããå Žåãè¿ãããè¡ããšã«ããã¹ããããã«ãŒãã¯Aããã³Bã®çŸåšã®è¡ã«åºã¥ããŠæ°ããè¡ãè¿ããŸãã
çµåãçµå
å¥ã®ããŒã¿ããŒãžæ¹æ³ã¯ãããŒãžçµåãšåŒã°ããŸãã çµåããŒã䜿çšããŠçµåå¯èœãªããŒã¿ã»ããã䞊ã¹æ¿ããããïŒãŸãã¯äœã³ã¹ãã§äžŠã¹æ¿ããããïŒå Žåã«äœ¿çšãããŸãã
æ¢è£œã®èŠèŠçãªäŸã¯ãªãã®ã§ãçµåããåã«ããŒã¿ããœãŒããããµãã¯ãšãªã䜿çšããŠäººçºçã«äœæããŸãã
$ explain analyze select * from ( select oid, * from pg_class order by oid) as c join ( select * from pg_attribute a order by attrelid) as a on c.oid = a.attrelid; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- Merge Join (cost=23.16..268.01 rows=2273 width=410) (actual time=0.658..3.779 rows=2274 loops=1) Merge Cond: (pg_class.oid = a.attrelid) -> Sort (cost=22.88..23.61 rows=292 width=207) (actual time=0.624..0.655 rows=293 loops=1) Sort Key: pg_class.oid Sort Method: quicksort Memory: 102kB -> Seq Scan on pg_class (cost=0.00..10.92 rows=292 width=207) (actual time=0.011..0.211 rows=293 loops=1) -> Materialize (cost=0.28..212.34 rows=2273 width=203) (actual time=0.028..1.264 rows=2274 loops=1) -> Index Scan using pg_attribute_relid_attnum_index on pg_attribute a (cost=0.28..183.92 rows=2273 width=203) (actual time=0.015..0.752 rows=2274 loops=1) Total runtime: 4.009 ms (9 rows)
ããŒãžçµåã¯ãä»ã®ãŠããªã³ãšåæ§ã«ã2ã€ã®ãµããªãã¬ãŒã·ã§ã³ïŒãã®å Žåã¯ãœãŒããšãããªã¢ã©ã€ãºïŒãå®è¡ããŸãã ã©ã¡ãã䞊ã¹æ¿ããããããŒã¿ãè¿ãã䞊ã¹æ¿ãé åºã¯çµåæäœã®å Žåãšåããªã®ã§ãPgã¯ãµãæäœã«ãã£ãŠè¿ãããäž¡æ¹ã®ããŒã¿ã»ãããã¹ãã£ã³ããåæã«èå¥åãäžèŽãããã©ããã確èªã§ããŸãã
æé ã¯æ¬¡ã®ãšããã§ãã
- å³åŽã®çµååãå·ŠåŽã®çµååãšåãå ŽåïŒ
- å·Šå³ã®çŸåšã®è¡ã«åºã¥ããŠãæ°ããé£çµè¡ãè¿ããŸãã
- 次ã®è¡ãå³ïŒãŸãã¯å³ã«è¡ããããªãå Žåã¯å·ŠïŒã«ç§»åããŸãã
- ã¹ããã1ã«æ»ããŸãã
- å³åŽã®çµååãå·ŠåŽã®çµååããããå°ãããå ŽåïŒ
- 次ã®è¡ãå³åŽã«ç§»åããŸãïŒããè¡ããªãå Žåã¯ãåŠçãçµäºããŸãïŒã
- ã¹ããã1ã«æ»ããŸãã
- å³åŽã®çµååãå·ŠåŽã®çµååãããã倧ãããå ŽåïŒ
- å·ŠåŽã®æ¬¡ã®è¡ãååŸããŸãïŒè¡ããããªãå Žåã¯ãåŠçãçµäºããŸãïŒã
- æé 1ã«æ»ããŸãã
ããã¯ãããŒã¿ã»ãããçµåããéåžžã«äŸ¿å©ãªæ¹æ³ã§ããããœãŒãããããœãŒã¹ã«å¯ŸããŠã®ã¿æ©èœããŸãã çŸåšã®Explain.depesz.comããŒã¿ããŒã¹ã«åºã¥ããŠã以äžããããŸãã
- æäœããã¹ããããã«ãŒãããå«ã44,721ã®èšç»ã
- ãããã·ã¥çµåãã䜿çšãã34,305ãã©ã³ã
- Merge Joinã䜿çšããåèš8,889ã®èšç»ã
ããã·ã¥çµå/ãã¹ããããã«ãŒã/çµåçµå修食å
äžèšã®ãã¹ãŠã®äŸã§ãçµåã®äž¡åŽããæååãåãåã£ãå Žåã«ã®ã¿ãçµåæäœãæååãè¿ãããšã瀺ããŸããã
ããããããã¯åžžã«èµ·ãããšã¯éããŸããã å·Šãå³ãå®å šïŒLEFT / RIGHT / FULL OUTER JOINïŒå€éšã¢ãœã·ãšãŒã·ã§ã³ãšãããããã¢ã³ãçµåã䜿çšã§ããŸãã
å·Š/å³çµåã®å Žåãæäœã®ååã¯æ¬¡ã®ããã«å€æŽãããŸãã
- ããã·ã¥å·Šçµåã
- ããã·ã¥å³çµåã
- å·Šçµåã®ããŒãžã
- å³çµåãããŒãžã
- ãã¹ããããã«ãŒãã®å·Šçµåã
ãã¹ããããã«ãŒãã®å³çµåã¯ååšããŸããããã¹ããããã«ãŒãã¯åžžã«å·ŠåŽããå§ãŸããã«ãŒãã®åºç€ãšããŠå·ŠåŽã䜿çšããããã§ãã ãããã£ãŠããã¹ããããã«ãŒãã§æ©èœããå³çµåã䜿çšããå ±çšäœã¯ããã¹ããããã«ãŒãæäœãæ©èœããããã«å éšçã«å·Šçµåã«å€æãããŸãã
ãããã®ãã¹ãŠã®å Žåã«ãããŠãè«çã¯åçŽã§ãïŒçµåã®2ã€ã®åŽé¢-å·Šãšå³ããããŸãã ãããŠããã®åŽããŠããªã³ã§èšåããããšã å察åŽã«å¯Ÿå¿ããè¡ããªãå Žåã§ããæ°ããè¡ãè¿ããŸãã
ããã¯ã次ã®ãããªã¯ãšãªã§çºçããŸãã
select * from a left join b on ...
ïŒãŸãã¯å³çµåïŒã
ããã·ã¥çµå/çµåã®çµåãšãã¹ããããã«ãŒãã«é¢ãããã®ä»ã®æ å ±ã¯ãã¹ãŠåãã§ãã©ã€ã³åºåãçæãããã¿ã€ãã³ã°ã®ããžãã¯ã«ããããªå€æŽã®ã¿ããããŸãã
次ã®æäœåãæã€å®å šçµåãšåŒã°ããããŒãžã§ã³ããããŸãã
- ããã·ã¥å®å šçµåã
- å®å šçµåãããŒãžããŸãã
ãã®å Žåãã©ã¡ããã®åŽã«ããŒã¿ããããã©ããã«é¢ä¿ãªãããŠããªã³ã¯æ°ããè¡åºåãçæããŸãïŒããŒã¿ãå°ãªããšãçåŽã«ããéãïŒã ããã¯æ¬¡ã®å Žåã«çºçããŸãã
select * from a full join b ...
åã®äŸã®ããã«ããã¹ãŠã®åŠçãçºçããŸãã
ããã«ãããããã¢ã³ãçµåããããŸãã æäœã®ååã¯æ¬¡ã®ãšããã§ãã
- ããã·ã¥ã¢ã³ãçµåã
- ã¢ã³ãçµåã®ããŒãžã
- ãã¹ãã«ãŒãã¢ã³ãçµåã
ãããã®å ŽåãJoinã¯ãå³åŽã§åäžã®æååãèŠã€ãããªãå Žåã«ã®ã¿æååãè¿ããŸãã ããã¯ããWHERE not existsïŒïŒããŸãã¯ãleft join ... where right_table.column is nullããªã©ã®æäœãè¡ãå Žåã«åœ¹ç«ã¡ãŸãã
ãã®äŸã®ããã«ïŒ
$ explain analyze select * from pg_class c where not exists (select * from pg_attribute a where a.attrelid = c.oid and a.attnum = 10); QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------- Hash Anti Join (cost=62.27..78.66 rows=250 width=203) (actual time=0.145..0.448 rows=251 loops=1) Hash Cond: (c.oid = a.attrelid) -> Seq Scan on pg_class c (cost=0.00..10.92 rows=292 width=207) (actual time=0.009..0.195 rows=293 loops=1) -> Hash (cost=61.75..61.75 rows=42 width=4) (actual time=0.123..0.123 rows=42 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 2kB -> Index Only Scan using pg_attribute_relid_attnum_index on pg_attribute a (cost=0.28..61.75 rows=42 width=4) (actual time=0.021..0.109 rows=42 loops=1) Index Cond: (attnum = 10) Heap Fetches: 0 Total runtime: 0.521 ms (9 rows)
ããã§ãPgã¯å³åŽïŒpg_attributeã«ããã€ã³ããã¯ã¹ã¹ãã£ã³ïŒãå®è¡ããããã·ã¥ããŠããå·ŠåŽïŒpg_classã«ããSeqã¹ãã£ã³ïŒãå®è¡ããæå®ãããpg_class.oidã®Hashã«ãšã³ããªããªãã£ãè¡ã®ã¿ãè¿ããŸããã
ãããªã¢ã©ã€ãº
ãã®æäœã¯ãçµåçµåã®äŸã§ãã§ã«å®èšŒãããŠããŸãããä»ã®å Žåã«åœ¹ç«ã€å ŽåããããŸãã
Psqlã«ã¯å€ãã®å éšã³ãã³ãããããŸãã ãããã®1ã€ã¯\ dTSã§ããã¹ãŠã®ã·ã¹ãã ããŒã¿ã¿ã€ãããªã¹ãããŸãã å éšçã«ã\ dTSã¯ãã®ãªã¯ãšã¹ããå®è¡ããŸãïŒ
SELECT n.nspname as "Schema", pg_catalog.format_type(t.oid, NULL) AS "Name", pg_catalog.obj_description(t.oid, 'pg_type') as "Description" FROM pg_catalog.pg_type t LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace WHERE (t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid) AND pg_catalog.pg_type_is_visible(t.oid) ORDER BY 1, 2;
圌ã®èšç»ã¯ããã§ãïŒ
QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------- Sort (cost=2783.00..2783.16 rows=65 width=68) (actual time=3.883..3.888 rows=87 loops=1) Sort Key: n.nspname, (format_type(t.oid, NULL::integer)) Sort Method: quicksort Memory: 39kB -> Nested Loop Left Join (cost=16.32..2781.04 rows=65 width=68) (actual time=0.601..3.657 rows=87 loops=1) Join Filter: (n.oid = t.typnamespace) Rows Removed by Join Filter: 435 -> Hash Anti Join (cost=16.32..2757.70 rows=65 width=8) (actual time=0.264..0.981 rows=87 loops=1) Hash Cond: ((t.typelem = el.oid) AND (t.oid = el.typarray)) -> Seq Scan on pg_type t (cost=0.00..2740.26 rows=81 width=12) (actual time=0.012..0.662 rows=157 loops=1) Filter: (pg_type_is_visible(oid) AND ((typrelid = 0::oid) OR (SubPlan 1))) Rows Removed by Filter: 185 SubPlan 1 -> Index Scan using pg_class_oid_index on pg_class c (cost=0.15..8.17 rows=1 width=1) (actual time=0.002..0.002 rows=1 loops=98) Index Cond: (oid = t.typrelid) -> Hash (cost=11.33..11.33 rows=333 width=8) (actual time=0.241..0.241 rows=342 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 14kB -> Seq Scan on pg_type el (cost=0.00..11.33 rows=333 width=8) (actual time=0.002..0.130 rows=342 loops=1) -> Materialize (cost=0.00..1.09 rows=6 width=68) (actual time=0.000..0.001 rows=6 loops=87) -> Seq Scan on pg_namespace n (cost=0.00..1.06 rows=6 width=68) (actual time=0.002..0.003 rows=6 loops=1) Total runtime: 3.959 ms
èŠãããããããã«ããã®ãã©ã³ãExplain.depesz.comã«ã¢ããããŒãããŸãã ã
æäœïŒ9ã¯ãããªã¢ã©ã€ãºã§ããããšã«æ³šæããŠãã ããã ãªãã§ïŒ
ãããªã¢ã©ã€ãºã¯ãã¹ããããã«ãŒãã®å·Šçµå-æäœïŒ2ã«ãã£ãŠåŒã³åºãããŸãã ãã¹ããããã«ãŒãã«ãããéžæãããæäœã匷å¶çã«è€æ°åããã®å Žåã¯87åå®è¡ãããŸãã
ãŠããªã³ã®å³åŽã¯ãpg_namespaceã«ããSeq Scanã§ãã ãã®ãããçè«çã«ã¯ãPostgresã¯pg_namespaceã®ã·ãŒã±ã³ã·ã£ã«ã¹ãã£ã³ã87åå®è¡ããå¿ èŠããããŸãã ãã®ããŒãã«ã®1åã®é 次ã¹ãã£ã³ã«0.003ããªç§ãããããšãèæ ®ãããšãåèšæéã¯çŽ0.25ããªç§ã«ãªããšäºæ³ã§ããŸãã
ããããPostgresã¯ããã¹ããŒãã«ãªã£ãŠããŸãã 圌ã¯ãããŒãã«ã1åã¹ãã£ã³ããŠããã¹ãŠã®è¡ã®ã€ã¡ãŒãžãã¡ã¢ãªã«æ§ç¯ããæ¹ãã³ã¹ããäœãããšãç解ããŠããŸãã 次ã«ãããŒãã«ãã¹ãã£ã³ããå¿ èŠããªãå Žåã¯ãå¯èŠæ§æ å ±ã確èªããããŒã¿ããŒãžã解æããŸãã åã«ã¡ã¢ãªããããŒã¿ãååŸããŸãã
ããã«ããããã¹ãŠã®åèšæéïŒããŒãã«ã1åèªã¿åããã¡ã¢ãªã«ããŒã¿ã€ã¡ãŒãžãæºåãããã®ã€ã¡ãŒãžã87åã¹ãã£ã³ããïŒã¯0.087msã§ããã
ããªãã¯èšãããšãã§ããŸãïŒããããããªãçµåã¯ä»¥åã«ãããªã¢ã©ã€ãºã䜿çšããã®ã§ãããããã¯ãã£ã1åã®ã¹ãã£ã³ãå®è¡ããã®ã§ããïŒãèšç»ãæãåºããŸãããïŒ
$ explain analyze select * from ( select oid, * from pg_class order by oid) as c join ( select * from pg_attribute a order by attrelid) as a on c.oid = a.attrelid; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- Merge Join (cost=23.16..268.01 rows=2273 width=410) (actual time=0.658..3.779 rows=2274 loops=1) Merge Cond: (pg_class.oid = a.attrelid) -> Sort (cost=22.88..23.61 rows=292 width=207) (actual time=0.624..0.655 rows=293 loops=1) Sort Key: pg_class.oid Sort Method: quicksort Memory: 102kB -> Seq Scan on pg_class (cost=0.00..10.92 rows=292 width=207) (actual time=0.011..0.211 rows=293 loops=1) -> Materialize (cost=0.28..212.34 rows=2273 width=203) (actual time=0.028..1.264 rows=2274 loops=1) -> Index Scan using pg_attribute_relid_attnum_index on pg_attribute a (cost=0.28..183.92 rows=2273 width=203) (actual time=0.015..0.752 rows=2274 loops=1) Total runtime: 4.009 ms (9 rows)
, . , Merge Join . ( ), , ( ).
- Materialize , ( Index Scan), , .
, Materialize ( ), , , .
ä»æ¥ã¯ä»¥äžã§ããç§ã¯ãããçµäºãããšæã£ããã説æãã䟡å€ã®ããæäœãããã«ããããããã®ã§ããã®ã·ãªãŒãºã§ã¯å°ãªããšã2ã€ã®æçš¿ïŒæ®ãã®æäœãšçµ±èšæ å ±ïŒããããŸãã