Optimizaciones para SQL Server 2005
Para ciertos casos de uso es necesario trabajar bastante en optimizaciones para base de datos, puesto que ciertos sistemas pueden poseer un gran problema con el procesamiento en servidores, y el cpu puede llegar al 100%.
Para resolver dicho problema, luego de varias consultas e investigaciones, logre conseguir 10 importantes items a tener en cuenta a la hora de pensar en el diseño de la base de datos, de un sistema que es accedido por miles y miles de usuarios al mismo tiempo.
Cabe resaltar que me encuentro hablando de un sistema totalmente dinamico, el cual por cada acceso necesita consultar si o si a nuestra base de datos, sin necesidad de poseer paginas estaticas. Los siguientes items no son los únicos, pero a mi entender son bastante importantes:
1.- Sin Tablas Temporales: No se debe utilizar tablas temporales en stored procedures, las famosas #tmps nos hacen consumir bastantes recursos de memoria, en reemplazo de las mismas, se utilizan los data type table. Su uso es bastante similar, ej:
DECLARE @tmp TABLE(Id int, UserName varchar(128))
INSERT INTO @tmp(Id, UserName)
VALUES(1, ‘dave’)
2.- FullText en varios discos: Para las búsquedas es muy común utilizar contains, los cuales buscan dentro de los FullText creados para ciertos campos de una tabla. Cuando se posee más de un FullText, es recomendable tener un disco para cada uno de ellos, puesto que los mismos ejercen mucha presión en el disco, de esta manera dividimos la presión separandola en discos distintos.
3.- Sin Like’s: Es importante reemplazar todos nuestros queries en los cuales utilicemos el famoso ‘like’, ya que el mismo consume mucho procesamiento para ser ejecutado, en reemplazo, se puede utilizar el Contains.
4.- LOCK de tablas: En cada consulta o SELECT las tablas necesitan ser lockeadas, para devolver ciertas información solicitada para los queries, esto es completamente innecesario el 99% de las ocasiones, y genera un problema muy grande en nuestra base, ya que al ser consultada por miles de transacciones, las mismas comienzan a dar time out. La solución es incluir la siguiente sitaxis luego de cada select que deseemos realizar:
SELECT Id, UserName FROM WebUser WITH (NOLOCK) WHERE Id=@ParamId
5.- Leer y Escribir: Para tener preparado el sistema para escalar de manera masiva, es importante tener en cuenta realizar dos diferentes conecciones a la base, una para leer información y otra para escribir en tablas. La velocidad es la misma, ya que las conecciones se ejecutan de manera paralela, y en un futuro (inmediato tal vez), se podra utilizar un servidor de sql para escribir y x servidores a los cuales se replicara, y estos seran a los que consultaremos la información desde los web servers.
6.- Redundar información: En ciertas ocasiones se necesita realizar una acción que puede requerir varios recursos del sistema, es necesario analizar CUANDO es conveniente hacerla. Por ejemplo, saber cuantas relaciones hijas posee un detarminado registro, para éste caso analicemos cuantas veces se insertaran mas relaciones hijas o cuantas veces se consultaran la totalidad de las mismas. En la mayoria de los casos de uso, seguramente se encontraran con que las consultas son mas solicitadas que las escrituras, para ello se pueden hacer tablas de history, donde la información de los counts se pueda guardar, la misma puede ser guardada mendiante un trigger en la tabla que se desee contar, y de esta manera actualizar el history en cada insert, update o delete. Otra posibilidad es hacer correr un job cada x tiempo y que actualice la tabla history.
Es posible tambien tener las tablas con todos los registros en otra base de datos, y que ésta se encargue de replicar la información en los servidores de consulta.
7.- Evitar los Count(*): Esta consulta muchas veces hace que nuestros queries posean mayor tiempo en su ejecución, una posibilidad de evitarlo, es realizando tablas donde guardemos los contadores, y actualicemos los campos con incrementos o decrementos en los registros. Reconozco que en ciertos casos, genera problemas utilizar éste metodo, es por ello, que debemos analizar muy bien, cuando es necesario utilizar los COUNT.
8.- Index: Antes de realizar un indice, debemos analizar por cuales campos realizamos las consultas a ciertas tablas, una vez que obtuvimos dicha información, debemos generar diferentes indices en las tablas, en los cuales seleccionaremos los campos por los cuales realizamos los filtros en las consultas, o sea en nuestro WHERE.
9.- IS NULL: Para realizar consultas sobre un null en un campo, no se debe realizar mendiante una igualdad, en cambio se debe realizar mediante un “IS”, como muestra el siguiente ejemplo:
SELECT Id, UserName FROM WebUser WITH (NOLOCK) WHERE Name IS NULL
10.- WARNING CON LOS LOWER: Otro gran error es realizarle un LOWER a un campo de una tabla, para realizar comparaciones mediante igualdades. Si desde el comienzo sabemos que ésta acción será necesaria en un futuro, entonces, deberiamos insertar los registros con minúsculas. A continuación un ejemplo erroneo:
SELECT Id, UserName FROM WebUser WHERE LOWER(Name)=LOWER(@ParamName)
Si se cumplen los anteriores 10 items la presión sobre el servidor en el cual se encuentre la base de datos, será increiblemente menor.
carlos replied:
me gustaria saber como puedo hacer para correr varios jobs al mismo tiempo en sql 2005
EJP: tengo 150 job y quiero que se ejecuten solos dandole un clip que puedo hacer ?
November 9, 2008 at 8:13 am. Permalink.
David Balogh replied:
Carlos,
Respecto a tu pregunta, me gustaría conocer un poco tu diseño, puesto que me llama la atención que necesites correr tantos jobs al mismo tiempo, tal vez esta acción genere problemas en tu servidor.
Por otra parte te comento que lo que puedes hacer para tu solicitud, es un stored procedure que contenga las 150 llamadas a tus jobs utilizando la ejecución a los mismos mediante sp_start_job.
Podras encontrar información adicional sobre éste procedimiento almacenado en:
Microsoft MSDN
Espero te sea útil la información, de todas maneras puedes agregarme al MSN para realizar cualquier consulta.
November 10, 2008 at 4:23 pm. Permalink.