{"id":516,"date":"2018-02-09T07:49:17","date_gmt":"2018-02-09T07:49:17","guid":{"rendered":"https:\/\/sqldoubleg.live-website.com\/?p=516"},"modified":"2018-02-09T07:51:16","modified_gmt":"2018-02-09T07:51:16","slug":"here-is-your-index-now-what","status":"publish","type":"post","link":"https:\/\/www.sqldoubleg.com\/es\/2018\/02\/09\/here-is-your-index-now-what\/","title":{"rendered":"Aqu\u00ed est\u00e1 tu Indice, \u00bfAhora qu\u00e9?"},"content":{"rendered":"<p>Es posible que esta historia suene familiar para la mayor\u00eda de DBA&#8217;s que est\u00e1n ya experimentados. Nuestro trabajo consiste en mantener las bases de datos funcionando y, de vez en cuando, hacer que sean m\u00e1s r\u00e1pidas (no voy a entrar en que significa r\u00e1pido, por si acaso). En otras ocasiones, tenemos desarrolladores que quieren que su c\u00f3digo se ejecute m\u00e1s r\u00e1pido, no se a que tanta prisa la verdad&nbsp;Es posible que esta historia suene familiar para la mayor\u00eda de DBA&#8217;s que est\u00e1n ya experimentados. Nuestro trabajo consiste en mantener las bases de datos funcionando y, de vez en cuando, hacer que sean m\u00e1s r\u00e1pidas (no voy a entrar en que significa r\u00e1pido, por si acaso). En otras ocasiones, tenemos desarrolladores que quieren que su c\u00f3digo se ejecute m\u00e1s r\u00e1pido, no se a que tanta prisa la verdad \ud83d\ude42<\/p>\n<p>Y tambi\u00e9n de vez en cuando tenemos que crear \u00edndices para que eso suceda, pero \u00bfah\u00ed se acaba la cosa? \u00bfEst\u00e1s seguro de que tener el \u00edndice es suficiente? \u00bfVa a servir de algo? Vamos a ver, aqu\u00ed est\u00e1 tu \u00edndice, \u00bfahora qu\u00e9?<\/p>\n<p><strong>Antecedentes<\/strong><\/p>\n<p>Los beneficios de tener un \u00edndice son bien conocidos, podemos obtener los mismos resultados leyendo una cantidad menor de datos, por lo que la mejora en el rendimiento puede ser de varios minutos a segundos o incluso menos.<\/p>\n<p>Eso suena incre\u00edble y ciertamente lo es, hay personas que viven de ello, as\u00ed que obviamente es bastante importante.<\/p>\n<p>Pero no siempre es as\u00ed, y las cosas pueden salir mal f\u00e1cilmente y convertir a todos estos \u00edndices en una carga in\u00fatiles.<\/p>\n<p>Dejadme que os muestre algunos ejemplos, donde podemos ver nuestros \u00edndices en uso, pero tambi\u00e9n c\u00f3mo el procesador de consultas puede ignorarlos y volverse totalmente in\u00fatiles. Voy a utilizar la base de datos de ejemplo de Microsoft [WideWorldImporters] para que poda\u00eds seguir conmigo si quer\u00e9is.<\/p>\n<p>&nbsp;<br \/>\n<strong>Comportamiento deseado<\/strong><\/p>\n<p>Si comprobamos la tabla [Sales].[InvoiceLines], podemos observar que hay un \u00edndice no agrupado en [PackageTypeID], por lo que esperamos que las consultas que utilicen esta columna para filtrar los resultados se pueden  beneficiar de \u00e9l. Ex\u00e1ctamente como esta<\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\nUSE [WideWorldImporters]\r\n\r\nSELECT COUNT(*) \r\nFROM [Sales].[InvoiceLines]\r\nWHERE [PackageTypeID] = 9\r\n<\/pre>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/02_index_seek.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/02_index_seek.png\" alt=\"\" width=\"870\" height=\"200\" class=\"aligncenter size-full wp-image-519\" srcset=\"https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/02_index_seek.png 870w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/02_index_seek-300x69.png 300w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/02_index_seek-768x177.png 768w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/02_index_seek-150x34.png 150w\" sizes=\"(max-width: 870px) 100vw, 870px\" \/><\/a><\/p>\n<p>&nbsp;<br \/>\nY aqu\u00ed tenemos otro ejemplo.<\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\nUSE [WideWorldImporters]\r\n\r\nSELECT * \r\nFROM [Sales].[InvoiceLines]\r\nWHERE [PackageTypeID] = 1\r\n<\/pre>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/01_index_seek_key_lookup.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/01_index_seek_key_lookup.png\" alt=\"\" width=\"870\" height=\"240\" class=\"aligncenter size-full wp-image-518\" srcset=\"https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/01_index_seek_key_lookup.png 870w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/01_index_seek_key_lookup-300x83.png 300w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/01_index_seek_key_lookup-768x212.png 768w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/01_index_seek_key_lookup-150x41.png 150w\" sizes=\"(max-width: 870px) 100vw, 870px\" \/><\/a><\/p>\n<p>&nbsp;<br \/>\nEste segundo ejemplo no es tan bueno como el primero, ya que tambi\u00e9n debemos realizar b\u00fasquedas en la tabla para satisfacer la consulta porque estamos solicitando m\u00e1s columnas que las que existen en el \u00edndice.<\/p>\n<p>&nbsp;<br \/>\n<strong>Inhibidores de b\u00fasqueda de \u00edndices<\/strong> <\/p>\n<p>Pero no todo es arco iris y unicornios, hay d\u00edas en que los \u00edndices son in\u00fatiles, no es su culpa, generalmente la nuestra, pero al final no importa, nuestros \u00edndices son in\u00fatiles.<\/p>\n<p>&nbsp;<br \/>\n<strong>Estad\u00edsticas<\/strong> <\/p>\n<p>Hemos visto que la primera consulta es el ejemplo perfecto de lo que estamos buscando, leyendo s\u00f3lo de nuestro \u00edndice y s\u00f3lo las filas que nos interesan.<\/p>\n<p>El segundo ejemplo ya se empieza a salir del buen camino y tiene que a\u00f1adir otra operaci\u00f3n para obtener el resto de las columnas que no est\u00e1n incluidas en nuestro \u00edndice no agrupado.<\/p>\n<p>Siguiendo este segundo ejemplo, podemos encontrar nuestro primer inhibidor, que incluyo en este post aunque se puede decir que es \u00abbenigno\u00bb.<\/p>\n<p>El procesador de consultas usa las estad\u00edsticas para determinar el mejor plan de consulta para cada consulta y, a veces, es m\u00e1s eficiente leer la table entera que buscar en un \u00edndice no agrupado m\u00e1s b\u00fasquedas para obtener el resto de columnas.<\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\nUSE [WideWorldImporters]\r\n\r\nSELECT * \r\nFROM [Sales].[InvoiceLines]\r\nWHERE [PackageTypeID] = 9\r\n<\/pre>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/03_clustered_index_scan.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/03_clustered_index_scan.png\" alt=\"\" width=\"870\" height=\"200\" class=\"aligncenter size-full wp-image-520\" srcset=\"https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/03_clustered_index_scan.png 870w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/03_clustered_index_scan-300x69.png 300w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/03_clustered_index_scan-768x177.png 768w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/03_clustered_index_scan-150x34.png 150w\" sizes=\"(max-width: 870px) 100vw, 870px\" \/><\/a><\/p>\n<p>\u00bfHe dicho estad\u00edsticas?, vamos a echar un vistazo<\/p>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/04_DBCC_SHOW_STATISTICS.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/04_DBCC_SHOW_STATISTICS.png\" alt=\"\" width=\"870\" height=\"250\" class=\"aligncenter size-full wp-image-521\" srcset=\"https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/04_DBCC_SHOW_STATISTICS.png 870w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/04_DBCC_SHOW_STATISTICS-300x86.png 300w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/04_DBCC_SHOW_STATISTICS-768x221.png 768w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/04_DBCC_SHOW_STATISTICS-150x43.png 150w\" sizes=\"(max-width: 870px) 100vw, 870px\" \/><\/a><\/p>\n<p>Observad c\u00f3mo cuando usamos el valor 1, el optimizador cree que Seek + Lookup es el m\u00e1s eficiente considerando que solo hay ~ 725 filas, pero para el valor 9 hay ~ 4988 filas, demasiadas b\u00fasquedas, por lo tanto, el plan es simplemente escanear toda la tabla y elige aquellas filas que coinciden con el filtro.<\/p>\n<p>En alg\u00fan lugar entre el n\u00famero de filas para el valor 1 y 9 hay un punto llamado \u00abpunto de inflexi\u00f3n\u00bb una fila por encima de ese umbral y el optimizador cambiar\u00e1 el plan de buscar a escanear. Esto no es necesariamente algo malo. El optimizador suele saber mejor que nosotros cu\u00e1l es el mejor plan la mayor\u00eda de las veces.<\/p>\n<p>&nbsp;<br \/>\n<strong>Variables<\/strong> <\/p>\n<p>Otro problema que podemos tener cuando el optimizador mira las estad\u00edsticas del \u00edndice es si no estamos proporcionando un valor sino una variable. Ahora el optimizador tiene que adivinar cu\u00e1ntas filas se devolver\u00e1n para este valor desconocido antes de ejecutar la consulta.<\/p>\n<p>Veamos nuestro valor 1 cuando est\u00e1 en una variable.<\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\nUSE [WideWorldImporters]\r\n\r\nDECLARE @PackageTypeID INT = 1\r\n\r\nSELECT * \r\nFROM [Sales].[InvoiceLines]\r\nWHERE [PackageTypeID] = @PackageTypeID\r\n-- Estimated rows = 57066\r\n-- Query plan Clustered Index Scan\r\nGO\r\n<\/pre>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/05_index_scan_variable.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/05_index_scan_variable.png\" alt=\"\" width=\"870\" height=\"275\" class=\"aligncenter size-full wp-image-522\" srcset=\"https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/05_index_scan_variable.png 870w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/05_index_scan_variable-300x95.png 300w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/05_index_scan_variable-768x243.png 768w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/05_index_scan_variable-150x47.png 150w\" sizes=\"(max-width: 870px) 100vw, 870px\" \/><\/a><\/p>\n<p>&nbsp;<br \/>\nEl optimizador calcula cu\u00e1ntas filas por valor en promedio, para adivinar cu\u00e1ntas filas se devolver\u00e1n y si este n\u00famero supera el punto de inflexi\u00f3n, el plan es escanear la tabla entera.<\/p>\n<p>Teniendo en cuenta la cardinalidad de esta columna (\u00edndice) donde el n\u00famero de filas para la mayor\u00eda de los valores y el promedio supera el punto de inflexi\u00f3n, ser\u00eda m\u00e1s sensato si siempre realizamos un escaneo de tabla.<\/p>\n<p>Todo esto hace que nuestro \u00edndice sea totalmente in\u00fatil en la mayor\u00eda de los casos &#8230;<\/p>\n<p>&nbsp;<br \/>\n<strong>M\u00e1s problemas relacionados con estad\u00edsticas, detecci\u00f3n de par\u00e1metros <\/strong><\/p>\n<p>Ejecutar las consultas de arriba tal y como est\u00e1n, probablemente no sea lo que hacemos normalmente. Por lo general, escribimos procedimientos almacenados por aquello de reutilizar el c\u00f3digo y eso.<\/p>\n<p>El problema es que si la primera vez que ejecutamos el procedimiento proporcionamos el valor 1, el plan ser\u00eda \u00abSeek + Lookup\u00bb y ser\u00e1 as\u00ed independientemente del valor en las ejecuciones posteriores, mientras el plan est\u00e9 en memoria.<\/p>\n<p>Si el primer valor es 9, entonces leer la table entera ser\u00eda la elecci\u00f3n.<\/p>\n<p>No voy a profundizar en esto ya que el tema es lo suficientemente amplio como para tener una publicaci\u00f3n o sesi\u00f3n completa, simplemente haced una busqueda en Bing\/Google y ver\u00e9is posibles soluciones para este problema.<\/p>\n<p>&nbsp;<br \/>\n<strong>Mal T-SQL<\/strong><\/p>\n<p>Porque seamos honestos, a veces escribimos c\u00f3digo que apesta.<\/p>\n<p>Imaginemos que tenemos otro \u00edndice que en ambos casos, para valores espec\u00edficos o para variables, siempre devuelve index seek + key lookup y que tambi\u00e9n es la forma m\u00e1s eficiente &#8230; \u00bfC\u00f3mo suena eso? bien, \u00bfno?<\/p>\n<p>Y ahora imaginaos que escribimos nuestro c\u00f3digo y lo fastidiamoes \ud83d\ude41<\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\nDBCC SHOW_STATISTICS ('[Sales].[InvoiceLines]', [FK_Sales_InvoiceLines_StockItemID])\r\n\r\n\/*\r\nAvg -&gt; Rows * All density = 951\r\n\r\nRANGE_HI_KEY\tEQ_ROWS\r\n1\t\t\t\t1097.179\r\n2\t\t\t\t991.8209\r\n3\t\t\t\t999.087\r\n4\t\t\t\t1060.849\r\n...\t\t\t\t...\r\n\t\t\r\n*\/\r\n<\/pre>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/06_DBCC_SHOW_STATISTICS_even_distribution.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/06_DBCC_SHOW_STATISTICS_even_distribution.png\" alt=\"\" width=\"870\" height=\"300\" class=\"aligncenter size-full wp-image-524\" srcset=\"https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/06_DBCC_SHOW_STATISTICS_even_distribution.png 870w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/06_DBCC_SHOW_STATISTICS_even_distribution-300x103.png 300w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/06_DBCC_SHOW_STATISTICS_even_distribution-768x265.png 768w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/06_DBCC_SHOW_STATISTICS_even_distribution-150x52.png 150w\" sizes=\"(max-width: 870px) 100vw, 870px\" \/><\/a><\/p>\n<p>Los valores est\u00e1n distribuidos uniformemente, de modo que tanto cada valor como el promedio (utilizando una variable) produce el mismo plan de consulta, seek + lookup.<\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\nUSE [WideWorldImporters]\r\n\r\nSELECT * \r\nFROM [Sales].[InvoiceLines]\r\nWHERE [StockItemID] = 1\r\n-- Estimated rows = 1159\r\n-- Query plan Index Seek + Key Lookup\r\nGO\r\n\r\n\r\nDECLARE @StockItemID INT = 1\r\n\r\nSELECT * \r\nFROM [Sales].[InvoiceLines]\r\nWHERE [StockItemID] = @StockItemID\r\n-- Estimated rows = 1005\r\n-- Query plan Index Seek + Key Lookup\r\nGO\r\n\r\n<\/pre>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/07_always_index_seek_key_lookup.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/07_always_index_seek_key_lookup.png\" alt=\"\" width=\"870\" height=\"475\" class=\"aligncenter size-full wp-image-525\" srcset=\"https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/07_always_index_seek_key_lookup.png 870w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/07_always_index_seek_key_lookup-300x164.png 300w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/07_always_index_seek_key_lookup-768x419.png 768w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/07_always_index_seek_key_lookup-150x82.png 150w\" sizes=\"(max-width: 870px) 100vw, 870px\" \/><\/a><\/p>\n<p>&nbsp;<br \/>\nEste ejemplo es perfecto, entonces, \u00bfqu\u00e9 puede salir mal?, f\u00e1cil, \u00bfcu\u00e1ntas veces tenemos que escribir c\u00f3digo como este?<\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\nUSE [WideWorldImporters]\r\n\r\nDECLARE @StockItemID INT = 1\r\n\r\nSELECT * \r\nFROM [Sales].[InvoiceLines]\r\nWHERE [StockItemID] = @StockItemID \r\n\tOR @StockItemID IS NULL\r\n<\/pre>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/08_unexpected_clustered_index_scan.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/08_unexpected_clustered_index_scan.png\" alt=\"\" width=\"870\" height=\"200\" class=\"aligncenter size-full wp-image-526\" srcset=\"https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/08_unexpected_clustered_index_scan.png 870w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/08_unexpected_clustered_index_scan-300x69.png 300w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/08_unexpected_clustered_index_scan-768x177.png 768w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/08_unexpected_clustered_index_scan-150x34.png 150w\" sizes=\"(max-width: 870px) 100vw, 870px\" \/><\/a><\/p>\n<p>&nbsp;<br \/>\n<strong>BOOOM!!!<\/strong> ah\u00ed lo tienes, aqu\u00ed esta tu \u00edndice que no vale para nada.<\/p>\n<p>&nbsp;<br \/>\n<strong>\u00bfY que hacemos ahora?<\/strong><\/p>\n<p>Pues mala soluci\u00f3n tiene el asunto, y como suele decirse, \u00abdepende\u00bb.<\/p>\n<p>Obviamente habr\u00eda que tener en cuenta muchos factores, porque es raro que tengamos un proceso t\u00e1n simple como una consulta. La complejidad del mismo as\u00ed como la frecuencia con la que llamamos a este proceso pueden ser determinantes.<\/p>\n<p>Una de las posibles soluciones ser\u00eda usar dos consultas en vez de una y ejecutar una u otra en funci\u00f3n del valor del par\u00e1metro.<\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\nDECLARE @StockItemID INT = 1\r\n\r\nIF @StockItemID IS NULL BEGIN\r\n\tSELECT * \r\n\t\tFROM [Sales].[InvoiceLines]\r\nEND\r\nELSE BEGIN\r\n\tSELECT * \r\n\t\tFROM [Sales].[InvoiceLines]\r\n\t\tWHERE [StockItemID] = @StockItemID \r\nEND\r\n<\/pre>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/11_two_queries_seek_lookup.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/11_two_queries_seek_lookup.png\" alt=\"\" width=\"870\" height=\"250\" class=\"aligncenter size-full wp-image-529\" srcset=\"https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/11_two_queries_seek_lookup.png 870w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/11_two_queries_seek_lookup-300x86.png 300w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/11_two_queries_seek_lookup-768x221.png 768w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/11_two_queries_seek_lookup-150x43.png 150w\" sizes=\"(max-width: 870px) 100vw, 870px\" \/><\/a><\/p>\n<p>Y si pasamos NULL, entoces tenemos<\/p>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/12_two_queries_scan.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/12_two_queries_scan.png\" alt=\"\" width=\"870\" height=\"200\" class=\"aligncenter size-full wp-image-530\" srcset=\"https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/12_two_queries_scan.png 870w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/12_two_queries_scan-300x69.png 300w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/12_two_queries_scan-768x177.png 768w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/12_two_queries_scan-150x34.png 150w\" sizes=\"(max-width: 870px) 100vw, 870px\" \/><\/a><\/p>\n<p>&nbsp;<br \/>\nLa otra opci\u00f3n ser\u00eda usar OPTION(RECOMPILE), pero hay que tener cuidado con esta soluci\u00f3n por el posible impacto en el rendimiento general del servidor ya que recompilar tiene un coste de CPU que hay que tener en cuenta.<\/p>\n<p>Quedar\u00eda algo as\u00ed como <\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\nUSE [WideWorldImporters]\r\n\r\nDECLARE @StockItemID INT = 1\r\n\r\nSELECT * \r\nFROM [Sales].[InvoiceLines]\r\nWHERE [StockItemID] = @StockItemID \r\n\tOR @StockItemID IS NULL\r\n\tOPTION(RECOMPILE)\t\r\n<\/pre>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/13_option_recompile_seek.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/02\/13_option_recompile_seek.png\" alt=\"\" width=\"870\" height=\"250\" class=\"aligncenter size-full wp-image-531\" srcset=\"https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/13_option_recompile_seek.png 870w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/13_option_recompile_seek-300x86.png 300w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/13_option_recompile_seek-768x221.png 768w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/02\/13_option_recompile_seek-150x43.png 150w\" sizes=\"(max-width: 870px) 100vw, 870px\" \/><\/a><\/p>\n<p>&nbsp;<br \/>\n<strong>Conclusi\u00f3n<\/strong><\/p>\n<p>Hab\u00e9is visto lo f\u00e1cil que las cosas pueden torcerse y hacer que nuestro nuevo y brillante \u00edndice sea absolutamente in\u00fatil. Este ha sido solo un ejemplo, pero espero que sea suficiente como para haceros reflexionar acerca de lo dif\u00edcil que es optimizar consultas para mejorar el rendimiento.<\/p>\n<p>Gracias por leer y por favor dejadme en los comentarios lo que pensais sobre este u otros casos que os hayan pasado.<\/p>\n<p>&nbsp;<\/p>\n<p><\/p>","protected":false},"excerpt":{"rendered":"<p>Es posible que esta historia suene familiar para la mayor\u00eda de DBA&#8217;s que est\u00e1n ya experimentados. Nuestro trabajo consiste en mantener las bases de datos funcionando y, de vez en cuando, hacer&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[55,32,15],"_links":{"self":[{"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/posts\/516"}],"collection":[{"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/comments?post=516"}],"version-history":[{"count":0,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/posts\/516\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/media?parent=516"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/categories?post=516"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/tags?post=516"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}