Dicen por ahí que rectificar es de sabios... así que aquí va mi momento de sabiduría del día: en la entrada anterior compartía con vosotros algunas de las sorpresas que me he ido encontrado en la RC0 de SQL Server 2008, y también os decía que debido al poquito tiempo que me queda libre estas semanas, seguramente no podría postear mucho más sobre el producto a corto plazo. Pues bien, heme aquí, humillándome y escribiendo una entrada sobre una nueva característica de SQL Server 2008 :)
La verdad es que no he podido evitarlo, realmente me parece que este va a ser otro de esos detalles 'pequeños' pero que pueden marcar una diferencia importante; en este caso a nivel de rendimiento. Vamos para allá...
Optimización para consultas Ad Hoc
El otro día, mientras leía los Books Online (la documentación del producto) de SQL Server 2008 RC0 me tropecé, como quien no quiere la cosa, con la característica que os voy a comentar ahora. Nada mas leerla me vino a la mente el artículo sobre el ciclo de vida de las consultas y el pequeño y bonito debate que se abrió en los comentarios, y me parece que complementa muy bien lo comentado en su momento en aquella entrada, por lo que no puedo resistirme a comentarla brevemente por aquí.
Haciendo un poco de memoria...
¿Recordáis el problema de las consultas ad hoc en SQL Server? Comentábamos que éstas, al contrario que los procedimientos almacenados y que las consultas parametrizadas, no tenían en cuenta los parámetros a la hora de almacenar y reutilizar su plan de ejecución (para una explicación detallada, echádle un vistazo al post antes referido).
Vamos a ver un ejemplo sobre la base de datos AdventureWorks:
USE AdventureWorks
GO
-- Limpiamos la Cache de planes de ejecucion
DBCC FREEPROCCACHE
GO
-- Ejecutamos esta consulta 5 veces
SELECT *
FROM Sales.SalesOrderDetail
WHERE UnitPrice = 5.70
GO
-- Ejecutamos esta consulta 5 veces
SELECT *
FROM Sales.SalesOrderDetail
WHERE UnitPrice = 21.98
GO
-- Miramos nuestros planes de ejecucion en la cache de planes
SELECT
usecounts,
size_in_bytes,
cacheobjtype,
objtype
FROM sys.dm_exec_cached_plans
WHERE objtype = 'Adhoc'
Como podéis ver, la demo se compone de los siguientes pasos:
- Limpiamos la Caché de Procedimientos Almacenados:
Inicialmente limpiamos la caché de planes de ejecución mediante el comando DBCC FREEPROCCACHE, con el único objetivo de facilitarnos luego la búsqueda de los planes que se han generado por las consultas de la demo. Por razones evidentes, no debemos ejecutar este comando en un servidor de producción.
- Ejecutamos una consulta con dos parámetros diferentes:
A continuación lanzamos una consulta sobre AdventureWorks. Como podéis ver, lanzamos la misma consulta con dos parámetros, ejecutando 5 veces cada una de ella.
En un mundo ideal SQL Server sería lo suficientemente inteligente como para detectar que son la misma consulta pero con diferentes parámetros, y que su plan de ejecución no va a variar ya que es trivial. ¡¡Vamos a ver si es así!!
- Monitorizamos la Cache de planes de ejecución:
¿Vivimos en ese mundo ideal? ¿Cómo podemos comprobarlo? Lo primero que se me ha ocurrido es dar un par de palmadas al aire a ver si por arte de magia aparecía una cerveza fresquita aquí la lado, pero no ha funcionado. Mmmm.. me tomaré eso como un primer indicio de que no vivimos en un mundo ideal :(
El segundo indicio lo sacamos de la vista de administración dinámica sys.dm_exec_cached_plans, en la que podremos observar como, al contrario de lo que sucede con los procedimientos almacenados o las consultas parametrizadas, los planes de ejecución no se han reutilizado. Como se puede ver en la siguiente captura de pantalla, tenemos dos planes de ejecución con 5 ejecuciones cada uno.
Bien, hasta aquí nada nuevo bajo el sol, ya que se trata del comportamiento por defecto de SQL Server 2005 y SQL Server 2008. Sin embargo os prometí que os traería novedades, y aqui vienen...
Let's Get Rocked!! Optimize for Ad Hoc Workload
Los planes de ejecución consumen memoria... ¡y no poca! Como podemos ver en la captura de pantalla, en el caso los planes de ejecución del ejemplo anterior cada uno de los planes se lleva 24576Kb... ¡24 Kb, 3 páginazas por plan, nada más y nada menos! Y eso que son planes pequeñitos...
Esto puede plantear problemas en un escenario lamentablemente muy común; aplicaciones que lanzan consultas ad-hoc directamente contra nuestro servidor. A no ser que siempre se repitan las consultas con los mismos parámetros, cosa bastante improbable, el número de planes de ejecución en la caché crecerá vertiginosamente, dando lugar a problemas de presión de memoria, que a su vez obligará a sacar planes 'antiguos', que en ultima instancia (y para terminar con nuestra cadena de males) implicará que se tengan que recompilar con mucha mayor frecuencia los planes de ejecución, con el aumento de coste de CPU asociado.
En SQL Server 2008 aparece una nueva opción de configuración del servidor, llamada 'optimize for ad hoc workloads', que viene a mejorar el comportamiento del servidor en este tipo de escenarios. La idea principal es que, cuando se lance una consulta ad hoc no parametrizada contra el servidor, éste no almacene el plan de ejecución completo. En su lugar, almacenara un pequeño 'stub', muy liviano.
Este stub sirve para poder almacenar una entrada en la caché de planes de ejecución, de modo que el servidor sepa que esa consulta ya se ha ejecutado alguna vez en el sistema. Lo bueno de este mecanismo es que el stub ocupa muy poca memoria, lo malo es que el stub no es un plan de ejecución. Por tanto en su siguiente ejecución, hay que volver a compilar la consulta.
Como optimización adicional, siempre que una consulta se ejecuta por segunda vez, SQL Server supone que esta consulta va a ejecutarse más veces con el mismo parámetro, por lo que, de algún modo, promociona su plan de ejecución, y en lugar del stub almacena su plan compilado real.
Vamos a ver un pequeño ejemplo:
-- Habilitamos la opcion de 'optimize for ad hoc workloads'
sp_configure 'show advanced options',1
GO
sp_configure 'optimize for ad hoc workloads',1
RECONFIGURE
GO
-- Limpiamos la cache de planes de ejecucion
DBCC FREEPROCCACHE
GO
-- Vamos a hacer las demos sobre AdventureWorks
USE AdventureWorks
GO
-- Vamos a ver una consulta auto parametrizada
SELECT *
FROM Sales.SalesOrderDetail
WHERE UnitPrice = 5.70
GO
-- Vemos ahi el plan stub para la consulta
SELECT
usecounts,
size_in_bytes,
cacheobjtype,
objtype
FROM sys.dm_exec_cached_plans
WHERE objtype = 'Adhoc'
-- Vamos a ver como, para la consulta autoparametriazada, no se nos
-- crea un plan real: vemos como la consulta tiene como query_plan NULL
SELECT sql.text, p.query_plan
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(sql_handle) sql
CROSS APPLY sys.dm_exec_query_plan(plan_handle) p
WHERE text NOT LIKE '%sys_dm_exec%' AND text NOT LIKE '%msparam_0%'
ORDER BY qs.EXECUTION_COUNT DESC
GO
-- Deshabilitamos la opcion y volvemos a hacer las pruebas para ver
-- como no se generan los stubs
sp_configure 'show advanced options',1
GO
sp_configure 'optimize for ad hoc workloads',0
RECONFIGURE
GO
Como vemos en la demo, al mirar la caché de planes de ejecución nos encontramos con lo siguiente:
Es interesante resaltar que el stub del plan de ejecución ocupa solamente 336 bytes ( 1 página)... ¡una gran diferencia respecto al tamaño del plan de ejecución real!
Si además tratamos de ver cual es el plan de ejecución almacenado para esa entrada en la caché, veremos que nos devuelve NULL:
Como vemos, de cara a minimizar el consumo de CPU, de memoria (en la caché de procedimientos), incluso de un modo indirecto, de E/S (menos paginas, menos fallos de página), este mecanismo tiene un aspecto genial. Eso si, se recomienda emplearlo solo en los servidores que sean atacados por aplicaciones que hagan uso masivo de consultas ad-hoc, y no empleen tantos procedimientos almacenados ni queries parametrizadas.
Y ahora, los deberes ;)
Para terminar, os animo a que hagais pruebas en vuestros entornos o aplicaciones. Yo aún no he podido sacar tiempo para probarlo en condiciones y estudiar su rendimiento sobre ningún producto, pero en el momento que pueda hacer una comparativa os lo haré saber.
Si me gustaría que, si os animáis a hacer las pruebas, me comentéis por aquí vuestros resultados. Realmente ha sido una característica que me ha gustado mucho, y tengo interés por ver su adopción y resultados :)
Rock Tip:
Es la primera vez que escojo un tema de los noruegos Wig Wam para acompañar una entrada de mi blog; en este caso se trata de 'Out of Time', un medio tiempo bestial, de impecable factura, y que deja claro el buen nivel instrumental y compositivo de esta banda, a pesar de la continua autoparodia que hacen de si mismos sus componentes.
Lo cierto es que todos los chicos de Wig Wam (Glam, Teeny, Flash y Sporty) ya tenían bastante experiencia antes de decidirse a montar un grupo a medio camino entre el homenaje y la parodia de las grandes bandas de hard rock, AOR y glam de los años ochenta y primeros noventa, ¡y eso se nota! Sin embargo, no saltaron a la luz pública principalmente gracias a su participación en Eurovision en 2005, con su temazo 'In My Dreams'. A partir de entonces su vida se ha convertido en un no-parar de estadios con decenas de miles de asistentes, y de hoteles con cientos de grouppies dispuestas cada noche... o eso dicen ellos! :) Sea como sea, esta claro que son un grupo muy divertido y recomendable!
He escogido esta canción principalmente por mi falta de tiempo estos días, que me están poniendo difícil cumplir con mis compromisos personales y profesionales; aún así, mejor que sea por esto que no por lo que comenta la letra de la cancion (un reo condenado a muerte que se queda sin tiempo, muy en la onda del
'Halloweed be Thy Name' de mis
Iron Maiden del alma) ;)
¡Albricias! ¡Albricias! ¡Que toquen las campanas! ¡Que corra la voz!... bueno, he de admitir que llego un poco tarde para daros la noticia, pero con gran regocijo, júbilo y satisfacción me uno a Miguel y Jorge para dar la bienvenida a la última release de evaluación de SQL Server 2008: la RC0.
Como ya sabréis, cuando un producto pasa de CTP (Community Technological Preview) a RC (Release Candidate), podemos dar por supuesto que todas las características definitivas del producto están implementadas, y ya solo se procederá a los ajustes y corrección de bugs para asegurar la calidad del producto antes de salir al mercado y de que se ponga en producción. Pero lo importante para nosotros es que ya podemos jugar con la practica totalidad de sus características, ir formándonos en el producto, estudiando que características podemos aplicar a nuestros entornos, etc...
Durante estos días creo (y espero) que se escribirán cantidad de artículos relacionados con las grandes características, como el Policy-Based Management, Capture Data Change, el almacenamiento FILESTREAM, etc... Lamentablemente no creo que yo pueda aportar mucho a corto plazo; en este momento la verdad es que lo que menos tengo es tiempo para escribir una entrada en el blog acerca de ninguna de estas características, y menos de hacerlo de una manera suficientemente digna.
Sin embargo, desde el domingo he estado jugando un poco con esta versión RC0, y he encontrado muchos 'pequeños detalles' que me han encantado y que me gustaría compartir con vosotros, así que vamos allá...
Depuración Integrada
La primera sorpresa agradable es la posibilidad de depurar código TSQL directamente desde la interfaz del SQL Server Management Studio. Si bien es cierto que ya podíamos hacerlo desde el Visual Studio, no deja de ser práctico e interesante el poder realizar la depuración, consultar variables locales y watches, así como el call stack del SQL desde el entorno que utilizamos tan a menudo para desarrollar nuestros procedimientos y consultas.
No se a vosotros, pero a mi el mero hecho de ver en la barra de menú principal del SSMS un menú llamado Debug ya me hace feliz :)
Recomendaciones de Índices en el Plan de Ejecución
No se si se apreciará bien en la captura de pantalla que os adjunto, pero si os fijáis en la ventana de abajo (la que muestra el plan de ejecución), veréis que en la caja de texto nos aparece una línea en verde. Bien, esa línea nos indica que nos vendría bien un índice determinado: si pulsamos con el botón derecho y le pedimos información adicional sobre el índice, nos llega a generar el script que tendriamos que ejecutar para implementar el índice.
En mi ejemplo, el script sería el siguiente:
/*
Faltan detalles del índice de SQLQuery2.sql - (local)\SQLExpress.Performance (DEMOSTENES\Plain Concepts (53))
El procesador de consultas estima que la implementación del
siguiente índice podría mejorar el costo de la consulta en un 46.7053%.
*/
/*
USE [Performance]
GO
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[Orders] ([orderdate])
INCLUDE ([custid],[empid],[shipperid])
GO
*/
Cómo se puede ver, ¡hasta nos realiza la estimación de la mejora de rendimiento en caso de implementar el índice!
No se como lo veréis vosotros, pero a mi estos detalles pequeños me encantan; en este caso, la tecnología no es nueva... en el fondo esto consulta unas DMVs que nos muestran esta información de índices no utilizados, etc. que es lo que emplea el Database Engine Tuning Advisor para darnos sus recomendaciones sobre índices. Por lo tanto, nada nuevo bajo el sol. Sin embargo, lo que me fascina es el hecho de que esté integrado en el SSMS, que es desde donde yo suelo lanzar el 80% de mis consultas en tiempo de desarrollo. De éste modo tenemos la oportunidad de ver estos mensajes de advertencia sobre nuestras políticas de índices antes de llegar a fases mas tardías de análisis y optimización.
Monitor de Actividad
El monitor de actividad, ese gran desconocido. Lo cierto es que yo no lo empleaba; generalmente, para ver la actividad de los diferentes procesos de SQL Server recurría a los conocidos sp_who y sp_who2, y desde la versión 2005 también a diferentes DMVs e informes del servidor.
Sin embargo, ¡puede que hasta yo mismo me vuelva un adepto del monitor de actividad y las interfaces gráficas de administración! He estado jugando con al Monitor de Actividad que viene con la versión RC0 y he de decir que estoy gratísimamente sorprendido. No solo nos muestra de un vistazo rápido el estado de todos los procesos, sino también de las consultas mas costosas ejecutadas recientemente sobre el servidor, las esperas por recursos (waitstats), uso de E/S sobre los ficheros de la base de datos y más información de un modo muy conveniente y práctico, en la linea del nuevo Performance Monitor de Windows Vista y Windows Server 2008.
Os pongo una pequeña captura de pantalla para que veáis el aspecto que tiene:
Conclusiones
Vaya por delante que este post no ha pretendido ser exhaustivo sobre nuevas características de SQL Server 2008 RC0. No se trata de un artículo de 'Primeras Impresiones', sino de una oportunidad de compartir con vosotros un par de cositas que me he encontrado :)
Cuando comencé a trastear con el producto me encontré con estos detalles (y alguno más); estaba esperando ponerme a explorar iFTS principalmente, así como otras características de mayor peso, pero finalmente preferí perderme con estos detalles (que normalmente no reciben exposición en artículos y blogs) y compartirlos con vosotros. Espero que este post, aunque no haya seguido mi línea, os sirva al menos para conocer algunos pequeños desconocidos y para abriros el apetito por SQL Server 2008 RC0.
Por cierto, si os animas a trastear con él, podéis descargarlo desde el este enlace. Enjoy!
Rock Tip:
Esta vez me gustaría dedicar el post a todo el grupo de producto de SQL Server; a pesar de que esta release ha tenido un tiempo de desarrollo relativamente corto (¡sobre todo si lo comparamos con el de SQL Server 2005!), no dejan de ser unos años de esfuerzo, cariño y dedicación que dentro de muy poquito culminarán con el 'nacimiento' de la versión RTM. Por ello, este post lo acompaño del tema 'The Last Mile', de Cinderella. Un poquito más... una milla mas, y podremos empezar a poner SQL Server 2008 en producción como locos ;)