viernes, 11 de abril de 2014

HASH WARNING - qué es y cómo evitarlo -

   Amigos,

   Que tal... Hoy quiero contarles acerca de los "HASH WARNINGS" que uds. muy probablemente hayan encontrado estudiando sus planes de ejecución o bien auditando el SqlSrv a través de la consulta del trace file (ver http://gherrerasqlserver.blogspot.com.ar/2011/09/auditando-sql-server-consultando-el.html) etc

   Qué indica un "Hash Warning"?

   Indica que nuestro motor de base de datos está leyendo o escribiendo datos desde el disco (TempDb), algo muy malo para nuestra performance.

  ORIGEN DEL PROBLEMA

   El Sql Server hace un Hash cuando tiene que joinear dos tablas y se encuentra con que los campos correspondientes al Join no están ordenados por la falta de idx o bien, están indexados pero las estadísticas que subyacen de esos idx están desactualizadas

   El Hash es un algoritmo que utiliza el motor de nuestra base de datos para resolver los joins cuando no encuentra los campos ordenados (indexados). Concretamente separa en pequeños grupos los registros correspondientes a esos campos para poder matchearlos con mayor facilidad. Cuando esos grupos exceden la capacidad de almancenamiento en memoria, el sql los vuelca a la TemDb qenerando el no deseado HASH WARNING.

  SOLUCION DEL PROBLEMA

   -          Revisar que siempre las columnas de un join tengan su correspondiente idx

   -          Tener actualizadas las estadísticas de esos idx (nosotros tenemos un sp que una vez por semana se encarga de eso)

   -          Si el problema persiste ir hacia otro tipo de join, por ejemplo el merge join.


    A tenerlo en cuenta y a poner en sintonía a los desarrolladores que poco saben de los problemas que pueden acarrear sus códigos pocos cuidadosos.

   
      Les saluda Gustavo Herrera desde Argentina.

jueves, 10 de abril de 2014

Sort Warning - qué es y cómo evitarlo -

Amigos,

     Probablemente hayan dado con este mensaje estudiando un plan de ejecución, o auditando el sql server a traves de la consulta del trace file ( http://gherrerasqlserver.blogspot.com.ar/2011/09/auditando-sql-server-consultando-el.html)


          Ante todo digamos que la detección de un Sort Warning, no es un hecho que debamos dejarlo pasar, ya que puede implicar una importante merma en la performance de las queries afectadas.

      Qué indica un "Sort Warning" ?

      Puntualmente indica que el motor de nuestro SQL Server está resolviendo en el disco un ordenamiento  indicado en una query (ORDER BY), escribiendo y leyendo datos desde la TempDB, en lugar de resolverlo en la memoria RAM.
  
      No hace falta decir pues, que cualquier lectura o escritura hecha desde el disco es mucho más lenta y nociva que otra hecha en memoria.

          
    Pero es que estamos mal de memora RAM ?  No necesariamente..

    Entonces qué pasa?

    Veamos …

     ORIGEN DEL PROBLEMA

      El Sql Server genera un plan de ejecución y lo cachea para cada query y para cada sp. Cuando esa query  o sp incluye “order by” lo que hace es determinar la cantidad de memoria que ese order by  va a precisar y ya lo guarda como parte del plan de ejecución. 

      Ocurre que , el SQL,  "se queda corto" en esa cálculo,  porque de pronto se puede encontrar con que las columnas a ordenar terminan siendo muchas más que las que tomó como ejemplo cuando hizo ese plan de ejecución que ahí quedó, clavado en memoria:

       Hay 3 motivos por los cuales los ORDER BY pueden tener dimensiones mayores a las normales y llevar al sql server a leer de disco:

1)      La query en el Where compara un campo de la tabla contra otro campo de la misma tabla dando un valor muy grande.

Select   ani
from
Smsmessages
Where date_begin = date_end
ORDER BY  ANI

2)       La query en el Where compara un campo de la tabla contra una variable externa

Select   ani
from
Smsmessages
Where  Id > @variable
ORDER BY  ANI

3)       Una query con order by dentro de un sp recibe un parámetro a través del mismo que hace que tenga que ordenar muchos más datos que los que el plan del sp tenía pensado.

  
     Les aseguro que los problemas de performance que se producen a instancias de los sort-warnings son bastante considerables, críticos.

    SOLUCION

     Cuál es la solución siendo que no se puede evitar los 3 motivos de arriba?

      Simplemente evitar los ORDER BY cuando no son estrictamente necesarios. (no se rian por favor) .   En verdad si un order by no va acompañado de un top, hablamos de un order by que apunta a entregar data presentada de tal o cual forma, pues bien, CAMBIEMOS EL CAMPO DEL ORDER BY (busquemos uno que no sea influenciado por los 3 motivos de arriba) o bien ELIMINEMOSLO.

     Consejo:   no dejen pasar de largo nunca un "Sort Warning". Ataquen sus orígenes y aleccionen a los desarrolladores para que dejen de lado los ORDER BY cuando no son estrictamente necesarios. Por último, revean los order by de las queries o sp si es que están padeciendo el problema.

Les saluda desde Argentina, Gustavo Herrera
      

UPGRADE SQL SERVER VERSION - 5 PASOS PREVIOS INDISPENSABLES -

Amigos,

   Ha llegado el momento de pasar de una versión de SQL SERVER hacia otra. Ya tienen la decisión tomada, han estudiado los features y las ventajas que les proporciona la nueva versión y cuentaN con el prespuesto para adquirir el software...

   En primer lugar deben elegir entre hacer una instalación "limpia", desde cero. O escoger la segunda opción, la de hacer un "upgrade" de la versión de sql server que hoy tienen hacia la versión hacia la cual desean migrar.

  Basándome en un típico upgrade, en este caso de SqlServer 2005 a SqlServer2008 R2, quiero recomendarles que sigan los 5 pasos que a continuación les dejo y eviten la tentadora y peligrosa opción de "dejarse llevar" por el Wizzard y dejar librada vuestra suerte "a las buenas de Dios".

  La forma profesional de encarar esta tarea es la siguiente: 


1)      VERIFICAR QUE NUESTRO UPGRADE SEA SOPORTADO

 

http://msdn.microsoft.com/en-us/library/ms143393(v=sql.105).aspx

 

 

2)      CORRER EL SQL SERVER UPGRADE ADVISOR

 

        Se debe utilizar el Microsoft SQL Server 2008 Upgrade Advisor

 

       2.1)  Detalle

 

-          Analiza instancias de Sql Server 2000 y Sql Server 2005 en preparación para el upgrade
-          Identifica cambios de recursos y configuración que pueden afectar el funcionamiento del sistema cuando se lleva a cabo el upgrade.
-          Provee links con documentación que describen e identifican cada problema encontrado y dice como resolverlo

         2.2)  Download

             -     El link es http://www.microsoft.com/en-us/download/details.aspx?id=11455
-          Hay 3 tipos de archivos disponibles
File name: 

SqlUA.msi                 (para 32 bits)

SqlUA_ia64.msi         (para 64 bits con procesador con arquitectura Itanium) 

SqlUA_x64.msi          (para 64 bits con arquitectura standard)


          2.3)  Requerimientos del Sistema

-          The Microsoft .NET Framework 2.0
-          Windows Installer 4.5 (para saber que versión de Windows installer tiene ingrese a run y escriba y ejecute este comando “msiexec.exe /?.”)


2.4)  Información Adicional

-          Upgrade Advisor puede analizar instancias remotas, excepto para Report.Services
-          No cambia ninguna configuración, settings o data.
-          Provee el UpgradeAvisorWizardCmd commad-prompt para ayudar a escanear múltiples instancias de Sql Server
-          No considerar “Other Issues” en el reporte generado


3)      VERIFICAR LOS REQUERIMIENTOS DE HARDWARE

 

 

-          Si vamos a encarar un upgarade “in situ” en lugar de una migración es sumamente importante verificar los requerimientos de hardware previamente para ello Microsoft nos provee de la siguiente página: http://msdn.microsoft.com/en-us/library/ms143506(v=sql.105).aspx


4)       REALIZAR UN BACKUP FULL PREVIO AL UPGRADE

 

-           Generalmente no debiesen existir mayores problemas en un proceso de upgrade mas es imperioso tomar la precaución de hacer un Backup Full que nos permita revertir el Sql Server al estado previo al Upgrade.
-          

5)       TOMAR  ALGUNOS RECAUDOS ADICIONALES

 

-           Desactivar aquellos store procedures que vayan a correr por Schedule en el proceso de upgrade
-          Hacer un check de la Master – Model – MSDB y TEMPD y verificar que tengan habilitado el autogrow y espacio en disco para hacerlo.
-          Setear el “Max Worker Threads” value to 0 para que el Sql Server ya upgredeado calcule automáticamente el valor óptimo para esa variable.
-          Estemos atentos de features que son discontinuados de una versión a otra.



   Estoy a disposición de uds como siempre.

   Les saluda Gustavo Herrera desde Argentina.

jueves, 16 de enero de 2014

Borrar Data Vieja en Tablas Particionadas - Switch Partitions

Buenas tardes amigos. 
Ante todo agradecer la enorme cantidad de correos recibidos con salutaciones, agradecimientos, consultas, correcciones etc.  Es un placer estar en contacto con uds y sepan disculpar si no les contesto a tiempo.

Ok dicho esto y deseándoles un feliz 2014 vamos al tema que nos convoca.

Ya hemos visto

1) Como  particionar tablas en 5 pasos http://gherrerasqlserver.blogspot.com.ar/2013/05/particionar-tablas-en-5-pasos.html

2) Como mantener las particiones creadas (Split y Merge) http://gherrerasqlserver.blogspot.com.ar/2013/05/mantener-particiones-de-tablas-split-y.html

Pues bien habiendo recibido un correo de un lector del blog que me hablaba del enorme tiempo que le insumía el borrar vieja data de una partición, en oportunidad del pase a histórico de la data más vieja de la partición. Me di cuenta que nunca les hablé de cómo  llevar adelante esta tarea rápidamente a través de Switch Partition.

Vamos a poner manos a la obra.

Supongamos que tenemos este esquema de partición con los datos de nuestras ventas de los años 2012 y 2013

CREATE PARTITION FUNCTION [PF_Ventas](datetime)
AS RANGE LEFT
FOR VALUES ('2012-06-30 23:59:59.000',
            '2012-12-31 23:59:59.000',
            '2013-06-30 23:59:59.000',
            '2013-12-31 23:59:59.000')

GO

Pues bien amigos... ok para pasar a una tabla histórica los datos del primer semestre del 2012.

En lo primero que pensaríamos sería en hacer un insert de los datos de la tabla de ventas en una tabla histórica y luego borrar de la tabla ventas los registros


INSERT INTO ventas_old
select * from ventas
where  fecha < '2012-06-30 23:59:59.000'


Delete from tabla_ventas
where fecha < '2012-06-30 23:59:59.000'

Para luego mergear la partición 1  y 2  ver merge y split en 2)

ERROR !!!

Pero por qué?

 Estaríamos generando una enorme carga en nuestro servidor borrando millones de registros, bloqueando la tabla y generando muy posiblemente un crecimiento desmesurado de nuestro LOG...

SOLUCION

Microsoft pensó en nosotros y nos pone a disposición una forma mucho menos costosa de hacerlo a través del comando SWITCH PARTITION

Veamos:

Paso 1) Creamos una tabla temporal con idéntica estructura a la tabla en la que queremos borrar la data ( en nuestro ejemplo la tabla ventas )


CREATE TABLE [dbo].[temp_ventas](
      [fecha] [datetime] NULL,
      [codigo] [integer] NULL,
      [Descripción] [varchar](100) NULL)


Paso 2) Switcheamos la particion hacia la tabla temporal creada. Esto, por simple movimiento de metadata generará la transeferencia de los datos que queremos pasar a histórico hacia la tabla temporal de un sorprendemente rápido. Sin costos para el sistema.

  
ALTER TABLE Ventas
SWITCH PARTITION 1 TO Temp_Ventas


PASO 3)  Ahora si, con la data a pasar a histórico en la tabla temporal podremos

    3.1)  Insertar rápidamente esta data en nuestra tabla histórica ventas_old desde nuestra tabla temporal

    3.2)   Dropear nuestra tabla temporal

    3.3)  Hacer ahora si el merge y borrar el datafile y el filegroup viejo (ver Mantenimiento de Particiones en este mismo blog)


Y bien amigos... eso es todo por ahora, sencillo y práctico.

Los animo a ponerlo en práctica y como siempre a preguntarme si encuentran dificultades.

Saludos!!!

miércoles, 11 de diciembre de 2013

DELETE CON JOIN (inner - left - right)

Amigos,

    He recibido varias consultas vía mail preguntando sobre esta posibilidad, la de hacer el borrado de una tabla filtrando los registros a borrar a partir del valor de un campo de otra tabla que "joinearemos" con la tabla base.

   La respuesta es si! Claro que si, simplemente les dejo un ejemplo que es de por si explicativo y como siempre me pongo a disposición de Uds. para cualquier duda o consulta.


 -- Delete With Inner T-Sql --


-- Se escribe el delete from la tabla en la que se quiera borrar
Delete
From
HumanResources.Employee
-- Se construye el Join que permitirá utilizar en el where el campo que usaremos como condición para borrar
From HumanResources.Employee
inner join HumanResources.EmployeeAddress
on HumanResources.Employee.EmployeeID = HumanResources.EmployeeAddress.EmployeeID
-- En el where se filtran los registros a borrar haciendo referencia a un campo de la tabla joineada
where HumanResources.EmployeeAddress.EmployeeID = 11

  
   Saludos, Gustavo Herrera

martes, 10 de diciembre de 2013

FUNCIONES SQL SERVER - Utilidades y Diferencias con Stores Procedures y Vistas --

Amigos,

    Hoy les traigo un tema que puede parecer triyado, pero sobre el que no está de más hacer un repaso, estoy hablando de las Funciones.

   Definición:

   Ante todo las funciones son un conjunto de sentencias que funcionan como una unidad lógica.

   Pero si las funciones son un conjunto de sentencias que devuelve un conjunto de resultados, qué diferencia tienen con los Store Procedures y las Vistas?

   Hablemos de algunas diferencias fundamentales que pueden justificar su uso:

   - A diferencia de un procedimiento almacenado, pueden ser referenciados en el from de una consulta y pueden ser utlizadas también en el join de  un consulta

  -  A diferencia de las vistas, pueden incluir todo tipo de sentencias como IF, pueden llamar a otras funciones o procedimientos... mientras que las vistas solo pueden devolver el resultado de un select.

 -   En el caso de las funciones escalares pueden emplearse como campo en cualquier consulta

  
   De la misma forma que los sp, pueden recibir parámetros de entrada y devolver parámetros de salida.
    
  
   Tipos de Funciones 

   Yo les propongo pues que entendamos la utilidad de las funciones mediante ejemplos prácticos para cada tipo de función. Empecemos...


   1) Funciones Escalares (Scalar-valued Functions)

       1.1)  Retornan un único valor
       1.2)  Pueden emplearse en cualquier consulta como un campo más de la misma
       1.3)  Admite parámetro de entrada y devuelve un único valor como salida.
       1.4)  Al ser "llamadas" se las debe llamar con su nombre completo dbo.NombreFunción

        La siguiente función llamada F_Mes devuelve el nombre de un mes a partir de el ingreso (como parámetro) de una fecha determinada.

      
Create Function F_Mes

 -- parametros de entrada con valor por default --
 (@fecha datetime='2007/01/01')

 -- tipo de datos retornado --
  Returns varchar(10)
 
  as
  -- cuerpo de la funcion --
  Begin
    -- declaro variable que va a devolver --
    declare @nombre varchar(10)
   
    set @nombre=
     case datename(month,@fecha)
       when 'January' then 'Enero'
       when 'February' then 'Febrero'
       when 'March' then 'Marzo'
       when 'April' then 'Abril'
       when 'May' then 'Mayo'
       when 'June' then 'Junio'
       when 'July' then 'Julio'
       when 'August' then 'Agosto'
       when 'September' then 'Setiembre'
       when 'October' then 'Octubre'
       when 'November' then 'Noviembre'
       when 'December' then 'Diciembre'
     end
    return @nombre

 end;
  
-- Llamado de la función como parte de la consulta a tabla empleados --
 select
 nombre,
 dbo.f_nombreMes('2007/01/01') as 'mes de ingreso'

 from empleados;

  
  2) Funciones de Tabla (Table-valued Functions)

       1.1)  Retornan una tabla
       1.2)  Pueden emplearse en lugar del from de una consulta
       1.3)  Pueden "joinearse" en  cualquier consulta.
       1.4)  No necesitan ser llamadas por su nombre completo.

      La siguiente función llamada F_Baratas  devuelve una tabla con todas aquellas novelas cuyo precio sea menor al pasado como parámetro

.
Create Function f_baratas
-- Parámetro/s de Entrada --
 (@Valor decimal (6,2))
 
-- Nombre de la Tabla de Retorno --
  returns @Libros

-- Formato de la Tabla de Retorno
 (Id Integer,
  Novela varchar(40),
  Autor varchar(40)
  Precio decimal (6,2))
  as
 
-- Cuerpo de la funcion --
 Begin

   -- Inserta Datos en la Tabla --
   insert @Libros
   select codigo, novela, autor, precio from libros
   where precio < @Valor
  
   -- retorna la tabla --
   return
 end;
 
 -- Llamado de la Función --
 select * from f_baratas (10);

 -- Podemos hacer un Join --
 Select *, l.editorial from f_baratas(10) as b
 left join libros as l
 on b.id = l.id

 -- O Podemos usarlo como vista --
 Select codigo, autor
 from f_baratas(10)


    3) Funciones de Agregado (Aggregate Functions)

       3.1) Son las típicas funciones que combinan varios valores y retornan un único valor
       3.2) Ejemplos Típicos "count" "sum" "min" "avg" etc.

    4) Funciones del Sistema (System Functions)

       4.1) Son las distintas funciones preestablecidas por el sql server.
       4.2) Hay de distintos tipos...
             4.2.1) De configuración, Select @@version;
             4.2.2) De fecha y hora ... Datead ()
             4.2.3) De metadatos (devuelven info sobre las bd y objetos)
             4.2.4)etc. (recomiendo abrir el front end del sql server y ver cada una de Ellas)


   Amigos, esto fue todo, espero haber sido claro y ante consultas saben que cuenta conmigo

    Saludos desde Argentina, 

     Gustavo Herrera para "SQL Server para Todos"

                        


  

jueves, 14 de noviembre de 2013

Listar Las Queries Mas "Pesadas" de Nuestro Servidor - (las queries "que mas tardan" en devolver resultados)

Estimados amigos, una vez más con ustedes.

Cuántas veces se han preguntado cuáles son las queries que se presentan como "las más complicadas de resolver" para nuestro motor de base de datos?

 Pues aquí les dejo un script que hará este trabajo para uds...

 Es muy útil  cuando notan problemas de performance y deciden comenzar a "atacarlos".

 Es una muy buena práctica dedicarle un tiempo a estudiar y tratar de mejorar al menos las queries más costosas (añadiendo índices, mejorando las estadísticas, cambiando lo lógica de las queries etc)

 Este script les devuelve las 10 queries más costosas con datos tomados desde la última modificación del plan de ejecución.

 Desde ya, incluye todas las queries que atacan por consola o por medio de un store procedure.

 La última columna les da un link que les permite ver el plan de ejecución gráfico.

 Cualquier duda estoy a su disposición.

 Saludos desde Argentina queridos colegas.

 IMPORTANTE --> El nivel de compatibilidad de la BD debe ser 90 o superior.   

Detalle: Lista las 10 queries más costosas de nuestra base de datos 
Autor  : Gustavo Herrera para Sql Server Para Todos                             


SELECT
TOP 10
SUBSTRING(qt.TEXT, (qs.statement_start_offset/2)+1,((CASE qs.statement_end_offset WHEN -1 THEN DATALENGTH(qt.TEXT)ELSE qs.statement_end_offset END - qs.statement_start_offset)/2)+1) as query,
qs.execution_count as 'cantidad de ejecuciones',
qs.total_logical_reads as 'total_lecturas_lógicas',
qs.total_logical_writes as 'total_escrituras_lógicas',
qs.total_worker_time 'total_CPU_consumida_ms',
qs.total_elapsed_time/1000000/60 'total_mts_consumidos_x_la_ejecución',
qs.max_elapsed_time/1000000/60 'máxima_tardanza_en_la_ejecución_mts',
qp.query_plan 'link_plan_ejecucion'
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp

ORDER BY qs.last_elapsed_time DESC