sql-servert-sqlquery-optimizationdatetime-conversion

DECLARE vs. Direct DateTime Conversion Performance Comparison


I am trying to understand if there is any performance difference between declaring a datetime conversion variable and using it versus directly converting the date in a SQL Server query.

Here are two example queries: Query 1: Do DateTime Conversion Every Time

SELECT * 
FROM TestMessages
WHERE CreatedDate > CONVERT(DATETIME, '2023-12-18 00:00:00', 120);

Query 2: DECLARE DateTime Conversion Variable

DECLARE @yourDateString NVARCHAR(19) = '2023-12-18 00:00:00';
DECLARE @ConvertedDate DATETIME = CONVERT(DATETIME, @yourDateString, 120);

SELECT * 
FROM TestMessages
WHERE CreatedDate > @ConvertedDate;

Is there any noticeable performance difference between these two queries? How does declaring a variable for datetime conversion impact the execution time of the query? Additionally, what SQL Server tools or techniques can be used to analyze and measure this performance difference?

I've been experimenting with two different approaches in my SQL Server queries for datetime conversion. In one query, I directly convert the datetime value, and in another, I use DECLARE to create a conversion variable. I expected to observe a potential difference in performance between these two methods, but the results were not as clear as I anticipated. I would like insights on the performance implications of these approaches and any recommended practices for optimizing datetime conversions in SQL Server queries.

When I examine the Execution Plans, there seems to be a difference in the plan, but it's unclear whether it's significant. Additionally, when I look at the statistics, it shows '88 rows affected' for the first query, while it shows '1 rows affected' for the other. The cost is shown as 100% and 0.000s for the first query with '88 of 88 (0%) rows affected.' However, for the second query, the cost is also 100%, but '0.000s 0 of 855 (0%)' rows are affected. Is this discrepancy significant?


Solution

  • With

    WHERE CreatedDate > CONVERT(DATETIME, '2023-12-18 00:00:00', 120);
    

    the cardinality estimates will likely be more accurate.

    This will improve the chances of getting an appropriate plan and, potentially, memory grant.

    For the CreatedDate > @ConvertedDate predicate it will just assume 30% will match unless you also use OPTION (RECOMPILE) to allow it to sniff the variable's value.

    For CreatedDate > CONVERT(DATETIME, '2023-12-18 00:00:00', 120) it can look that value up in the histogram and get estimates from there.

    CREATE TABLE TestMessages
                 (
                              CreatedDate DATETIME INDEX ix_CreatedDate,
                              Filler      CHAR(1000) NULL
                 )
    INSERT TestMessages
           (CreatedDate)
    SELECT DATEADD(HOUR, value, '1990-01-01 00:00:00')
    FROM   generate_series(1, 300000) 
    

    WHERE CreatedDate > CONVERT(DATETIME, '2023-12-18 00:00:00', 120);

    enter image description here

    WHERE CreatedDate > @ConvertedDate

    enter image description here

    WHERE CreatedDate > @ConvertedDate OPTION (RECOMPILE);

    enter image description here