提高Postgresql中的函数性能

提高Postgresql中的函数性能,sql,performance,postgresql,function,Sql,Performance,Postgresql,Function,下面的函数是创建一个临时表,然后在其中填充数据 该临时表应该在点击网站上的按钮时显示 我试图提高性能的步骤: 1.修改了postgresql.conf文件。 2.在临时表中添加了索引 CREATE OR REPLACE FUNCTION lastonemonth() RETURNS void AS $BODY$ DECLARE query1 text; query2 text; var_loop1 RECORD; dealerName text; cur_minus_

下面的函数是创建一个临时表,然后在其中填充数据

该临时表应该在点击网站上的按钮时显示

我试图提高性能的步骤: 1.修改了postgresql.conf文件。 2.在临时表中添加了索引

CREATE OR REPLACE FUNCTION lastonemonth()
  RETURNS void AS
$BODY$
  DECLARE
  query1 text;
  query2 text;
  var_loop1 RECORD;
  dealerName text;
  cur_minus_2_month text; 
  var_sum_of_quantity numeric;
  var_net_value numeric;
  var_average_price_nsr numeric; 
  BEGIN
  EXECUTE 'DROP TABLE IF EXISTS LOM CASCADE';
  EXECUTE 'CREATE TEMP TABLE LOM ( dealer_name text PRIMARY KEY , sum_of_quantity numeric, net_value numeric, average_price_nsr numeric)';
  EXECUTE 'CREATE UNIQUE INDEX dealer_name_idx ON LOM (dealer_name)';

  query1:= 'SELECT DISTINCT dealer FROM customernotorderdb_temp WHERE month IN ( to_char( now() - interval ''2 month'', ''YYYYMM'') , to_char( now() - interval ''3 month'', ''YYYYMM''))EXCEPT SELECT DISTINCT dealer FROM customernotorderdb_temp WHERE month IN ( to_char( now() - interval ''1 month'', ''YYYYMM''), to_char(now(), ''YYYYMM'') )';
  FOR var_loop1 IN EXECUTE (query1)
  LOOP
      dealerName:= var_loop1.dealer;
      INSERT INTO LOM(dealer_name) VALUES(dealerName);
      EXECUTE 'SELECT month FROM customernotorderdb_temp WHERE dealer LIKE ''%'||dealerName||'%'' AND month IN(to_char( now() - interval ''2 month'', ''YYYYMM''))' INTO cur_minus_2_month;

      --RAISE NOTICE 'cur_minus_2_month( % )', cur_minus_2_month;
      IF cur_minus_2_month IS NOT NULL 
      THEN
          EXECUTE 'SELECT SUM(saleqtypermt) FROM customernotorderdb_temp WHERE dealer LIKE ''%'||dealerName||'%'' AND month IN (to_char( now() - interval ''2 month'', ''YYYYMM''),to_char( now() - interval ''3 month'', ''YYYYMM''),to_char( now() - interval ''4 month'', ''YYYYMM''),to_char( now() - interval ''5 month'', ''YYYYMM''),to_char( now() - interval ''6 month'', ''YYYYMM''),to_char( now() - interval ''7 month'', ''YYYYMM''),to_char( now() -interval ''8 month'', ''YYYYMM''),to_char( now() - interval ''9 month'', ''YYYYMM''),to_char( now() - interval ''10 month'', ''YYYYMM''),to_char( now() - interval ''11 month'', ''YYYYMM''),to_char( now() - interval ''12 month'', ''YYYYMM''),to_char( now() - interval ''13 month'', ''YYYYMM''))' INTO var_sum_of_quantity;
          EXECUTE 'SELECT SUM(basic_value-rate_diff) FROM customernotorderdb_temp WHERE dealer LIKE ''%'||dealerName||'%'' AND month IN (to_char( now() - interval ''2 month'', ''YYYYMM''),to_char( now() - interval ''3 month'', ''YYYYMM''),to_char( now() - interval ''4 month'', ''YYYYMM''),to_char( now() - interval ''5 month'', ''YYYYMM''),to_char( now() - interval ''6 month'', ''YYYYMM''),to_char( now() - interval ''7 month'', ''YYYYMM''),to_char( now() -interval ''8 month'', ''YYYYMM''),to_char( now() - interval ''9 month'', ''YYYYMM''),to_char( now() - interval ''10 month'', ''YYYYMM''),to_char( now() - interval ''11 month'', ''YYYYMM''),to_char( now() - interval ''12 month'', ''YYYYMM''),to_char( now() - interval ''13 month'', ''YYYYMM''))' INTO var_net_value;
          EXECUTE 'SELECT SUM(avgpricensr) FROM customernotorderdb_temp WHERE dealer LIKE ''%'||dealerName||'%'' AND month IN (to_char( now() - interval ''2 month'', ''YYYYMM''),to_char( now() - interval ''3 month'', ''YYYYMM''),to_char( now() - interval ''4 month'', ''YYYYMM''),to_char( now() - interval ''5 month'', ''YYYYMM''),to_char( now() - interval ''6 month'', ''YYYYMM''),to_char( now() - interval ''7 month'', ''YYYYMM''),to_char( now() -interval ''8 month'', ''YYYYMM''),to_char( now() - interval ''9 month'', ''YYYYMM''),to_char( now() - interval ''10 month'', ''YYYYMM''),to_char( now() - interval ''11 month'', ''YYYYMM''),to_char( now() - interval ''12 month'', ''YYYYMM''),to_char( now() - interval ''13 month'', ''YYYYMM''))' INTO var_average_price_nsr;
          --RAISE NOTICE 'A [ %   % ]', dealername,var_net_value;
          UPDATE LOM SET sum_of_quantity=var_sum_of_quantity,
                         net_value=var_net_value,
                         average_price_nsr=var_average_price_nsr 
          WHERE dealer_name=var_loop1.dealer;

      ELSE
          EXECUTE 'SELECT SUM(saleqtypermt) FROM customernotorderdb_temp WHERE dealer LIKE ''%'||dealerName||'%'' AND month IN (to_char( now() - interval ''3 month'', ''YYYYMM''),to_char( now() - interval ''4 month'', ''YYYYMM''),to_char( now() - interval ''5 month'', ''YYYYMM''),to_char( now() - interval ''6 month'', ''YYYYMM''),to_char( now() - interval ''7 month'', ''YYYYMM''),to_char( now() -interval ''8 month'', ''YYYYMM''),to_char( now() - interval ''9 month'', ''YYYYMM''),to_char( now() - interval ''10 month'', ''YYYYMM''),to_char( now() - interval ''11 month'', ''YYYYMM''),to_char( now() - interval ''12 month'', ''YYYYMM''),to_char( now() - interval ''13 month'', ''YYYYMM''),to_char( now() - interval ''14 month'', ''YYYYMM''))' INTO var_sum_of_quantity;
          EXECUTE 'SELECT SUM(basic_value-rate_diff) FROM customernotorderdb_temp WHERE dealer LIKE ''%'||dealerName||'%'' AND month IN (to_char( now() - interval ''3 month'', ''YYYYMM''),to_char( now() - interval ''4 month'', ''YYYYMM''),to_char( now() - interval ''5 month'', ''YYYYMM''),to_char( now() - interval ''6 month'', ''YYYYMM''),to_char( now() - interval ''7 month'', ''YYYYMM''),to_char( now() -interval ''8 month'', ''YYYYMM''),to_char( now() - interval ''9 month'', ''YYYYMM''),to_char( now() - interval ''10 month'', ''YYYYMM''),to_char( now() - interval ''11 month'', ''YYYYMM''),to_char( now() - interval ''12 month'', ''YYYYMM''),to_char( now() - interval ''13 month'', ''YYYYMM''),to_char( now() - interval ''14 month'', ''YYYYMM''))' INTO var_net_value;
          EXECUTE 'SELECT SUM(avgpricensr) FROM customernotorderdb_temp WHERE dealer LIKE ''%'||dealerName||'%'' AND month IN (to_char( now() - interval ''3 month'', ''YYYYMM''),to_char( now() - interval ''4 month'', ''YYYYMM''),to_char( now() - interval ''5 month'', ''YYYYMM''),to_char( now() - interval ''6 month'', ''YYYYMM''),to_char( now() - interval ''7 month'', ''YYYYMM''),to_char( now() -interval ''8 month'', ''YYYYMM''),to_char( now() - interval ''9 month'', ''YYYYMM''),to_char( now() - interval ''10 month'', ''YYYYMM''),to_char( now() - interval ''11 month'', ''YYYYMM''),to_char( now() - interval ''12 month'', ''YYYYMM''),to_char( now() - interval ''13 month'', ''YYYYMM''),to_char( now() - interval ''14 month'', ''YYYYMM''))' INTO var_average_price_nsr;
          --RAISE NOTICE 'B [ %  % ]', dealername,var_net_value;
          UPDATE LOM SET sum_of_quantity=var_sum_of_quantity,net_value=var_net_value,average_price_nsr=var_average_price_nsr WHERE dealer_name=var_loop1.dealer;
      END IF;         
 END LOOP;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE 

首先,看起来您将月份存储为字符串,并手动使用字符串进行日期比较。那会减慢速度的。你能用Postgres日期类型或整数来代替吗

对于其他方面,如果不了解数据库布局和统计信息,我就无法确定,但以下是优化查询的基本方法:

  • 使用psql或其他方法打开新连接
  • 设置enable_seqscan=off
    ,这将仅为此会话禁用查询计划器中的seq scan(除非完全必要)
  • 在查询之前运行
    EXPLAIN
    ,查看哪些查询被强制扫描大型表。如果您看到任何
    SEQ SCAN
    s,请添加索引

  • “解释分析选择lastonemonth();st=0.00..0.26行=1宽度=0)(实际时间=16959.720..16959.721行=1循环=1)”“总运行时间:16959.734毫秒”非常感谢,现在代码的效率是解释分析选择lastonemonth();“结果(成本=0.00..0.26行=1宽度=0)(实际时间=2783.845..2783.845行=1循环=1)”“总运行时间:2783.859毫秒”不错。你改变了什么?您没有发布解释生成的查询计划。1。删除通配符%2。添加了显式索引。3.在if块下,将三个execute语句合并为一个4。修改了postgresql.conf文件设置5。从函数6中删除了“CREATE”和“DROP”语句。删除了减速部分中的一个变量,但没有在表格上运行分析。较新的drop temp表,将其截断。然后你可以使用静态SQL,你不需要函数;您不需要循环,也不需要plpgsql。该函数有效地将
    插入LOM(…)选择经销商名称、金额(xxx0)。。。根据上述建议,从CustomerMotorDerDB_temp GROUP BY dealer_name
    (加上一些其他聚合和选择)中选择以下代码:
    其中dealer喜欢“%”| | dealerName | |“%”
    为什么在这里使用通配符?你在同一张桌子上找到了dealername!