performance postgresql strict sql-function

performance - La función se ejecuta más rápido sin el modificador STRICT?



postgresql sql-function (1)

Me pregunto acerca de una caída en el rendimiento cuando una simple función de SQL se declara STRICT . Me encontré con este fenómeno al responder una pregunta aquí .

Para demostrar el efecto creo dos variantes de una función SQL simple que ordena dos elementos de una matriz en orden ascendente.

Configuración de prueba

-- temporary table with 10000 random pairs of integer CREATE TEMP TABLE arr (i int[]); INSERT INTO arr SELECT ARRAY[(random() * 1000)::int, (random() * 1000)::int] FROM generate_series(1,10000);

Función con el modificador STRICT :

CREATE OR REPLACE FUNCTION f_sort_array1(int[]) RETURNS int[] AS $$ SELECT CASE WHEN $1[1] > $1[2] THEN ARRAY[$1[2], $1[1]] ELSE $1 END; $$ LANGUAGE sql STRICT IMMUTABLE;

Función sin el modificador STRICT (por lo demás idéntico):

CREATE OR REPLACE FUNCTION f_sort_array2(int[]) RETURNS int[] AS $$ SELECT CASE WHEN $1[1] > $1[2] THEN ARRAY[$1[2], $1[1]] ELSE $1 END; $$ LANGUAGE sql IMMUTABLE;

Resultados

Ejecuté cada una alrededor de 20 veces y obtuve el mejor resultado de EXPLAIN ANALYZE .

SELECT f_sort_array1(i) FROM arr; -- Total runtime: 103 ms SELECT f_sort_array2(i) FROM arr; -- Total runtime: 43 ms (!!!)

Estos son los resultados de un servidor v9.0.5 en Debian Squeeze. Resultados similares en v8.4. No hice la prueba en 9.1, no tengo clúster a mi disposición en este momento. (¿Alguien puede proporcionar resultados adicionales para v9.1?)

Editar: en una prueba con 10000 valores NULL, ambas funciones realizan lo mismo en el mismo entorno de prueba: ~ 37 ms.

Investigué un poco y encontré un interesante juego. Declarar una función SQL STRICT deshabilita la función en línea en la mayoría de los casos. Más sobre eso en la Revista en línea de PostgreSQL o en la lista de distribución de pgsql-performance o en la Wiki de Postgres .

Pero no estoy muy seguro de cómo esta podría ser la explicación. ¿Cómo no puede la creación de la función causar la caída del rendimiento en este escenario simple? Sin índice, sin lectura de disco, sin clasificación. ¿Tal vez una sobrecarga de la llamada de función repetida que se simplifica al subrayar la función? ¿Puedes explicarlo? ¿O me estoy perdiendo algo?

Volver a probar con Postgres 9.1

La misma prueba en el mismo hardware con PostgreSQL 9.1 y encontró diferencias aún mayores:

SELECT f_sort_array1(i) FROM arr; -- Total runtime: 107 ms SELECT f_sort_array2(i) FROM arr; -- Total runtime: 27 ms (!!!)

Volver a probar con Postgres 9.6

La misma prueba en hardware diferente con PostgreSQL 9.6. La brecha es aún mayor, sin embargo:

SELECT f_sort_array1(i) FROM arr; -- Total runtime: 60 ms SELECT f_sort_array2(i) FROM arr; -- Total runtime: 10 ms (!!!)


¿Tal vez una sobrecarga de la llamada de función repetida que se simplifica al subrayar la función?

Eso es lo que supongo. Tienes una expresión muy simple allí. Una llamada a la función real implica presumiblemente la configuración de la pila, el paso de parámetros, etc.

La prueba a continuación da tiempos de ejecución de 5 ms para inline y 50 ms para strict.

BEGIN; CREATE SCHEMA f; SET search_path = f; CREATE FUNCTION f1(int) RETURNS int AS $$SELECT 1$$ LANGUAGE SQL; CREATE FUNCTION f2(int) RETURNS int AS $$SELECT 1$$ LANGUAGE SQL STRICT; /timing on SELECT sum(f1(i)) FROM generate_series(1,10000) i; SELECT sum(f2(i)) FROM generate_series(1,10000) i; /timing off ROLLBACK;