Estoy tratando de comprender el impacto en el rendimiento de seleccionar datos de una vista, donde una de las columnas de una vista es función de otros datos en la tabla original.
¿El cálculo se realiza independientemente de si la columna calculada está o no en la lista de columnas seleccionadas?
Si tuviera una mesa y la vista así se declarara
CREATE TABLE price_data (
ticker text, -- Ticker of the stock
ddate date, -- Date for this price
price float8, -- Closing price on this date
factor float8 -- Factor to convert this price to USD
);
CREATE VIEW prices AS
SELECT ticker,
ddate,
price,
factor,
price * factor as price_usd
FROM price_data
¿Se realizaría esa multiplicación en una consulta como la siguiente?
select ticker, ddate, price, factor from prices
¿Hay alguna referencia que garantice de una forma u otra? Estaba leyendo la documentación sobre el sistema de reglas en Postgres, pero creo que la respuesta realmente recae en el optimizador, ya que nada en la documentación del sistema de reglas indicaba que no se seleccionaría.
Sospecho que en el caso anterior no se realiza el cálculo. Cambié la vista para usar la división en lugar de la multiplicación, e inserté un 0
for factor
en price_data
. La consulta anterior no falló, pero si la consulta se modificó para seleccionar la columna calculada, la consulta modificada falló.
¿Hay alguna manera de entender qué cálculos se están haciendo cuando select
se lleva a cabo una? Supongo que estoy buscando algo así, EXPLAIN
pero que también me informa sobre los cálculos que se están realizando.
fuente
Respuestas:
Como dijo @Laurenz, su análisis es correcto: el optimizador evitará evaluar expresiones de columna que no afecten el resultado de la consulta (y su intento de forzar un error de división por cero es prueba de ello).
Esto depende de las columnas que esté seleccionando, pero también depende de la categoría de volatilidad de las expresiones de columna. El optimizador es libre de omitir
immutable
ystable
llamar a las funciones si su salida nunca se usa, ya que no pueden afectar el resultado, pero lasvolatile
funciones pueden tener efectos secundarios, por lo que no se optimizan tan fácilmente.Por ejemplo:
Si solo
volatile
se selecciona la columna:... entonces, como puede ver,
stable_function()
está ausente de laexplain
salida, y la falta de unNOTICE
confirma que esta llamada ha sido optimizada.Sin embargo, si
stable
se selecciona la columna en su lugar:... luego vemos que ambas expresiones de columna aparecen en el plan, y la
NOTICE
s muestra que ambas funciones se han ejecutado.No parece haber ninguna mención explícita de este comportamiento en los documentos, por lo que no hay garantías firmes de si se evaluará o no una expresión, y no debe confiar en los efectos secundarios que puedan tener sus llamadas de función.
Pero si su única preocupación es el rendimiento, a continuación, todo el tiempo que marca sus funciones
stable
oimmutable
en su caso, puede estar razonablemente seguro (especialmente en los casos simples como este) que no van a ser evaluados si no son necesarios.(Y mientras esté allí auditando sus declaraciones de volatilidad, es posible que también desee establecer las banderas de seguridad paralelas ).
fuente
Su sospecha es correcta, y el cálculo no debe realizarse si no se utiliza la columna.
Para confirmar eso, mire el resultado de
EXPLAIN (VERBOSE)
la consulta, que le mostrará las columnas devueltas.fuente