Postgres的CTE与子查询的性能差异。为什么呢?

时间:2015-11-16 08:30:06

标签: postgresql postgis common-table-expression

我有两个等效查询,用于提取特定区域(ace)和城市(pro_com)中建筑物(表a)与最近的高速公路(表v中的高速公路)之间的平均距离。

这是CTE版本

WITH subq AS (
SELECT a.n, a.geom as g1, unnest(ARRAY(SELECT v.geom as g2 
  FROM atlas_sezioni2 as v
  where v.code = '12230' and a.pro_com = v.pro_com and a.code <> v.code  
  ORDER BY a.geom <-> v.geom LIMIT 15)) as g2
FROM atlas_sezioni2 a
where a.pro_com = 15146 and a.ace = 1 and a.code IN('11100', '11210', '11220', '11230', '11240', '11300', '12100', '14200')  
)

select avg(dist) from (
select distinct on(n) n, dist
from (
SELECT n, ST_Distance_Sphere(g1, g2) as dist FROM subq
) disttable
order by n, dist asc
) final;

在CTE中,我提取最近的15条高速公路并计算距离,以便使用GIST索引(http://workshops.boundlessgeo.com/postgis-intro/knn.html)。 而CTE的解释是:

Aggregate  (cost=37342.10..37342.11 rows=1 width=8)
   CTE subq
     ->  Index Scan using atlas_sezioni2_code_ace_pro_com_n_idx on atlas_sezioni2 a  (cost=0.29..29987.90 rows=20900 width=236211)
       Index Cond: (((code)::text = ANY ('{11100,11210,11220,11230,11240,11300,12100,14200}'::text[])) AND (ace = 1) AND (pro_com = 15146::numeric))
       SubPlan 1
         ->  Limit  (cost=141.04..141.08 rows=15 width=236190)
               ->  Sort  (cost=141.04..141.21 rows=69 width=236190)
                     Sort Key: ((a.geom <-> v.geom))
                     ->  Index Scan using atlas_sezioni2_code_ace_pro_com_n_idx on atlas_sezioni2 v  (cost=0.28..139.35 rows=69 width=236190)
                           Index Cond: (((code)::text = '12230'::text) AND (a.pro_com = pro_com))
                           Filter: ((a.code)::text <> (code)::text)
   ->  Unique  (cost=7247.20..7351.70 rows=200 width=72)
     ->  Sort  (cost=7247.20..7299.45 rows=20900 width=72)
           Sort Key: subq.n, (_st_distance(geography(subq.g1), geography(subq.g2), 0::double precision, false))
           ->  CTE Scan on subq  (cost=0.00..5747.50 rows=20900 width=72)
(15 rows)

这与子查询等效:

select avg(dist) from (
select distinct on(n) n, dist
from (
SELECT n, ST_Distance_Sphere(g1, g2) as dist FROM (
SELECT a.n, a.geom as g1, unnest(ARRAY(SELECT v.geom as g2 
  FROM atlas_sezioni2 as v
  where v.code = '12230' and a.pro_com = v.pro_com and a.code <> v.code  
  ORDER BY a.geom <-> v.geom LIMIT 15)) as g2
FROM atlas_sezioni2 a
where a.pro_com = 15146 and a.ace = 1 and a.code IN('11100', '11210', '11220', '11230', '11240', '11300', '12100', '14200')  
) subq
) disttable
order by n, dist asc
) final

及其解释

Aggregate  (cost=6366298.35..6366298.36 rows=1 width=8)
   ->  Unique  (cost=6365932.60..6366037.10 rows=20900 width=236230)
     ->  Sort  (cost=6365932.60..6365984.85 rows=20900 width=236230)
           Sort Key: subq.n, (_st_distance(geography(subq.g1), geography(subq.g2), 0::double precision, false))
           ->  Subquery Scan on subq  (cost=0.29..35526.40 rows=20900 width=236230)
                 ->  Index Scan using atlas_sezioni2_code_ace_pro_com_n_idx on atlas_sezioni2 a  (cost=0.29..29987.90 rows=20900 width=236211)
                       Index Cond: (((code)::text = ANY ('{11100,11210,11220,11230,11240,11300,12100,14200}'::text[])) AND (ace = 1) AND (pro_com = 15146::numeric))
                       SubPlan 1
                         ->  Limit  (cost=141.04..141.08 rows=15 width=236190)
                               ->  Sort  (cost=141.04..141.21 rows=69 width=236190)
                                     Sort Key: ((a.geom <-> v.geom))
                                     ->  Index Scan using atlas_sezioni2_code_ace_pro_com_n_idx on atlas_sezioni2 v  (cost=0.28..139.35 rows=69 width=236190)
                                           Index Cond: (((code)::text = '12230'::text) AND (a.pro_com = pro_com))
                                           Filter: ((a.code)::text <> (code)::text)
(14 rows)

我知道CTE是优化的边界围栏(Postgres不会在CTE和它们之外的查询之间进行优化),但这很奇怪。为什么表现会以这种方式吹灭?

1 个答案:

答案 0 :(得分:2)

正如@CraigRinger所说,我应该检查一下分析。事实上,来自&#34;解释分析&#34;我们看到第一个是:

WebView webView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        webView = (WebView) findViewById(R.id.webview);
        String url="http://www.google.com";
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
        });
        webView.loadUrl(url);
    }

而子查询是:

Aggregate  (cost=58406.66..58406.67 rows=1 width=8) (actual time=138191.294..138191.295 rows=1 loops=1)
 CTE subq
   ->  Bitmap Heap Scan on atlas_sezioni2 a  (cost=9.93..51052.46 rows=20900 width=236211) (actual time=2.814..308.667 rows=3705 loops=1)
         Recheck Cond: (ace = 1)
         Filter: ((pro_com = 15146::numeric) AND ((code)::text = ANY ('{11100,11210,11220,11230,11240,11300,12100,14200}'::text[])))
         Rows Removed by Filter: 4
         Heap Blocks: exact=42
         ->  Bitmap Index Scan on atlas_sezioni2_ace_idx  (cost=0.00..9.88 rows=251 width=0) (actual time=0.110..0.110 rows=251 loops=1)
               Index Cond: (ace = 1)
         SubPlan 1
           ->  Limit  (cost=240.70..240.74 rows=15 width=236190) (actual time=0.630..0.636 rows=15 loops=247)
                 ->  Sort  (cost=240.70..240.87 rows=69 width=236190) (actual time=0.627..0.630 rows=15 loops=247)
                       Sort Key: ((a.geom <-> v.geom))
                       Sort Method: top-N heapsort  Memory: 26kB
                       ->  Bitmap Heap Scan on atlas_sezioni2 v  (cost=4.56..239.01 rows=69 width=236190) (actual time=0.045..0.518 rows=73 loops=247)
                             Recheck Cond: ((code)::text = '12230'::text)
                             Filter: (((a.code)::text <> (code)::text) AND (a.pro_com = pro_com))
                             Heap Blocks: exact=6916
                             ->  Bitmap Index Scan on atlas_sezioni2_code_idx  (cost=0.00..4.55 rows=73 width=0) (actual time=0.030..0.030 rows=73 loops=247)
                                   Index Cond: ((code)::text = '12230'::text)
 ->  Unique  (cost=7247.20..7351.70 rows=200 width=72) (actual time=138190.527..138191.243 rows=247 loops=1)
       ->  Sort  (cost=7247.20..7299.45 rows=20900 width=72) (actual time=138190.526..138190.800 rows=3705 loops=1)
             Sort Key: subq.n, (_st_distance(geography(subq.g1), geography(subq.g2), 0::double precision, false))
             Sort Method: quicksort  Memory: 270kB
             ->  CTE Scan on subq  (cost=0.00..5747.50 rows=20900 width=72) (actual time=159.739..138182.891 rows=3705 loops=1)
 Planning time: 2.623 ms
 Execution time: 138217.574 ms
(27 rows)

所以它只在解释:)中表现更好。真正的表现并没有改变。