PostgreSQL'de EXPLAIN Kullanımı


EXPLAIN ifadesi bir sorgunun çalışma planını bize sunar. Sorgu aslında gerçekte çalışmaz, yani INSERT/UPDATE/DELETE sorgularına da EXPLAIN ile planına bakabilirsiniz. EXPLAIN'i aşağıdaki seçeneklerle birlikte kullanabilirsiniz:

  • ANALYZE [ boolean ]: Sorguyu gerçekten çalıştırır ve tüm kısımlarla ilgili ayrıntılı bilgi verir. INSERT/UPDATE/DELETE sorguları için;
         BEGIN;
         EXPLAIN ANALYZE sorgu;
         ROLLBACK;
    ifadesi içinde kullanılması önerilir.
  • VERBOSE [ boolean ]: Varsayılan değeri FALSE olan bu değer sorgu ile ilgili ayrıntılı bilgi verir.
  • COSTS [ boolean ]: Varsayılan olarak TRUE gelen bu değer sorgunun toplam maliyeti ve her bir parçasının tahmini satır değeri gibi ayrıntıları verir.
  • BUFFERS [ boolean ]: Varsayılan olarak FALSE gelen ve yalnızca ANALYZE ile kullanılabilen bu değer sorgunun buffer kullanımı ile ilgili bilgi verir.
  • TIMING [ boolean ]: Varsayılan olarak TRUE gelen ve yalnızca ANALYZE ile kullanılabilen  bu değer sorgunun her bir parçasının süresi ile ilgili ayrıntılı bilgi verir.
  • SUMMARY [ boolean ]: ANALYZE ile birlikte varsayılan olarak kullanılan bu değer sorgu planının en sonunda plan ve çalışma süreleri ile ilgili süre bilgisi verir.
  • FORMAT { TEXT | XML | JSON | YAML }: Varsayılan olarak TEXT gelen bu değer sorgu planının tipini belirlemek için kullanılır.

Örneklerle EXPLAIN'i açıklamak için bir tablo oluşturalım ve random veri ekleyelim:
 postgres=# CREATE TABLE t1 (c1 serial, c2 text);
CREATE TABLE
postgres=#  INSERT INTO t1(c2) SELECT md5(random()::text) FROM  generate_series(1,1000000);
INSERT 0 1000000

EXPLAIN ile sorgu planına bakalım:
postgres=# EXPLAIN  SELECT c2 FROM t1 WHERE c1 < 20;
                         QUERY PLAN                         
------------------------------------------------------------
 Seq Scan on t1  (cost=0.00..21564.22 rows=352806 width=32)
   Filter: (c1 < 20)
(2 rows)                                                                                                                                                                                                                         

ANALYZE ifadesi eklendiğinde sorgu gerçekten çalıştı ve sorgu planında satır satıyı ve çalışma süresi ile ilgili ayrıntılı bilgi verdi:
postgres=# EXPLAIN ANALYZE SELECT c2 FROM t1 WHERE c1 < 20;
                                                    QUERY PLAN                                                    
-------------------------------------------------------------------------------------------------------------------
 Gather  (cost=1000.00..14552.33 rows=100 width=33) (actual time=0.735..60.184 rows=19 loops=1)
   Workers Planned: 2
   Workers Launched: 2
   ->  Parallel Seq Scan on t1  (cost=0.00..13542.33 rows=42 width=33) (actual time=31.826..50.377 rows=6 loops=3)
         Filter: (c1 < 20)
         Rows Removed by Filter: 333327
 Planning Time: 0.576 ms
 Execution Time: 60.222 ms
(8 rows)

                                                                                                                         

COST seçeneği varsayılan olarak açık gelir ve kullanmak istemediğimizca aşağıdaki örnekteki gibi COST OFF olarak belirtmemiz gerekir:
postgres=# EXPLAIN (ANALYZE, COSTS OFF) SELECT c2 FROM t1 WHERE c1 < 20;
                                QUERY PLAN                                 
---------------------------------------------------------------------------
 Gather (actual time=0.484..66.711 rows=19 loops=1)
   Workers Planned: 2
   Workers Launched: 2
   ->  Parallel Seq Scan on t1 (actual time=35.399..56.227 rows=6 loops=3)
         Filter: (c1 < 20)
         Rows Removed by Filter: 333327
 Planning Time: 0.094 ms
 Execution Time: 66.746 ms
(8 rows)



BUFFERS seçeneği sorgu için ne kadar buffer'ın shared buffers'tan geldiğini gösterir Varsayılan olarak kapalı olduğu için bu seçeneği kullanmak isterseniz aşağıdaki örnekteki gibi BUFFERS ON olarak belirtmenir gerekir:

postgres=# EXPLAIN (ANALYZE, BUFFERS ON)  SELECT c2 FROM t1 WHERE c1 < 20;
                                                    QUERY PLAN                                                    
-------------------------------------------------------------------------------------------------------------------
 Gather  (cost=1000.00..14552.33 rows=100 width=33) (actual time=0.281..40.477 rows=19 loops=1)
   Workers Planned: 2
   Workers Launched: 2
   Buffers: shared hit=8334
   ->  Parallel Seq Scan on t1  (cost=0.00..13542.33 rows=42 width=33) (actual time=22.078..34.403 rows=6 loops=3)
         Filter: (c1 < 20)
         Rows Removed by Filter: 333327
         Buffers: shared hit=8334
 Planning Time: 0.059 ms
 Execution Time: 40.500 ms
(10 rows)


TIMING seçeneği sorgu planının her parçasındaki actual time bilgisini gizler. Bu seçeneği kullanmadığımızca varsayılan olarak TRUE gelir, bu seçeneği kullanmak istemiyorsanız aşağıdaki örnekteki gibi TIMING FALSE olarak belirtmeniz gerekir:

postgres=# EXPLAIN (ANALYZE, TIMING FALSE)  SELECT c2 FROM t1 WHERE c1 < 20;
                                          QUERY PLAN                                          
-----------------------------------------------------------------------------------------------
 Gather  (cost=1000.00..14552.33 rows=100 width=33) (actual rows=19 loops=1)
   Workers Planned: 2
   Workers Launched: 2
   ->  Parallel Seq Scan on t1  (cost=0.00..13542.33 rows=42 width=33) (actual rows=6 loops=3)
         Filter: (c1 < 20)
         Rows Removed by Filter: 333327
 Planning Time: 0.128 ms
 Execution Time: 52.260 ms
(8 rows)



SUMMARY seçeneği sorgunun en sonundaki plan ve çalışma süresi bilgisini verir. Sürelerle ilgili bilginin planda bulunmasını istemediğinizde SUMMARY FALSE olarak kullanabilirsiniz:

postgres=# EXPLAIN (ANALYZE, SUMMARY FALSE)  SELECT c2 FROM t1 WHERE c1 < 20;
                                                    QUERY PLAN                                                    
-------------------------------------------------------------------------------------------------------------------
 Gather  (cost=1000.00..14552.33 rows=100 width=33) (actual time=0.588..51.397 rows=19 loops=1)
   Workers Planned: 2
   Workers Launched: 2
   ->  Parallel Seq Scan on t1  (cost=0.00..13542.33 rows=42 width=33) (actual time=26.160..41.197 rows=6 loops=3)
         Filter: (c1 < 20)
         Rows Removed by Filter: 333327
(6 rows)




FORMAT seçeneği sorgu planının formatını belirlemek için kullanılır. Varsayılan olarak text gelir ve sorgu planını  XML, JSON veya YAML olarak görmek istiyorsanız bunu aşağıdaki örnekteki gibi belirtmeniz gerekir:

postgres=# EXPLAIN (ANALYZE, FORMAT XML)  SELECT c2 FROM t1 WHERE c1 < 20;
                            QUERY PLAN                            
-------------------------------------------------------------------
 <explain xmlns="http://www.postgresql.org/2009/explain">         +
   <Query>                                                        +
     <Plan>                                                       +
       <Node-Type>Gather</Node-Type>                              +
       <Parallel-Aware>false</Parallel-Aware>                     +
       <Startup-Cost>1000.00</Startup-Cost>                       +
       <Total-Cost>14552.33</Total-Cost>                          +
       <Plan-Rows>100</Plan-Rows>                                 +
       <Plan-Width>33</Plan-Width>                                +
       <Actual-Startup-Time>0.549</Actual-Startup-Time>           +
       <Actual-Total-Time>49.861</Actual-Total-Time>              +
       <Actual-Rows>19</Actual-Rows>                              +
       <Actual-Loops>1</Actual-Loops>                             +
       <Workers-Planned>2</Workers-Planned>                       +
       <Workers-Launched>2</Workers-Launched>                     +
       <Single-Copy>false</Single-Copy>                           +
       <Plans>                                                    +
         <Plan>                                                   +
           <Node-Type>Seq Scan</Node-Type>                        +
           <Parent-Relationship>Outer</Parent-Relationship>       +
           <Parallel-Aware>true</Parallel-Aware>                  +
           <Relation-Name>t1</Relation-Name>                      +
           <Alias>t1</Alias>                                      +
           <Startup-Cost>0.00</Startup-Cost>                      +
           <Total-Cost>13542.33</Total-Cost>                      +
           <Plan-Rows>42</Plan-Rows>                              +
           <Plan-Width>33</Plan-Width>                            +
           <Actual-Startup-Time>25.595</Actual-Startup-Time>      +
           <Actual-Total-Time>40.413</Actual-Total-Time>          +
           <Actual-Rows>6</Actual-Rows>                           +
           <Actual-Loops>3</Actual-Loops>                         +
           <Filter>(c1 &lt; 20)</Filter>                          +
           <Rows-Removed-by-Filter>333327</Rows-Removed-by-Filter>+
         </Plan>                                                  +
       </Plans>                                                   +
     </Plan>                                                      +
     <Planning-Time>0.149</Planning-Time>                         +
     <Triggers>                                                   +
     </Triggers>                                                  +
     <Execution-Time>49.899</Execution-Time>                      +
   </Query>                                                       +
 </explain>
(1 row)

















Yorumlar