查询当前表时,Postgresql插入触发器变慢

时间:2015-10-13 01:14:28

标签: sql database postgresql plpgsql

当在表格中插入批号时,我们计算基数存在的次数,并根据该计数在新数字的末尾添加 - ##。

我已经删除了大多数逻辑(我们也检查了其他内容)。我也知道这里的逻辑缺陷会跳过-1。

-- Function: stone._lsuniqueid()

-- DROP FUNCTION stone._lsuniqueid();

CREATE OR REPLACE FUNCTION stone._lsuniqueid()
  RETURNS trigger AS
$BODY$
DECLARE
 _count INTEGER;

BEGIN
  -- Obtain the number of occurences of this new ls_number
  SELECT COUNT(ls_number) into _count
  FROM ls
  WHERE ls_number LIKE CAST(NEW.ls_number || '%' AS text);

  -- Allow new ls_numbers to be entered as is, otherwise add "-#{count + 1}"
  -- to the end of the ls_number
  if _count > 0 THEN
    NEW.ls_number = NEW.ls_number || '-' || CAST(_count + 1 AS text);
  END IF;      

  RETURN NEW;
END
$BODY$

INSERT INTO ls VALUES (NEXTVAL('ls_ls_id_seq'),7285,UPPER('20151012'));
--> Query returned successfully: one row affected, 391 ms execution time.

计数查询速度很快

SELECT COUNT(ls_number)
FROM ls
WHERE ls_number LIKE CAST('20151012' || '%' AS text);
--> 19ms

为了进行比较,我尝试了类似的触发器,但是针对具有相同行数和相似查询时间的不同表运行计数。

SELECT COUNT(lsdetail_id)
FROM lsdetail
WHERE lsdetail_id > 2433308
--> 20ms

运行相同的插入,对不同的表运行计数会使结果返回20倍。

INSERT INTO ls VALUES (NEXTVAL('ls_ls_id_seq'),7285,UPPER('20151012'));
 --> Query returned successfully: one row affected, 20 ms execution time.

ls表有大约250万行

我尝试了几个不同的东西,问题似乎是从我插入的同一个表中选择。

我想知道为什么会发生这种情况,但我也愿意更好地创建“子批次”数字。

谢谢!

1 个答案:

答案 0 :(得分:1)

在这里找到答案: http://www.postgresql.org/message-id/27705.1150381444@sss.pgh.pa.us

Re:如何分析功能性能

  “明道加斯”写道:

     
    

是否有可能以某种方式分析功能性能?例如。我们正在使用函数cleanup(),这显然需要花费太多时间来执行,但是我在试图弄清楚什么会减慢速度方面遇到了问题。

         

当我逐步解释分析功能线时,它表现出相当可接受的性能。

  

-

  

你确定你是“解释分析”相同的查询功能   真的在干嘛? 你必须考虑plpgsql是什么的事实   发布是参数化查询,有时限制了   策划者选择好计划的能力。例如,如果你有

declare x int;
begin
    ...
    for r in select * from foo where key = x loop ...
  

然后真正计划和执行的是“select * from foo   其中key = $ 1“---每个plpgsql变量都被一个参数替换   符号“$ n”。您可以使用准备好的方法为EXPLAIN目的建模   语句:

prepare p1(int) as select * from foo where key = $1;
explain analyze execute p1(42);
  

如果您在参数化时发现特定查询确实很糟糕,   您可以通过使用EXECUTE强制查询来解决此问题   使用文字常量而不是参数重新计划每次使用:

然后我调查了这个: http://www.postgresql.org/docs/9.1/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN

  

<强> 39.5.4。执行动态命令

     

通常,您需要在PL / pgSQL函数中生成动态命令,即每次执行时都会涉及不同表或不同数据类型的命令。 PL / pgSQL正常尝试缓存命令计划(如第39.10.2节所述)在这种情况下不起作用。为了处理这类问题,提供了EXECUTE语句:

EXECUTE 'SELECT count(*) FROM mytable WHERE inserted_by = $1 AND inserted <= $2'
INTO c
USING checked_user, checked_date;

-

所以最后这是一个更新计数选择的问题:

 EXECUTE 'SELECT COALESCE(COUNT(ls_number), 0) FROM ls WHERE ls_number LIKE $1 || ''%'';'
 INTO _count
 USING NEW.ls_number;