Cuando se usa GETDATE () en muchos lugares, ¿es mejor usar una variable?


Por mejor, quiero decir, ¿mejora el rendimiento en una cantidad no marginal?

Es decir, cada vez que llamo a GETDATE(), ¿qué cantidad de trabajo hace el servidor para devolver ese valor?

Si estoy usando GETDATE() en muchos lugares de un procedimiento almacenado, ¿debería crear una variable para almacenar la fecha de la transacción?

declare @transDate datetime = GETDATE()

Los datos de benchmarking serían fantásticos.

EDIT Quiero aclarar: Estoy interesado principalmente en el diferencias de rendimiento entre estas dos posibilidades, y si es o no significativa.

Author: Shmiddty, 2012-08-22

5 answers

[NOTA: Si vas a votar en contra de esta respuesta, por favor deja un comentario explicando por qué. Ya ha sido rechazada muchas veces, y finalmente ypercube (gracias) explicó al menos una razón. No puedo eliminar la respuesta porque es aceptada, por lo que también podría ayudar a mejorarla.]

De acuerdo con este intercambio en Microsoft, GETDATE() pasó de ser constante dentro de una consulta a no determinista en SQL Server 2005. En retrospectiva, no creo que sea preciso. Creo que era completamente no determinista antes de SQL Server 2005 y luego hackeado en algo llamado "constante de tiempo de ejecución no determinista "desde SQL Server 2005". La frase posterior realmente parece significar "constante dentro de una consulta".

(Y GETDATE() se define como inequívoca y orgullosamente no determinista, sin calificadores.)

Por desgracia, en SQL Server, no determinista no significa que una función se evalúa para cada fila. SQL Server realmente lo hace hacer esto innecesariamente complicado y ambiguo con muy poca documentación sobre el tema.

En la práctica, la llamada a la función se evalúa cuando la consulta se está ejecutando en lugar de una vez cuando la consulta se compila y su valor cambia cada vez que se llama. En la práctica, GETDATE() solo se evalúa una vez para cada expresión donde se usa at en tiempo de ejecución en lugar de tiempo de compilación. Sin embargo, Microsoft pone rand() y getdate() en una categoría especial, llamada funciones constantes de tiempo de ejecución no deterministas. Por el contrario, Postgres no salta a través de tales aros, solo llama a las funciones que tienen un valor constante cuando se ejecuta como "estable".

A pesar del comentario de Martin Smith, la documentación de SQL Server simplemente no es explícita en este asunto {GETDATE() se describe como "constante de tiempo de ejecución no determinista" y "no determinista", pero ese término no se explica realmente. El único lugar en el que he encontrado el término , por ejemplo, el las líneas de la documentación dicen no usar funciones no deterministas en subconsultas. Eso sería un consejo tonto para "constante de tiempo de ejecución no determinista".

Sugeriría usar una variable con una constante incluso dentro de una consulta, para que tenga un valor consistente. Esto también deja la intención bastante clara: Desea un solo valor dentro de la consulta. Dentro de una sola consulta, puedes hacer algo como:

select . . . 
from (select getdate() as now) params cross join
     . . . 

En realidad, esta es una sugerencia de que debería evaluar solo una vez en la consulta, pero puede haber excepciones. La confusión surge porque getdate() devuelve el mismo valor en todas las filas diferentes but pero puede devolver valores diferentes en columnas diferentes. Cada expresión con getdate() se evalúa de forma independiente. Esto es obvio si ejecuta:

select rand(), rand()
from (values (1), (2), (3)) v(x);

Dentro de un procedimiento almacenado, le gustaría tener un solo valor en una variable. ¿Qué sucede si el procedimiento almacenado se ejecuta a medida que pasa la medianoche y la fecha cambia? ¿Qué impacto tiene eso en la resultados?

En cuanto al rendimiento, mi conjetura es que la búsqueda de fecha/hora es mínima y para una consulta se produce una vez por expresión cuando la consulta comienza a ejecutarse. Esto no debería ser realmente un problema de rendimiento, sino más bien un problema de coherencia de código.

 19
Author: Gordon Linoff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-25 16:19:54

Mi sugerencia sería usar una variable principalmente porque si tiene un proceso de larga duración, el valor GetDate() podría ser diferente entre llamadas.

A menos que solo esté utilizando la parte Date de GetDate(), entonces estará seguro de que siempre está utilizando el mismo valor.

 17
Author: Taryn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-22 17:20:12

Una razón para usar una variable con getdate() o funciones como suser_sname() es una gran diferencia de rendimiento si está insertando filas, o si está haciendo un GRUPO POR. Notará esto si inserta una gran cantidad de filas.

Yo mismo sufrí esto migrando 300 GB de datos a varias tablas.

 1
Author: MarianoC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-30 11:56:52

Estaba probando en un par de procedimientos almacenados usando la función GETDATE () como una variable dentro de un SP y estaba teniendo un aumento en las lecturas de IO y el tiempo de ejecución debido al hecho de que query optimizer no sabe cuál es el valor para operar read this Ejecución de procedimientos almacenados con Parámetros, variables y Literales, dicho esto, puede usar la función GETDATE() en cada parte del SP como @Gordon Linoff mencionó que su valor no cambia durante la ejecución o en para evitar / eliminar la idea de que el valor podría cambiar, creé un parámetro de esta manera:

CREATE PROC TestGetdate
(
@CurrentDate DATETIME = NULL
)
AS
SET CurrentDate  = GETDATE()

..... y luego use los parámetros como mejor le parezca, verá buenos resultados

Cualquier comentario o sugerencia son bienvenidos.

 1
Author: jthalliens,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-25 15:30:05

He utilizado

WHERE ActualDateShipped+30 > dbo.Today()

En combinación con la función siguiente. Trajo mi tiempo de consulta de 13 segundos a 2 segundos. Ninguna respuesta previa en este post ayudó a este problema en SQL 2008 / R2.

CREATE FUNCTION [dbo].[Today]()

    RETURNS date
    AS
    BEGIN

        DECLARE @today date = getdate()

        RETURN @today
    End
 0
Author: pghcpa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-09 01:47:59