sql >> Base de Datos >  >> RDS >> PostgreSQL

Función SQL muy lenta en comparación con la consulta sin contenedor de función

user

Mientras reescribía su función, me di cuenta de que agregó alias de columna aquí:

SELECT 
  ...
  auth_user.email AS user, 
  customers.name AS customer,

.. que no haría nada para empezar, ya que esos alias son invisibles fuera de la función y no están referenciados dentro de la función. Así serían ignorados. Para fines de documentación, mejor use un comentario.

Pero también hace que su consulta sea inválida , porque user es una palabra completamente reservada y no se puede usar como alias de columna a menos que esté entre comillas dobles.

Curiosamente, en mis pruebas, la función parece funcionar con el alias no válido. Probablemente porque es ignorado (?). Pero no estoy seguro de que esto no pueda tener efectos secundarios.

Tu función reescrita (de lo contrario, equivalente):

CREATE OR REPLACE FUNCTION get_web_events_by_userid(int)
  RETURNS TABLE(
     id int
   , time_stamp timestamptz
   , description text
   , origin text
   , userlogin text
   , customer text
   , client_ip inet
  ) AS
$func$
SELECT w.id
     , w.time_stamp
     , w.description 
     , w.origin  
     , u.email     -- AS user   -- make this a comment!
     , c.name      -- AS customer
     , w.client_ip
FROM   public.auth_user       u
JOIN   public.auth_web_events w ON w.user_id_fk = u.id
JOIN   public.customers       c ON c.id = u.customer_id_fk 
WHERE  u.id = $1   -- reverted the logic here
ORDER  BY w.id DESC
$func$ LANGUAGE sql STABLE;

Obviamente, el STABLE palabra clave cambió el resultado. Volatilidad de la función no debería ser un problema en la situación de prueba que describe. La configuración normalmente no beneficia a una sola llamada de función aislada. Lea los detalles en el manual. Además, estándar EXPLAIN no muestra planes de consulta de lo que sucede dentro funciones Podría emplear el módulo adicional explicación automática por eso:

  • Plan de consulta de Postgres de una invocación de UDF escrita en pgpsql

Tienes una distribución de datos muy extraña :

La tabla auth_web_events tiene 100000000 registros, auth_user->2 registros, clientes-> 1 registro

Como no definió lo contrario, la función asume una estimación de 1000 filas ser devuelto. Pero su función en realidad solo devuelve 2 filas . Si todas sus llamadas solo devuelven (cerca de) 2 filas, simplemente declare eso con un ROWS 2 agregado . Podría cambiar el plan de consulta para el VOLATILE variante también (incluso si STABLE es la elección correcta de todos modos aquí).