viernes, 12 de agosto de 2022

CONVERT vs FORMAT

Hace poco estaba revisando el código T-SQL de un cliente y le comentaba que resulta un poco complicado el deducir qué formato de fecha se estará devolviendo al usuario cuando utiliza la función CONVERT, por ejemplo:

CONVERT(VARCHAR(10), GETDATE(), 23)

De forma inmediata recordé que existe la función FORMAT que hace mucho más legible el código. Si tomamos como base la expresión que anteriormente mencioné, su versión en FORMAT sería:

FORMAT(GETDATE(), 'yyyy-MM-dd')

Es evidente que es muchísimo más legible, y de manera inevitable me brincó la pregunta, ¿cuál de las dos opciones es mejor? Para responder a esta pregunta he preparado un ejercicio bastante sencillo, pero que nos ayudará a comprender la enorme diferencia.

Comencemos por crear nuestra tabla y llenarla con 500 mil registros:

CREATE TABLE TestFormat(
    Fecha DATETIME2(0)
)
GO
SET NOCOUNT ON
INSERT INTO TestFormat (Fecha)
VALUES (DATEADD(MINUTE, ABS(CHECKSUM(NEWID())) % 15768000, '1992-01-01 00:00:00'))
GO 500000

Vamos a comenzar por obtener las fechas en el formato yyyy-MM-dd con CONVERT y tomaremos los tiempos de ejecución.   Para tener una mejor perspectiva, ejecutaremos el ejercicio tres veces.

SET STATISTICS TIME ON
SELECT CONVERT(VARCHAR(10), Fecha, 23)
FROM TestFormat

Y después vamos a obtener el mismo formato pero utilizando la función FORMAT.   Al igual que en el ejercicio anterior, vamos a ejecutarlo unas tres veces para tener más datos de comparación.

SET STATISTICS TIME ON
SELECT FORMAT(Fecha, 'yyyy-MM-dd')
FROM TestFormat

La diferencia en las métricas es muy importante:



Ahora vamos a hacer el mismo ejercicio pero obteniendo la fecha y hora en formato yyyy-MM-dd HH:mm:ss.    Con CONVERT quedaría de la siguiente manera:

SET STATISTICS TIME ON
SELECT CONCAT(CONVERT(VARCHAR(10), Fecha, 23), ' ', CONVERT(VARCHAR(10), Fecha, 24))
FROM TestFormat

Y con FORMAT quedaría de la siguiente manera:

SET STATISTICS TIME ON
SELECT FORMAT(Fecha, 'yyyy-MM-dd HH:mm:ss')
FROM TestFormat

En la imagen siguiente podremos notar que el tiempo de CPU de CONVERT se incrementa y que el tiempo de CPU de FORMAT se mantiene muy parecido:


Pero ni con el incremento de tiempo de CPU en el formato yyyy-MM-dd HH:mm:ss nos acercamos al tiempo de CPU de FORMAT, porque FORMAT se ejecuta casi 10 veces más lento cuando incluimos la hora y casi 20 veces más lento cuando únicamente tenemos la fecha.

¿Qué factores debemos tomar en cuenta para entender estos datos?
  1. FORMAT está implementada a través de un ensamblado de .NET, es decir que se está ejecutando de forma externa.
  2. CONVERT se va al doble cuando hay que incluir la hora porque podemos ver que hay dos ejecuciones de la función, una para obtener la fecha y otra para obtener la hora.
La recomendación que te puedo hacer, es que en el código incluyan un comentario donde se indique el formato de fecha que se estará obteniendo, por ejemplo:

--yyyy-MM-dd HH:mm:ss
SELECT CONCAT(CONVERT(VARCHAR(10), Fecha, 23), ' ', CONVERT(VARCHAR(10), Fecha, 24))
FROM TestFormat

De esta forma será mucho más sencillo el darle mantenimiento al código porque podremos ver de forma inmediata lo que se está obteniendo.   La programación considerada no es una buena práctica, es una obligación.

Espero te haya resultado útil esta entrada.