Los síntomas de recibir el siguiente error al intentar ejecutar informes creados en CRM con el asistente ó utilizando MSCRM_FetchDataSource:
En el servidor de SSRS: Your browser does not support scripts or has been configured not to allow scripts. En las máquinas clientes: An error occurred during client rendering. An error has occurred during report processing. Cannot create a connection to data source ‘CRM’. For more information about this error navigate to the report server on the local server machine, or enable remote errors. En CRM: Reporting Error The report cannot be displayed. (rsProcessingAborted)
En el servidor de SSRS: Your browser does not support scripts or has been configured not to allow scripts. En las máquinas clientes: An error occurred during client rendering. An error has occurred during report processing. Cannot create a connection to data source ‘CRM’. For more information about this error navigate to the report server on the local server machine, or enable remote errors. En CRM:
Reporting Error The report cannot be displayed. (rsProcessingAborted)
Pueden tener las siguientes causas:
1. SPN's no configurados 2. Falta de permisos de la cuenta de servicio de SSRS Service en el AD y en SQL 3. Site de CRM ApplicationHost.config no configurado para utilizar las credenciales de Windows Authentication del AppPoolCredentials
Prueba las alguna de las siguientes alternativas para solucionarlo:
1. Configurar los SPNs en el servidor especificado:
Servidor CRM SETSPN -a HTTP/CrmServerName Domain\CRMAppPool SETSPN -a HTTP/CrmServerName.Domain.com Domain\CRMAppPool Servidor SSRS/SQL Server: SETSPN -a HTTP/SsrsServerName Domain\SRSAppPool SETSPN -a HTTP/SsrsServerName.Domain.com Domain\SRSAppPool Para SQL: SETSPN -a MSSQLSvc/SqlServerName:1433 Domain\SQLServerSvcAcct SETSPN -a MSSQLSvc/SqlServerName.Domain.com:1433 Domain\SQLServerSvcAcct
2. Configurar los permisos de la cuenta de servicio de SSRS Service en el AD y modificar los permisos del grupo SQLAccessGroup en SQL como dice el artículo:
Error message when you run a report in Microsoft Dynamics CRM 4.0: "Reporting Error. The report cannot be displayed" http://support.microsoft.com/kb/946585 Sección: Complete the following steps if SQL Reporting Services is running as a domain user account
3. Añadir/cambiar la siguiente sección el fichero ApplicationHost.config del site de CRM Site en un editor de texto . (%windir%\system32\inetsrv\config\. Para todos los ficheros bajo la ruta del Default Web Site)
Poner el elemento WindowsAuthentication del atributo useAppPoolCredentials a true.
Por ejemplo: <system.webServer> <security> <authentication> <windowsAuthentication enabled="true" useAppPoolCredentials="true" /> </authentication> </security> </system.webServer>
Por ejemplo:
<system.webServer>
<security>
<authentication>
<windowsAuthentication enabled="true" useAppPoolCredentials="true" />
</authentication>
</security>
</system.webServer>
Maria Esteban
Ingeniero de Soporte de Reporting Services
Supongamos que nos encontramos en la siguiente situación:
En nuestro entorno tenemos montado Log shipping. Estamos utilizando logins de SQL Server, por lo que podemos tener usuarios huérfanos.
Queremos corregir este problema, pero no queremos romper el log shipping. ¿Qué podemos hacer?
Primero, vamos a entender que es un usuario de base de datos, que es un login, como se genera un usuario huérfano, y cuál es la relación entre un usuario de BD y un login:
¿Qué es un login?
Un login es una entidad que accede a la instancia de SQL Server. Esto puede ser un usuario de dominio, un usuario local del sistema, o un usuario de SQL Server. Con esto, podremos entrar a nivel de instancia, aunque no necesariamente a ninguna BD que este dentro de esta instancia.
Para acceder a una BD, tendremos que ser parte de alguno de los roles que otorgan acceso a las BD, o bien tener un usuario de BD mapeado a nuestro login.
¿Qué es un usuario de BD?
Un usuario de BD es la entidad que trabajara a nivel de BD, que puede tener ciertos privilegios a ciertos objetos dentro de esta misma BD.
¿Cuál es la posible relación entre un usuario de BD y un login?
Cuando se relacionan login y usuario, lo hacen a través de un identificador único, el SID. Este SID puede ser generado a nivel de dominio, a nivel de máquina, o bien a nivel de instancia.
Podréis encontrar más información en la siguiente URL:
http://msdn.microsoft.com/es-es/library/ms181127.aspx
Una vez visto esto, vamos a comprobar si tenemos usuarios huérfanos entre las instancias que trabajan en el logshipping:
Primero, comprobamos que en la instancia principal, nuestro Login “Orphaned”, tiene mapeado el usuario de BD:
Y comprobamos que el SID que une al usuario de BD “test”, y al login “Orphaned” es el mismo:
Por lo que, debido a cómo funciona “Log Shipping”, en la BD secundaria, tendremos este mismo SID asociado a nuestro usuario de BD, pero, nuestro login tendrá un diferente SID:
Es decir, que si rompemos el logshipping, veremos que nuestro login “Orphaned” no tendrá acceso a la BD “LogShipping_test”.
Si intento entrar con el login “Orphaned” dentro de la BD recién recuperada, recibiré el siguiente error:
Posibles soluciones para no romper el LogShipping:
Crear el login en la instancia secundaria con el mismo SID que la primaria, añadiendo la cláusula “SID”, y poniendo el mismo SID que el login de la instancia primaria:
En esta pantalla podemos observar que el login “Orphaned” ya tiene acceso a nuestra BD.
Esto es muy útil si, por cualquier razón, no podemos modificar el usuario de BD. Aunque, al borrar el login, cuando lo creemos, tendremos que darle todos los permisos que tuviese antes a nivel de instancia, y corregir cualquier otro mapeo de usuario que tenga.
Si pudiéramos modificar la BD, podremos lanzar el siguiente comando:
USE <database_name>;
GO
sp_change_users_login @Action='update_one', @UserNamePattern='<database_user>',
@LoginName='<login_name>';
Un poco mas de información:
http://msdn.microsoft.com/es-es/library/ms175475(v=sql.105).aspx
Moisés Romero Senosiain – Microsoft Customer Support Services
INTRODUCCION.-
Muchas veces nos hemos encontrado cuando desarrollamos procedimientos almacenados la necesidad de poder crear una versión de uno previamente creado.
A la hora de versionar un procedimiento almacenado nos encontramos con diferentes problemas, como por ejemplo:
PEQUEÑO TRUCO.-
Vamos a establecer un ejemplo, de cómo, SQL SERVER puede ayudarnos a organizarlos y cómo puede a la hora de crear el script sólo ver un procedimiento almacenado con sus diferentes versiones.
Lo primero vamos a crear un procedimiento almacenado simple:
CREATE PROCEDURE [dbo].[spVersion] AS BEGIN SELECT 'v1' END
Si ejecutamos el procedimiento almacenado, por ejemplo, EXEC spVersion obtenemos el valor v1.
Ahora crearemos otro procedimiento con el mismo nombre pero esta vez vamos a añadir al nombre el signo ; y un número de versión, por ejemplo, el (Inicialmente la versión 1 ya está reservada para la primera definición del procedimiento ).
CREATE PROCEDURE [dbo].[spVersion];2 AS BEGIN SET NOCOUNT ON;
SELECT 'v2' END
Si ejecutamos el procedimiento EXEC spVersion volvemos a obtener el valor ‘v1’ y si ejecutamos el procedimiento EXEC spVersion;2 obtenemos el valor ‘v2’.
Si abrimos el SQL SERVER Management Studio y expandimos los procedimientos almacenados, vemos que sólo existe un procedimiento almacenado.
Y si accedemos a su definición veremos el siguiente resultado.
Lo cual nos permite ir realizando los diferentes versionados del procedimiento almacenado.
José Manuel Jurado Diaz.
Ingeniero de Soporte de SQL SERVER
Voy a ser sincero. Las primeras bases de datos con las que trabaje fueron de Oracle. Desde la versión 8i en adelante.
Comencé a trabajar con SQL Server hace ya unos años, y lo primero que eche en falta eran las vistas dinámicas, no porque no existieran, sino porque no encontré una referencia rápida que me dijera, por ejemplo, que equivalente tenemos de la v$session.
Intentare, durante las próximas entregas, mostrar las diferencias entre estos dos grandes motores, y poder aportar toda la información necesaria para tener una “piedra rosetta”, y que el cambio de tecnología de un DBA desde Oracle a SQL Server sea lo menos traumático posible, que cosas podemos mantener, y que no podemos. Que existe, y que no.
En este caso, me basare en Oracle 10g R2 y SQL Server 2008 R2.
Sin más, comenzamos:
En esta ocasión, vamos a hablar de algunas de las vistas dinámicas que suelen usarse más de Oracle, y la opción mas parecida en SQL Server
Oracle Views
SQL Server equivalent
v$session
sys.sysprocesses
v$process
sys.dm_exec_connections
sys.dm_exec_sessions
sys.dm_exec_requests
v$session_wait
sys.dm_os_waiting_tasks
v$sql
Para estas vistas, tendremos que realizar alguna de las siguientes consultas:
v$sqltext
select * from sys.dm_exec_query_stats cross apply sys.dm_exec_sql_text(plan_handle)
v$sqlarea
Select * from sys.dm_exec_cached_plans CROSS APPLY sys.dm_exec_query_plan(plan_handle);
select * from sys.dm_exec_query_stats CROSS APPLY sys.dm_exec_query_plan(plan_handle) cross apply sys.dm_exec_sql_text(plan_handle)
v$lock
Algunos enlaces útiles:
Link de Oracle
http://download.oracle.com/docs/cd/B19306_01/server.102/b14237/dynviews_2088.htm#sthref2731
http://download.oracle.com/docs/cd/B19306_01/server.102/b14237/dynviews_2022.htm#sthref2643
http://download.oracle.com/docs/cd/B19306_01/server.102/b14237/dynviews_2094.htm#sthref2738
http://download.oracle.com/docs/cd/B19306_01/server.102/b14237/dynviews_2113.htm#sthref2757
http://download.oracle.com/docs/cd/B19306_01/server.102/b14237/dynviews_2132.htm#sthref2776
http://download.oracle.com/docs/cd/B19306_01/server.102/b14237/dynviews_2129.htm#sthref2773
http://download.oracle.com/docs/cd/B19306_01/server.102/b14237/dynviews_1147.htm#sthref2582
SQL Server view
Link de Microsoft
http://msdn.microsoft.com/es-es/library/ms179881.aspx
http://msdn.microsoft.com/es-es/library/ms181509.aspx
http://msdn.microsoft.com/es-es/library/ms176013.aspx
http://msdn.microsoft.com/es-es/library/ms177648.aspx
http://msdn.microsoft.com/es-es/library/ms188743.aspx
sys.dm_exec_query_stats
http://msdn.microsoft.com/en-us/library/ms189741.aspx
sys.dm_exec_sql_text
http://msdn.microsoft.com/en-us/library/ms181929.aspx
sys.dm_exec_query_plan
http://msdn.microsoft.com/en-us/library/ms189747.aspx
sys.dm_exec_cached_plans
http://msdn.microsoft.com/en-us/library/ms187404.aspx
1. ¿Esta soportada la instalación de Reporting Services en clúster?
Del siguiente artículo puedes ver que la instalación en clúster está soportada sólo para las bases de datos de SQL server (ReportServer y ReportServerTempDB) pero no para el servicio Web.
Hosting a Report Server Database in a SQL Server Failover Cluster http://msdn.microsoft.com/en-us/library/bb630402.aspx (en Español) Hospedar una base de datos del servidor de informes en un clúster de conmutación por error de SQL Server http://msdn.microsoft.com/es-es/library/bb630402.aspx SQL Server provides failover clustering support so that you can use multiple disks for one or more SQL Server instances. Failover clustering is supported only for the report server database; you cannot run the Report Server service as part of a failover cluster. To host a report server database on a SQL Server failover cluster, the cluster must already be installed and configured. You can then select the failover cluster as the server name when you create the report server database in the Database Setup page of the Reporting Services Configuration tool. Although the Report Server service cannot participate in a failover cluster, you can install Reporting Services on a computer that has a SQL Server failover cluster installed. The report server runs independently of the failover cluster. If you install a report server on a computer that is part of a SQL Server failover instance, you are not required to use the failover cluster for the report server database; you can use a different SQL Server instance to host the database.
Hosting a Report Server Database in a SQL Server Failover Cluster
http://msdn.microsoft.com/en-us/library/bb630402.aspx
(en Español)
Hospedar una base de datos del servidor de informes en un clúster de conmutación por error de SQL Server
http://msdn.microsoft.com/es-es/library/bb630402.aspx
SQL Server provides failover clustering support so that you can use multiple disks for one or more SQL Server instances. Failover clustering is supported only for the report server database; you cannot run the Report Server service as part of a failover cluster.
To host a report server database on a SQL Server failover cluster, the cluster must already be installed and configured. You can then select the failover cluster as the server name when you create the report server database in the Database Setup page of the Reporting Services Configuration tool.
Although the Report Server service cannot participate in a failover cluster, you can install Reporting Services on a computer that has a SQL Server failover cluster installed. The report server runs independently of the failover cluster. If you install a report server on a computer that is part of a SQL Server failover instance, you are not required to use the failover cluster for the report server database; you can use a different SQL Server instance to host the database.
2. Pasos a seguir para instalar Reporting Services con las bases de datos en clúster:
1. Primero instalamos Reporting Services en una máquina (diferente al clúster, o en un nodo del clúster si se prefiere) eligiendo la opción “Install but do not configure the server” durante las opciones de instalación del asistente.
2. Una vez terminada la instalación, habrá que configurar Reporting Services utilizando el “Reporting Services Configuration Manager”
Los siguientes artículos muestran los pasos a seguir para configurar las urls y la base de datos
How to: Configure a URL (Reporting Services Configuration) http://msdn.microsoft.com/en-us/library/bb630447.aspx How to: Create a Report Server Database (Reporting Services Configuration) http://msdn.microsoft.com/en-us/library/ms157300.aspx
How to: Configure a URL (Reporting Services Configuration)
http://msdn.microsoft.com/en-us/library/bb630447.aspx
How to: Create a Report Server Database (Reporting Services Configuration)
http://msdn.microsoft.com/en-us/library/ms157300.aspx
los enlaces en español son:
Cómo configurar una dirección URL (Configuración de Reporting Services) http://msdn.microsoft.com/es-es/library/bb630447.aspx Cómo crear una base de datos de servidor de informes (configuración de Reporting Services) http://msdn.microsoft.com/es-es/library/ms157300.aspx
Cómo configurar una dirección URL (Configuración de Reporting Services)
http://msdn.microsoft.com/es-es/library/bb630447.aspx
Cómo crear una base de datos de servidor de informes (configuración de Reporting Services)
http://msdn.microsoft.com/es-es/library/ms157300.aspx
En este post vamos a introducir el manejo a bajo nivel que hace SQL de las tareas que le piden los usuarios, como algunos sabréis SQL tiene su proprio “sistema operativo” que se encarga del scheduling, memoria etcetera, este componente recibe el original nombre de SQLOS. En este post nos centraremos en la parte de scheduling, para apoyar las explicaciones vamos a usar las vistas dinámicas que proporciona SQL Server a partir de su versión 2005 (http://msdn.microsoft.com/en-us/library/ms188754.aspx).
Los nodos pertenecen más a la parte de memoria, pero juegan un papel muy importante a la hora de crear otros los schedulers, SQLOS crea un nodo por cada nodo NUMA (http://en.wikipedia.org/wiki/Non-Uniform_Memory_Access) que tenga la máquina más un nodo adicional para la conexión dedicada de administración (DAC), si nuestra máquina es UMA (http://en.wikipedia.org/wiki/Uniform_Memory_Access) se crearan dos nodos uno para uso normal y otro para el DAC.
Para ver los nodos que ha creado nuestro SQLOS podemos recurrir a la vista: sys.dm_os_nodes (http://msdn.microsoft.com/en-us/library/bb510628(v=sql.100).aspx), en mi máquina podemos ver que solo crea dos nodos, uno para uso normal y otro para uso del DAC.
El id de los nodos es consecutivo excepto el DAC que para 32bits es 32 y para 64bits es 64. En el estado podemos ver como todos están ONLINE (normalmente deben estar así), luego su dirección de memoria del nodo que para tareas de depuración de SQLOS viene muy bien y la máscara de afinidad del nodo, en sistemas con un solo socket veremos que la afinidad es 255, en sistemas con varios sockets veremos que la afinidad se ajusta al numero de cores de cada socket.
Para procesadores X64 indicar que todos los procesadores con controladora interna de memoria son procesadores NUMA esto incluye todos los procesadores AMD (Opteron, Athlon X64 y posteriores) y los procesadores de intel basados en Nehalem (http://en.wikipedia.org/wiki/Nehalem_(microarchitecture)) y posteriores (Sandy Bridge, Ivy Bridge…)
La tecnología IA64 (Itanium) es NUMA.
Para estudiar los diferentes componentes vamos a ir de abajo a arriba, en la parte más baja entran los schedulers, este componente es el encargado de realizar el scheduling entre las diferentes tareas tanto de usuario como de sistema. SQL Server crea un scheduler de usuario por cada CPU lógica que tenga el sistema, y algunos más para tareas internas.
Para ver los schedulers del sistema tenemos la vista dinámica sys.dm_os_schedulers (http://msdn.microsoft.com/en-us/library/ms177526.aspx). La salida de esta vista en mi máquina:
Como con los nodos tenemos la dirección de memoria del Scheduler así como a que nodo pertenece, mi máquina es un i7 (Nehalem) de un solo socket y cuatro cores, como tengo Hyper-Threading (HT) activado el número de cores lógicos es ocho, por tanto SQLOS crea ocho schedulers, uno por core lógico, para tareas de usuario (status = VISIBLE), adicionalmente crea 4 schedulers para tareas administrativas y uno para el DAC. La columna is_idle nos indica si el scheduler está ejecutando algo [0] o está sin hacer nada [1], Failed_to_create_worker es una columna interesante ya que nos indica si el scheduler a fallado en crear un worker [1] en algun momento, si es así podemos encontrarnos ante problemas de presión de memoria, o un valor de worker threads (http://msdn.microsoft.com/en-us/library/ms187024.aspx) muy alto si hemos establecido esta opción a mano, no recomendable.
Indicar que en máquinas dedicadas exclusivamente a SQL puede ser buena opción desactivar Hyper-Threading a nivel de BIOS esto provocará que el número de cores lógicos corresponda con el número de cores físico haciendo que SQL cree un scheduler por core físico, reduciendo posibles esperas causadas por Hyper-Threading. Para determinar el impacto en el rendimiento se recomienda probar una carga de uso normal en un entorno de preproducción tanto con HT activado como con HT desactivado.
Cada scheduler tiene un número n de workers, el número global de workers en toda la instancia no puede sobrepasar el valor ‘max worker threads’. Cuando llega un nuevo trabajo el scheduler busca un worker libre si no existe ninguno intenta crear uno nuevo y asignarle la tarea. Para poder ver los workers del sistema podemos usar la vista: sys.dm_os_workers (http://msdn.microsoft.com/en-us/library/ms178626.aspx)
Como siempre la primera columna (worker_address) es la dirección de memoria del objeto, is_preemtive lo veremos más adelante, exception_num es el último numero de error que se ha producido en ese worker, en la captura podemos ver un 1222 que significa lock timeout. en state podemos ver si el worker está corriendo o suspendido, en last_wait_type podemos ver por que estaba esperando en la última espera que hizo el thread, posteriormente tenemos las direcciones de memoria de: task que está ejecutando el worker, el thread de windows usado para ejecutar la tarea y el scheduler al cual pertenece este thread.
Esto representa una tarea, o subtarea de un usuario, cuando el engine decide paralelizar una query creará subtasks que se asignaran a workers libres para completar la query original. La vista que nos proporciona esta información es: sys.dm_os_tasks (http://msdn.microsoft.com/en-us/library/ms174963.aspx). En mi máquina
Aquí podemos ver la dirección de la tarea, el estado en el que está la tarea, el scheduler en el que está ejecutando la tarea, el número de sesión de usuario que ha lanzado la tarea y la dirección del worker que está ejecutando la tarea.
Para empezar vamos a recordar las relaciones entre elementos.
SQLOS tiene tantos nodos como nodos NUMA tenga la máquina,
SQLOS tiene tantos schedulers como cores lógicos reporte windows.
Cada scheduler tiene n workers y un worker solo puede pertenecer a un scheduler.
Cada worker tiene uno y solo un thread.
Cada worker tiene una y solo una tarea. Una vez completada la tarea el worker puede tener una tarea nueva.
Una tarea solo puede pertenecer a un worker.
Llega una nueva tarea, ¿ahora que hago?
Cuando llega una nueva tarea se le asigna un scheduler, este scheduler busca entre sus workers si hay algun que no esté haciendo nada, si es así se asigna la tarea al worker y se coloca en la lista de workers que pueden ser ejecutado. Si no hay ningun worker libre se intenta crear uno nuevo. Cuando al worker le toque ejecutar se le dara el procesador y es el worker el que debe decidir cuanto tiempo permanece en el. ¡Multitarea colaborativa!
Multitarea colaborativa en SQLOS
Como hemos visto es decisión del worker cuando devuelve el control al scheduler para que pueda ejecutar otro worker. Todos las tareas internas de SQL Server se controlan para no estar mucho tiempo ocupando el scheduler y que la ejecución sea fluida, esto se hace por rendimiento ya que simplifica enormemente el scheduler.
Bien, pero y si una tarea tarda mucho
Para estos casos existe una monitorización de los schedulers, si un scheduler no ha hecho un cambio de contexto en cierto tiempo se genera un volcado de memoria del scheduler afectado, elimina la task y marca el worker como libre.
Seguramente muchos de vosotros os habréis encontrado con un volcado cuya descripción es “Non-Yielding Scheduler”, este tipo de volcados significa que un worker no ha retornado el control al scheduler en un tiempo adecuado, por tanto la tarea es terminada para no afectar a las restantes.
Que pasa cuando es necesario hacer una llamada a Windows.
Como muchos sabréis la multitarea de Windows es preemtiva, esto quiere decir que es el sistema operativo el que quita la ejecución a los procesos y se los asigna a otros procesos sin que el proceso afectado se entere de nada. Que pasa si tengo que hacer una llamada a Windows, ODBC, … cuya multitarea es preemtiva. En ese caso se marca el flag is_preemtive en el worker para evitar que el monitor de schedulers genere un volcado y mate el proceso en caso de que este tarde mucho en responder, como puede ser un acceso a disco, registro....
Pablo Gavela López – Microsoft Customer Support Services
Hemos observado en algunos casos en determinados proyectos que usan SQL SERVER se implementan campos de tipo TEXT para almacenar datos de XML.
Desde la versión de SQL SERVER 2005 existe la posibilidad o bien de leer archivos de XML y poder manipularlos o almacenarlos como un campo de XML dentro de una tabla de SQL SERVER.
Nuestro pequeño post girará en entorno al nuevo tipo de dato XML que nos permite realizar operaciones desde la lectura, indexación por path, valores y tags así como poder actualizar sólo la parte del XML sin tener que sustituir todo el contenido del campo, ahorrando muchas de las operativas de manipulación por parte de desarrollador.
Con el fin de crear una pequeña guía de trabajo del uso de este nuevo tipo de datos, os mostraremos varios detalles del mismo.
Lo primero que vamos a realizar será crear una tabla que llamaremos EjemploXML que contendrá dos campos:
Una vez ya tenemos la tabla vamos a realizar operaciones básicas como:
Insertar varios registros pudiendo utilizar dos formas:
DECLARE @xml AS XML
SET @xml = '<Clientes> <Cliente> <ClienteID>2005</ClienteID> <Nombre>25</Nombre> </Cliente> </Clientes>’
INSERT INTO EjemploXML(XML_Data) Values (@xml)
Una vez hemos insertado estos datos, podemos ya realizar nuestras propias sentencias de SQL. Por un lado:
SELECT * FROM EjemplosXML where xml_data.exist('/Clientes/Cliente/ClienteID[text()=10]')=1
Comentar dos casos en relación a las búsquedas:
Lo primero crearemos un índice primario como cualquier otro que podamos crear: CREATE Primary XML INDEX xml_idx_1 ON EjemploXML(XML_Data) Con este índice indicaremos a SQL SERVER que este campo XML tiene un índice.
CREATE XML INDEX xml_idx_1_a ON EjemploXML(XML_Data) USING XML INDEX xml_idx_1 FOR PATH CREATE XML INDEX xml_idx_1_v ON EjemploXML(XML_Data) USING XML INDEX xml_idx_1 FOR value CREATE XML INDEX xml_idx_1_p ON EjemploXML(XML_Data) USING XML INDEX xml_idx_1 FOR property
CREATE XML INDEX xml_idx_1_a ON EjemploXML(XML_Data) USING XML INDEX xml_idx_1 FOR PATH
CREATE XML INDEX xml_idx_1_v ON EjemploXML(XML_Data) USING XML INDEX xml_idx_1 FOR value
CREATE XML INDEX xml_idx_1_p ON EjemploXML(XML_Data) USING XML INDEX xml_idx_1 FOR property
Finalmente, nos queda la posibilidad de bien, borrar o actualizar los datos de un XML. Para ello tenemos los siguientes métodos explicados en la siguiente URL: http://msdn.microsoft.com/es-es/library/ms177454.aspx
Comentar por último que los nuevos tipos de datos de XML no sólo pueden usarse como campos de tablas, sino, que tienen otras funcionalidades como:
A parte, otras de las ventajas de que disponemos, es que podemos aplicar un constraint para evitar que un XML no esté bien formado, es decir, validar esquemas de XML o bien podemos añadir el contenido directamente del XML a través del comando BULK INSERT
Hoy vamos a hablar de cómo recrear un grupo de cluster de SQL Server bajo Windows Server 2008 cuando sea eliminado por error.
Si lo que quieres es montarlo por primera vez, es necesario seguir este link, http://msdn.microsoft.com/en-us/library/ms179530.aspx , el cual nos ira guiando desde la planificación, hasta la consecución de nuestro objetivo. Siguiendo este link, además de crear el grupo de cluster, se deja configurado automáticamente el grupo de cluster y el servicio de SQL.
Supongamos esta situación, Mike, nuestro DBA senior, le pide a Paul, un recién contratado DBA, que modifique la configuración del cluster. Paul borra, accidentalmente, el grupo del cluster.
¿Como puede Mike recuperar nuestro grupo perdido de cluster?
Primero, Mike se conectara a la consola de cluster del nodo activo.
Dentro de “Services and Applications”, tendremos que generar nuestro contenedor. Botón derecho sobre “Services and applications” > “More Actions” > “Create Empty Service or application”
Vamos a ponerle un nombre que nos diga algo, por ejemplo “test_moises”
Como vemos, esta vacío, así que vamos a añadir todos nuestros resources…
Primero, para SQL Server, debemos añadir un “Client Access Point”, donde pondremos nuestro “Virtual name”, y nuestro “Virtual Address”, y la subred a la que va a escuchar, en caso de que haya varias...
Bien, pues ya está montado, ahora añadiremos los discos que utilizaremos para SQL Server, para ello pulsaremos sobre “Add storage”, y seleccionaremos los discos que necesitemos.
Perfecto, y ahora a por nuestro objetivo real, el resource de SQL Server.
Pulsamos sobre “Add a resource” > “More resources” > “Add Sql Server”
Ojo, porque todavía no está configurado. Botón derecho sobre el recién estrenado SQL Server resource, y propiedades. En la pestaña “General”, podremos cambiar el nombre del recurso. Esto es solo para que nosotros nos acordemos, el cluster trabaja por debajo con los GUID.
En la pestaña “Dependencies”, añadiremos las dependencias necesarias, en este caso, SQL Server, VirtualName y discos:
En la pestaña “Properties”, añadiremos el value del “VirtualServerName” y del “InstanceName”. (ejemplo grafico de que es el VirtualServerName y el InstanceName)
Por último, el SQL Server Agent. Pulsamos sobre “Add a resource” > “More resources” > “Add Sql Server Agent”.
La dependencia que pondremos es el resource de “SQL Server”, y en la pestaña “Properties”, configuramos, al igual que en el caso del resource de “SQL Server”, los values del “VirtualServerName” y del “InstanceName”.
Si tuviésemos algún problema con las propiedades, podemos guiarnos por este kb: http://support.microsoft.com/kb/810056
*Cuidado con este link, porque la traducción automática en castellano también modifica los valores del registro a editar, que realmente no se deben cambiar...
Pero en registro veremos:
Mike volverá a tener su cluster funcionando, y los usuarios no han tenido perdida de servicio.
Moisés Romero Senosiain
Ingeniero de soporte de SQL Server
Acabamos de comprar un flamante nuevo servidor, 24 cores, 128GB de RAM, discos SSD en RAID 0… Instalamos SQL Server, 64 bits por supuesto, activamos Lock Pages in Memory (http://msdn.microsoft.com/en-us/library/ms190730.aspx) para que SQL no sea paginado fuera de RAM. Y para deleitarnos con nuestra obra cogemos contadores de carga de CPU, bloqueos, memoria…. Y ahí empieza el problema, ¡dónde está mi memoria!
La memoria puede estar “perdida”, entre comillas ya que la memoria está siendo realmente usada, por diversos motivos, para los ejemplos usaré mi modesto Xeon de 4 cores y 12GB de RAM. Para capturar el uso de RAM física se usara la herramienta RAMMap de Mark Russinovich y Bryce Cogswell que podemos bajar de sysinternals: http://technet.microsoft.com/en-us/sysinternals/ff700229
1 – Task Manager y lock pages in memory.
Para realizar las pruebas se hace una SELECT de 10.000.000 de registros. Si usamos task manager para comprobar el uso de RAM de SQL podemos llevarnos una sorpresa. Esta memoria es el Working Set (la memoria física usada actualmente por SQL Server). Apenas 116MB de uso, esto no cuadra con una base de datos que mueve cientos, miles o millones de datos por segundo por tanto algo debe estar mal. Si vamos a Management Studio y ejecutamos DBCC MEMORYSTATUS SQL nos proporcionará un resumen del uso de RAM que para nada coincidirá con lo que nos indica el task manager. Memory Manager KB ---------------------------------------- ----------- VM Reserved 19015912 VM Committed 119148 Locked Pages Allocated 747776 Reserved Memory 1024 Reserved Memory In Use 0 Vamos a fijarnos únicamente en los valores VM Committed y Locked Pages Allocated (AWE Allocated en SQL Server 2005). VM Commited: Éste valor es el tamaño de memoria virtual (del proceso) que actualmente está siendo manejado por SQL Server, esta memoria puede ser paginada, el working set es un sub conjunto de esta memoria, por tanto los valores obtenidos tienen lógica. Locked Pages Allocated (AWE allocated en SQL Server 2005): Este valor indica la cantidad de RAM física bloqueada en memoria por SQL Server y que no se puede ser paginada. Por tanto esta valor más el working set nos darán una idea aproximada del tamaño de la RAM física consumida por SQL Server (En este caso 118972KB + 747776KB, unos 846MB)
Para realizar las pruebas se hace una SELECT de 10.000.000 de registros.
Si usamos task manager para comprobar el uso de RAM de SQL podemos llevarnos una sorpresa.
Esta memoria es el Working Set (la memoria física usada actualmente por SQL Server). Apenas 116MB de uso, esto no cuadra con una base de datos que mueve cientos, miles o millones de datos por segundo por tanto algo debe estar mal.
Si vamos a Management Studio y ejecutamos
DBCC MEMORYSTATUS
SQL nos proporcionará un resumen del uso de RAM que para nada coincidirá con lo que nos indica el task manager.
Memory Manager KB ---------------------------------------- ----------- VM Reserved 19015912 VM Committed 119148 Locked Pages Allocated 747776 Reserved Memory 1024 Reserved Memory In Use 0
Vamos a fijarnos únicamente en los valores VM Committed y Locked Pages Allocated (AWE Allocated en SQL Server 2005).
VM Commited: Éste valor es el tamaño de memoria virtual (del proceso) que actualmente está siendo manejado por SQL Server, esta memoria puede ser paginada, el working set es un sub conjunto de esta memoria, por tanto los valores obtenidos tienen lógica.
Locked Pages Allocated (AWE allocated en SQL Server 2005): Este valor indica la cantidad de RAM física bloqueada en memoria por SQL Server y que no se puede ser paginada. Por tanto esta valor más el working set nos darán una idea aproximada del tamaño de la RAM física consumida por SQL Server (En este caso 118972KB + 747776KB, unos 846MB)
La explicación de este comportamiento es que al activar Lock Pages in Memory en x64 se está haciendo uso de algo muy conocido por la gente que ya ha trabajado con SQL en x86, me refiero a: Address Windowing Extensions (AWE) http://msdn.microsoft.com/en-us/library/aa366527(v=vs.85).aspx. Esta API sigue estando presente en las ediciones de 64 bits de Windows debido a su utilidad ya que es la única forma que tiene un programa de usuario de bloquear RAM física para su uso. Para los programadores que tenga curiosidad les recomiendo que vean la entrada de msdn VirtualAlloc(http://msdn.microsoft.com/en-us/library/aa366887(v=vs.85).aspx) con el flag MEM_PHYSICAL. Esta memoria está fuera de la memoria virtual del proceso y por tanto no aparece en el Working Set del Task Manager. A continuación lanzamos RAMMap para ver en que se está usando la RAM física. Como podemos ver el valor consumido por AWE coincide exactamente con el de Lock Pages Allocated, 744776KB. Hemos encontrado nuestra memoria.
La explicación de este comportamiento es que al activar Lock Pages in Memory en x64 se está haciendo uso de algo muy conocido por la gente que ya ha trabajado con SQL en x86, me refiero a: Address Windowing Extensions (AWE) http://msdn.microsoft.com/en-us/library/aa366527(v=vs.85).aspx. Esta API sigue estando presente en las ediciones de 64 bits de Windows debido a su utilidad ya que es la única forma que tiene un programa de usuario de bloquear RAM física para su uso. Para los programadores que tenga curiosidad les recomiendo que vean la entrada de msdn VirtualAlloc(http://msdn.microsoft.com/en-us/library/aa366887(v=vs.85).aspx) con el flag MEM_PHYSICAL. Esta memoria está fuera de la memoria virtual del proceso y por tanto no aparece en el Working Set del Task Manager.
A continuación lanzamos RAMMap para ver en que se está usando la RAM física.
Como podemos ver el valor consumido por AWE coincide exactamente con el de Lock Pages Allocated, 744776KB.
Hemos encontrado nuestra memoria.
2 – Lock Pages Allocated no coincide con el valor de AWE. Presentamos “Large Page Extensions”
Ahora realizamos la misma prueba con una máquina i7 de 4 cores y 16GB de RAM. Arrancamos SQL Server, lanzamos Management Studio, hacemos una SELECT de 10.000.000 de registros y… Un working set de 131468KB. Mas o menos como antes. Ahora veamos la salida de DBCC MEMORYSTATUS Memory Manager KB ---------------------------------------- ----------- VM Reserved 23200928 VM Committed 174292 Locked Pages Allocated 682048 Reserved Memory 1024 Reserved Memory In Use 0 Parece que todo está mas o menos como en el ejemplo anterior, 174292KB para VM Commited y 682048KB para Lock Pages Allocated. Pero cuando vamos a RAMmap vemos esto: Y… oops. AWE está consumiendo 731200de RAM, lo que nos deja con la siguiente pregunta ¿Donde están mis 48MB? La respuesta está en “Large Page Extension” (http://msdn.microsoft.com/en-us/library/aa366720.aspx). Basicamente SQL Server 64bits si se encuentra más de 8GB libres al arrancar usará parte de la memoria para "Large Pages” este tipo de páginas de memoria proporcionan un aumento de rendimiento para grandes cargas de datos y se reserva usando el API de AWE, por tanto RAMMap la muestra como memoria AWE, mas información (http://blogs.msdn.com/b/psssql/archive/2009/06/05/sql-server-and-large-pages-explained.aspx). Si en vez de utilizar DBCC MEMORYSTATUS usamos DMV’s podremos ver este tipo de reservas de memoria. Usaremos la siguinte query (Esta query solo funciona en SQL Server 2008 y superiores): SELECT large_page_allocations_kb, locked_page_allocations_kb FROM sys.dm_os_process_memory En mi caso el resultado es el siguiente: Lo que nos dice que 682048KB están en Locked Pages y 49152KB están en Large Pages, lo que nos suma los 731200KB. En caso de SQL Server 2005 no hay ninguna query con la que podamos consultar este tipo de memoria, con lo que tendremos que hacer un acto de fe. Notas sobre Large Pages: - Solo está disponible en Developer y Enterprise - Cuanto más RAM tenga el sistema más RAM se reserva para Large Pages. - Las Large Pages solo se activan si tenemos más de 8GB libres cuando arranca SQL Server. - Large Pages no está limitado por Max Server Memory. - Con mirar nuestro ERROLOG sabremos si están activas las Large Pages, se registrara lo siguiente: 2011-09-02 13:13:47.41 Server Large Page Extensions enabled. 2011-09-02 13:13:47.41 Server Large Page Granularity: 2097152 2011-09-02 13:13:47.41 Server Large Page Allocated: 32MB 2011-09-02 13:13:47.43 Server Using locked pages for buffer pool.
Ahora realizamos la misma prueba con una máquina i7 de 4 cores y 16GB de RAM. Arrancamos SQL Server, lanzamos Management Studio, hacemos una SELECT de 10.000.000 de registros y…
Un working set de 131468KB. Mas o menos como antes. Ahora veamos la salida de DBCC MEMORYSTATUS
Memory Manager KB ---------------------------------------- ----------- VM Reserved 23200928 VM Committed 174292 Locked Pages Allocated 682048 Reserved Memory 1024 Reserved Memory In Use 0
Parece que todo está mas o menos como en el ejemplo anterior, 174292KB para VM Commited y 682048KB para Lock Pages Allocated. Pero cuando vamos a RAMmap vemos esto:
Y… oops. AWE está consumiendo 731200de RAM, lo que nos deja con la siguiente pregunta ¿Donde están mis 48MB?
La respuesta está en “Large Page Extension” (http://msdn.microsoft.com/en-us/library/aa366720.aspx). Basicamente SQL Server 64bits si se encuentra más de 8GB libres al arrancar usará parte de la memoria para "Large Pages” este tipo de páginas de memoria proporcionan un aumento de rendimiento para grandes cargas de datos y se reserva usando el API de AWE, por tanto RAMMap la muestra como memoria AWE, mas información (http://blogs.msdn.com/b/psssql/archive/2009/06/05/sql-server-and-large-pages-explained.aspx). Si en vez de utilizar DBCC MEMORYSTATUS usamos DMV’s podremos ver este tipo de reservas de memoria. Usaremos la siguinte query (Esta query solo funciona en SQL Server 2008 y superiores):
SELECT large_page_allocations_kb, locked_page_allocations_kb FROM sys.dm_os_process_memory
En mi caso el resultado es el siguiente:
Lo que nos dice que 682048KB están en Locked Pages y 49152KB están en Large Pages, lo que nos suma los 731200KB. En caso de SQL Server 2005 no hay ninguna query con la que podamos consultar este tipo de memoria, con lo que tendremos que hacer un acto de fe.
Notas sobre Large Pages:
- Solo está disponible en Developer y Enterprise
- Cuanto más RAM tenga el sistema más RAM se reserva para Large Pages.
- Las Large Pages solo se activan si tenemos más de 8GB libres cuando arranca SQL Server.
- Large Pages no está limitado por Max Server Memory.
- Con mirar nuestro ERROLOG sabremos si están activas las Large Pages, se registrara lo siguiente:
2011-09-02 13:13:47.41 Server Large Page Extensions enabled. 2011-09-02 13:13:47.41 Server Large Page Granularity: 2097152 2011-09-02 13:13:47.41 Server Large Page Allocated: 32MB 2011-09-02 13:13:47.43 Server Using locked pages for buffer pool.
Continuamente llegan a nosotros casos de rendimiento en las que de una manera u otra están relacionadas con la gestión de los índices.
En muchos casos TSQL, Jobs, que tardan mucho o TSQL que antes no tardaban nada con pocos registros cada vez la base de datos invierte más tiempo en realizarlos.
En todos ellos, se observa un patrón común con un alto uso de CPU o los contadores de rendimiento de disco inusualmente elevados o bien muchos operativas de table scan.
En este post trataremos de identificar los aspectos relacionados con los índices en el que lo dividiremos en tres partes:
· Fragmentación de los índices, es decir, cada vez que se inserta/actualiza o se borran registros el impacto de cómo está alineado las páginas de datos de índices con los datos.
· Índices que SQL SERVER identifica que podrían ser necesarios crear y que creándolos provocarían un aumento considerable en la mejora del rendimiento del servidor.
· Cómo, cuándo y en qué porcentaje la base de datos están usando estos índices.
Para ello nos apoyaremos en unas vistas dinámicas muy interesantes que nos van a permitir conocer estos datos que tenemos habilitadas en SQL SERVER 2005 y 2008.
Fragmentación de los índices:
Para conocer qué es la fragmentación para ello visitemos la URL: http://technet.microsoft.com/es-es/library/ms189858.aspx
Para conocer cómo se detecta la fragmentación disponemos de dos opciones uno DBCC SHOWCONTIG que aportaba esta información en versiones anteriores o bien la nueva DMV que nos informa con muchos más detalles, el nivel de fragmentación de los índices. Para ello visitaremos la URL: http://technet.microsoft.com/es-es/library/ms188917.aspx
Dentro de la DMV ejecutaremos la siguiente query para observar la fragmentación de los índices:
select OBJECT_NAME([object_id]) as NombreTabla, *
from master.sys.dm_db_index_physical_stats(DB_ID('bbddusuario'),NULL,NULL,NULL,'DETAILED')
order by avg_fragmentation_in_percent desc
En este ejemplo, crearemos una tabla con 3 campos:
· IdElemento que será el campo Identidad y Primary key por defecto.
· Campo1 y Campo2 ambos de nvarchar(10)
Una vez creada la tabla creamos un nuevo índice seleccionado el campo Campo1 dejando la definición del índice de relleno ( fillfactor) por defecto.
Haremos inserciones y borrados masivos durante un tiempo y volveremos a ejecutar la query, obteniendo el siguiente resultado:
En la que podemos identificar la columna avg_fragmentation_in_percent que nos indica por cada tipo de índice el porcentaje de fragmentación. En algunos casos observamos que el porcentaje es muy alto.
Por ello, basta con realizar alguna actividad de reindexación ( reconstrucción ( rebuild ) o reorganización ( reorganize ) ) de los datos para obtener el siguiente resultado y mejorar sensiblemente el resultado de las operaciones de búsqueda. URL: http://msdn.microsoft.com/es-es/library/ms188917.aspx
Otro de las cosas que podemos observar en esta estadística son:
o El nivel de ocupación de cada una de las páginas ( columna avg_page_space_used_in_percent ) con lo cual podemos definir un fill factor o índice de relleno acorde y bajar la fragmentación. URL: http://msdn.microsoft.com/es-es/library/ms191005(v=sql.90).aspx
o La cantidad de registros usados en cada índice ( columna record_count ). En caso de que este índice tenga una cantidad de registros muy cercano a la cantidad de registros de la tabla ( select count(*) from , este índice podría no ser necesario por su nivel de cardianalidad ( número de registros diferentes único que forman el índice ). El motor de optimización de la base de datos podría no utilizar este índice ya que podría considerar que es mejor leer la tabla que usar el índice.
Índices que SQL SERVER identifica que mejorarían el rendimiento ( MISSING INDEXES )
Por otro lado, tenemos los índices que provocarían un aumento considerable en la mejora del rendimiento del servidor.
Para conocer los índices que sería necesarios crear, si ejecutamos la siguiente query podremos encontrar los índices que podría ser necesarios crear para mejorar el rendimiento. En la columna avg_user_impact se podría ver el % de performance. Debemos recordar que crear índices mejora el rendimiento pero obliga a que las escrituras puedan llevar más tiempo al actualizar los datos y que la información que obtenemos se inicializa después de cada reinicio de la instancia de SQL SERVER. URL: http://technet.microsoft.com/es-es/library/ms345434.aspx
SELECT
statement AS [database.scheme.table],
column_id , column_name, column_usage,
migs.user_seeks, migs.user_scans,
migs.last_user_seek, migs.avg_total_user_cost,
migs.avg_user_impact
FROM sys.dm_db_missing_index_details AS mid
CROSS APPLY sys.dm_db_missing_index_columns (mid.index_handle)
INNER JOIN sys.dm_db_missing_index_groups AS mig
ON mig.index_handle = mid.index_handle
INNER JOIN sys.dm_db_missing_index_group_stats AS migs
ON mig.index_group_handle=migs.group_handle
ORDER BY mig.index_group_handle, mig.index_handle, column_id
Siguiendo con nuestro ejemplo, vamos a realizar un par de consultas en nuestra tabla. Como recordamos nuestra tabla ( Table_1 ) contiene 3 campos, IdElemento como índice primario, Campo1 que está indexado y Campo2 que no está indexado.
Vamos a realizar un par de consultas sobre el campo2 al cercar de los 7 millones de registros que tenemos en la tabla table_1.
Select * from table_1 where campo2 = ‘juan’
Select * from table_1 where campo2 like ‘juan%’
Seguidamente, ejecutaremos la query de obtener los índices que SQL SERVER aconseja crear y obtenemos los siguientes datos.
Como podemos observar las primeras tres filas corresponde a la mejora del filtrado inicial de campo2 = ‘juan’ en las que SQL SERVER nos indica que podríamos mejorar nuestro rendimiento en un 99.91% si creamos un índice en el que Campo2 esté definido en el mismo e incluyamos como campos include del mismo a IdElemento y Campo1.
SQL SERVER recomienda el incluir los campos debido a la query SELECT * en la que se recogen todos los campos. Lógicamente, este índice es para este caso y posiblemente acotar los campos ( sustituir el * por los campos que necesitamos hará que quizás no sea necesario incluir estos campos.
Finalmente, podemos observar que las tres siguientes filas con un porcentaje de cerca del 69% para la query con la clausula LIKE.
INDICES QUE SQL SERVER NO USA EN NUESTRA BASE DE DATOS
Por último, para conocer los índices no usados, si ejecutamos la siguiente query
select i.name, * from sys.dm_db_index_usage_stats s
inner join sys.indexes i on i.object_id = s.object_id and i.index_id = s.index_id
where database_id = DB_ID()
podremos encontrar los índices que podría ser necesarios crear para mejorar la performance desde el último reinicio de la instancia de SQL SERVER. En la URL http://technet.microsoft.com/es-es/library/ms188755.aspx encontramos información sobre todas sus columnas.
Para ello creamos un índice llamado IX_Table_2 que lo formarán los campos campo1 y campo2 y estarán incluidos el campo de IdElemento.
Realizamos un par de consultas a la tabla incluyendo algunos de estos campos y volveremos a realizar la query para obtener la estadística de los índices.
Podemos observar la columna user_updates o las columnas last_user_seek o las columnas last_user_scan para observar si el índice se está usando.
Como ocurre con los índices que podrían ser necesarios crear, estas estadísticas se inicializan cada vez que se reinicia la instancia.
Jose Manuel Jurado Díaz