Buscar este blog

martes, 23 de mayo de 2017

Sql Server Best Practices

Amigos,

    Son muchos los mails que recibo y contesto en modo privado con preguntas relacionadas con "buenas prácticas" para nuestro entorno de Base de Datos.

    Ya hemos hablado sobre el tema en post anteriores mas, en lo personal, creo que debemos seguir "machacando" una y otra vez sobre estas buenas prácticas para que nuestra vida como DBA's no sufra evitables y molestas desventuras...
  
   Hagamos entonces un breve repaso de buenas prácticas, como siempre quedo a vuestra disposición, saludos cordiales desde Argentina.

    
1.    Diseñando las bases con el máximo grado de normalización posible.

                       *  Elimine los grupos repetidos de las tablas individuales.(redundancia)
                       *  Cree una tabla independiente para cada conjunto de datos relacionados 
                       *  Identifique cada conjunto de datos relacionados con una clave principal.
                       *  Relacione estas tablas con una clave externa.
                       *  Elimine los campos que no dependan de la clave.

2.     Utilizando el Isolation Level más laxo acorde nuestras regla de negocio

·         Si nuestras reglas de negocio permiten realizar lecturas sin loqueo, conocidas como “lecturas sucias”,  podemos entonces setear nuestro Isolation Level en “Read Uncomitted” o bien utilizar el hint “no lock “
·         Hay también otras alternativas intermedias entre el IL por default y el Read Uncomitted, por ejemplo el que permite la lectura por versionado llamado “Read_Uncomitted_Snapshot”

3.     Programando queries performantes

 3.1) Seleccionando la menor cantidad de datos posibles. (ser muy selectivo en los campos a filtrar, en los where, en los having…)
 3.2) Manteniendo las transacciones chicas. (un Select no tiene por qué formar parte de transacción )
3.3) Utilizando datos del mismo tipo para comparaciones y joins de tablas evitando así conversiones implícitas-
3.4) Reemplazando cursores por el uso de While+Tablas temporales o Tablas variables  http://www.sqlbook.com/advanced/sql-cursors-how-to-avoid-them/
3.5) Utilizando los campos indexados para los campos select, las cláusulas where, los joins, lor order by, group by…
3.6) No permitiendo interacciones de usuarios dentro de las transacciones (cualquier transacción que permanezca abierta esperando un input de un user es bloqueante)
3.7)  Utilizando Métodos “Set – Based” por sobre “Procedural Methods”        https://www.codeproject.com/Articles/34142/Understanding-Set-based-and-Procedural-approaches
3.8) Estudiar Planes de Ejecución y otimizando las queries y atacando las queries + lentas
3.9) Eliminando los Order By  cuando no son necesarios
3.10)  Disminuyendor al Máximo el Uso de Funciones del Sistema (por ejemlplo la función max(), genera un scant table más allá del que el campo esté o no idx.
3.11)  Utilizando los Hints Necesarios
3.12)  Evitando bloqueos de recursos por borrados masivos de datos. A veces en mucho menos perjudicial para el sistema el generar una tabla nueva con los datos online que el borrar los datos que queremos deprecar de una tabla mediante el uso de un delete
3.13)  Evitando “Chatty Aplications”. Se conoce como Chatty App aquellas que commitean data en reiteradas ocasiones en lugar de hacerlo una vez. (por ejemplo formularios de suscripción web que validan cada dato que el user va llenando)

4.    Dotando a las tablas de los índices necesarios

4.1) Una buena indexación es aquella que es funcional a los procedimientos y que no excede las necesidades reales. 

4.2) Seleccionando los campos más “chicos” en términos de “tipo de datos” (un idx  debería ser hecho sobre un campo integer o datetime mientras su utilidad sería muy poca en campos del tipo varchar)

4.3)  Eliminando aquellos índices que NO son necesarios (recordemos que todo índice tiene asociado un costo de mantenimiento  y almacenamiento además de atentar contra la performance en caso de inserciones sobre tablas sobreindexadas)

4.4)  Generando e Implementando Rutinas de Mantenimiento de Indices (es muy importante que los índices se mantengan desfragmentados, especialmente en entornos oltp)

4.5) Utilizando Indices Cubiertos, para consultas en las que puedan eliminarse key lookups, incluyendo campos del select en forma lógica con la cláusula “include”


5.    Generando Rutinas de Mantinimiento de Estadísticas

5.1) Las estadísticas son importantísimas para que nuestros planes de ejecución elijan la mejor alternativa para ejecutar una query. Tengan en cuenta que si bien Microsoft nos da la chance de setear su actualización automáticamente dicha actualización no es efectiva. Utilicen una rutina para tal fin. La pueden encontrar también en este blog


6.    Implementando el Pariticionado de Tablas

6.1)  El particionar tablas puede agilizar mucho nuestras consultas en tablas que necesitan mantener grandes cantidades de datos históricos on line y que por lo tanto tienen varios millones de registros.  Si en este tipo de tablas, existen consultas donde se puede llegar a necesitar datos históricos y actuales de un cliente (por ejemplo la consulta histórica de la cuenta corriente de una empresa), pues bien, sería una buena idea particionar por año y generar, distribuir datafiles en distintos discos y generar lecturas paralelas. OJO NO ABUSAR de las PARTCIONES, ya que su mantenimiento es complejo (más de todo este tema en este blog)

7.    Distribuyendo los datafiles de nuestra base de datos correctamente

7.1)  El gran punto fuerte del SQL Server es la posibilidad de realizar lectoescrituras paralelas Para ello un escenario ideal es el tener separado en unidades físicas diferentes:
                 - El OS
                  - El motor de Base de Datos
                  - Los archivos de Datos
                  - Los archivo de índices
                  - Los archivos de log.

7.2)  Una vez hecho esto el analizar la carga de los discos (i/o) valiéndose del perfomance monitor y, llegado el caso, dettachar y reubicar los files que sean necesarios:

8.     Seteando la instancia del motor de base de datos del modo más eficaz posible.

Seteos como Memoria Asignada / Máx grado de paralelismo / Uso de Procesadores etc son sumamente importantes para la performance y estabilidad de nuestro sistema. Es importante lograr la mejor configuración para los mismos y revalidarla acorde al control permanente que debemos hacer sobre las bases y su estabilidad y performance.

9.     Manteniendo on line solo la data necesaria
El realizar el pase a files “off line” o bien a backups, es una tarea que si la reglas de negocio la permiten debería ser planificada y ejecutada con periodicidad.

10.  Evitando la fragmentación física de los discos
Es muy importante que tengamos corriendo en períodos de baja o nula concurrencia alguna herramienta eficiente de desfragmentado de nuestros hard disk.


11.   Monitoreando permanentemente nuestro servidor y base de datos

Es vital la uilización del performance monitor y el event viewer y el establecimiento de baselines..Las vistas del sistema son también aliados excluyentes para el monitoreo y el traceo de posibles deficiencias El revisar logs y utilizar trazas "server side"es algo fundamental.