如何使用参数/变量并一起解释

时间:2016-07-14 03:39:51

标签: sql performance postgresql pgadmin sql-execution-plan

我的函数有一个参数carAzimuth

CREATE OR REPLACE FUNCTION map.get_near_link(x numeric, y numeric, carAzimuth numeric)

我在里面有一些计算和这个查询

SELECT *
FROM map.vzla_seg S
WHERE
    S.azimuth > carAzimuth - 30  and   
    S.azimuth < carAzimuth + 30  or
    S.azimuth < carAzimuth - 330 or 
    S.azimuth > carAzimuth + 330;

我想分析查询性能。所以我必须将变量替换为常量。并且工作正常,EXPLAIN PLAN显示我正在使用正确的索引。

EXPLAIN ANALYZE    
 SELECT *
 FROM map.vzla_seg S
 WHERE
    S.azimuth > 345 - 30  and   
    S.azimuth < 345 + 30  or
    S.azimuth < 345 - 330 or 
    S.azimuth > 345 + 330;

但是如果想要测试不同的值,则很难改变每个变量。然后,如果你尝试

EXPLAIN ANALYZE  
  WITH param(carAzimuth) as (select 345) 
  SELECT *
  FROM vzla_seg S, param 
  WHERE
      S.azimuth > carAzimuth- 30 and   
      S.azimuth < carAzimuth + 30 or
      S.azimuth < carAzimuth - 330 or 
      S.azimuth > carAzimuth + 330;

工作但停止使用索引并更改FULL SCAN

"Nested Loop  (cost=0.01..208990.91 rows=2328905 width=4) (actual time=0.146..4138.882 rows=642115 loops=1)"
"  Join Filter: (((s.azimuth > (p.carazimuth - 30)) AND (s.azimuth < (p.carazimuth + 30))) OR (s.azimuth < (p.carazimuth - 330)) OR (s.azimuth > (p.carazimuth + 330)))"
"  Rows Removed by Join Filter: 3207719"
"  CTE parameter"
"    ->  Result  (cost=0.00..0.01 rows=1 width=0) (actual time=0.002..0.002 rows=1 loops=1)"
"  ->  CTE Scan on parameter p  (cost=0.00..0.02 rows=1 width=4) (actual time=0.009..0.012 rows=1 loops=1)"
"  ->  Seq Scan on vzla_seg s  (cost=0.00..93496.22 rows=3849822 width=4) (actual time=0.072..1380.356 rows=3849834 loops=1)"
"Total runtime: 4253.113 ms"

那么有没有一种方法可以创建我的变量并在没有函数的情况下在解释中使用它?

我在pgAdmin上使用SQL编辑器来运行我的查询。

1 个答案:

答案 0 :(得分:3)

您的假设所以WITH子句是等效函数是错误的。条款WITHCommon Table Expressions有关,与函数关系不大。当你想看到函数的计划时,有两种可能性:

  1. 使用auto_explain扩展程序 - 使用此扩展程序,您可以记录任何嵌套计划 - 只需启用选项auto_explain.log_nested_statements

  2. 您可以使用预准备语句 - 任何SQL都透明地翻译为PLpgSQL中的预处理语句。

    prepare xx(int) as select * from foo where a = $1::text;
    explain analyze execute xx(10);
    ┌───────────────────────────────────────────────────────────────────────────────────────────────┐
    │                                          QUERY PLAN                                           │
    ╞═══════════════════════════════════════════════════════════════════════════════════════════════╡
    │ Seq Scan on foo  (cost=0.00..21.00 rows=4 width=64) (actual time=0.019..0.019 rows=0 loops=1) │
    │   Filter: (a = '10'::text)                                                                   │
    │   Rows Removed by Filter: 2                                                                   │
    │ Execution time: 0.052 ms                                                                      │
    └───────────────────────────────────────────────────────────────────────────────────────────────┘
    

    注意:前5次执行计划总是新鲜的(不会被重复使用,并且会一次又一次地生成)。执行5次后,该计划可以是通用的并重复使用。请参阅related documentation中的计划缓存一章。