改善PL / pgSQL中的聚合功能

时间:2019-04-23 11:49:31

标签: sql postgresql plpgsql

我尝试创建一个聚合函数,该函数在列中找到最小值,然后添加拉普拉斯噪声。 我正在使用Postregres PL / pgSQL语言。

汇总工作正常,但是我想知道是否有任何方法可以改善我编写的代码

/*
 * PLpgSQL function which behaves to aggregate the MIN(col) function then adds the laplacian noise.
 * For the sensivity (which is the upper bound of the query), We use the  halfed maximum value of the column called.
 * Passing the array which contains the entire column values, that will be compared, to establish which one is the minimum.
 * Then we compute Laplacian distribution (sensivity/epsilon). This given value is added to the minimum Value that will disturb
 * the final result
 */
CREATE OR REPLACE FUNCTION addLaplacianNoiseMin (real[]) RETURNS real AS $$
DECLARE 
   i real;
   minVal real; --minimum value which is found in the column and then disturbed
   laplaceNoise real; --laplacian distribution which is computed finding the halfed maximum value, divided by an arbitrary epsilon (small value)
   epsilon real := 1.2;
   sensivity real; --our computed upper bound
   maxVal real;
BEGIN
   minVal := $1[1];
   maxVal := $1[1];
   IF ARRAY_LENGTH($1,1) > 0 THEN --Checking whether the array is empty or not
      <<confrontoMinimo>>
      FOREACH i IN ARRAY $1 LOOP --Looping through the entire array, passed as parameter
         IF minVal >= i THEN
            minVal := i;
         ELSE
            maxVal := i;
         END IF;
      END LOOP confrontoMinimo;
   ELSE
      RAISE NOTICE 'Invalid parameter % passed to the aggregate function',$1;
      --Raising exception if the parameter passed as argument points to null.
      RAISE EXCEPTION 'Cannot find MIN value. Parameter % is null', $1
         USING HINT = 'You cannot pass a null array! Check the passed parameter';
   END IF;

   sensivity := maxVal/2;
   laplaceNoise := sensivity/(epsilon);

   RAISE NOTICE 'minVal: %, maxVal: %, sensivity: %, laplaceNoise: %', minVal, maxVal, sensivity,laplaceNoise;

   minVal := laplaceNoise + minVal;
   RETURN minVal;
END;
$$ LANGUAGE plpgsql;

CREATE AGGREGATE searchMinValueArray (real)
(
   sfunc = array_append,
   stype = real[],
   finalfunc = addLaplacianNoiseMin,
   initCond = '{}'
);

1 个答案:

答案 0 :(得分:1)

是的,您可以通过不使用数组作为聚合的状态,而是使用类似以下的复合类型来改善此问题:

CREATE TYPE aggstate AS (minval real, maxval real);

然后,您可以在SFUNC中从循环执行操作,而不必在内存中保留可能会变得非常大的数组。这样FINALFUNC就会变得非常简单。