SQL Server, ideas y experiencias

Cómo permitir el uso del Profiler o la creación de Trazas sin tener derechos de administrador

por Jose Mariano Alvarez 31. julio 2009

La ejecución del SQL Server Profiler requiere al menos del permiso de servidor ALTER TRACE. Este es el mismo permiso que se requiere para poder ejecutar los procedimientos almacenados de T-SQL que se utilizan para crear las trazas.

Veamos un ejemplo.

Creamos un usuario con mínimos permisos :

USE [master]

GO

-- creamos el Login 

CREATE LOGIN [prueba] 

WITH PASSWORD=N'pruebaPass', 

DEFAULT_DATABASE=[master], 

CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF

GO

Luego podemos verificar que no se puede acceder mediante el profiler:

ProfilerPrbPerm

Hacer click en la imagen para agrandarla.

Asignamos el permiso de servidor ALTER TRACE con lo cual le concedemos el permiso de hacer trazas y conectar el Profiler para realizar un seguimiento.

GRANT ALTER TRACE 

TO [Prueba]

GO

Luego nos conectamos desde el Profiler y verificamos que ahora si se puede conectar.

Entonces ejecutamos :

CREATE LOGIN [prueba2] 

WITH PASSWORD=N'pruebaPass', 

DEFAULT_DATABASE=[master], 

CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF

GO

exec sp_help 'sys.indexes'

Como puede verse en la próxima imagen siguiente, el Profiler funciona y como seleccionamos el evento SQL:BatchStarting nos muestra las sentencias que ejecutamos.

CreateLoginEnProfiler

Hacer click en la imagen para agrandarla.

Consideraciones de seguridad importantes al asignar el permiso ALTER TRACE

Es importante ver que en el caso del CREATE LOGIN nos oculta los datos del usuario y la contraseña. Sin embargo nos muestra el parámetro del procedimiento almacenado sp_help.

Como los usuarios que tienen el permiso ALTER TRACE pueden ver las consultas capturadas, se debe tener cuidado ya que las mismas pueden contener datos confidenciales, como contraseñas que se pasan como parámetros en los procedimientos almacenados. El caso mas común es cuando se utilizan mecanismos propietarios de autenticación. Por lo tanto, es importante conceder estos permisos solo a los usuarios que tengan autorización para ver información confidencial.

Tags: , , , ,

Artículos

SQL Server Service Broker - Mensajería asincrónica desde la base de datos

por Jose Mariano Alvarez 28. julio 2009

El SQL Service Service Broker incluye la infraestructura necesaria para la programación asincrónica y se puede utilizar para la creación de aplicaciones distribuidas a través de múltiples bases de datos. Hace ya un tiempo que vengo hablando con algunos colegas respecto de los beneficios que nos ofrece el Service Bróker sobre todo cuando se necesita realizar el procesamiento de forma asincrónica o se necesita distribuir el procesamiento entre varios equipos.

Entre los beneficios que nos ofrece el Service bróker tenemos:

  • La integración de bases de datos.
  • Ordenación y coordinación de mensajes.
  • El acoplamiento flexible de las aplicaciones.
  • El bloqueo de mensajes relacionados.
  • La activación automática.

Para ver el detalle de estos conceptos pueden visitar:

Ventajas de Service Broker

Algunos ejemplos de uso del Service bróker pueden ser:

  • Desencadenadores asincrónicos
  • Procesamiento confiable de consultas
  • Recopilación confiable de datos
  • Procesamiento distribuido en el servidor para aplicaciones cliente
  • Consolidación de datos para aplicaciones cliente
  • Procesamiento por lotes a gran escala

 

Para ver el detalle de estos conceptos pueden visitar:

Usos habituales de Service Broker

 

Motivación

Ayer mismo estuvimos hablando de las posibilidades de usarlo en una reunión de trabajo con un grupo de arquitectos y desarrolladores. Luego me puse a buscar algo de información al respecto para respaldar mis afirmaciones y encontré este caso de éxito.

Les resumo parte de lo que pueden ver en el documento (en inglés) que pueden encontrar en el siguiente Link:

MySpace Uses SQL Server Service Broker to Protect Integrity of 1 Petabyte of Data

 

Resumen del caso de éxito en el uso del Service Broker

MySpace decidió que la mejor manera de manejar el constante crecimiento de sus bases de datos relacionales, que actualmente suman más de 1 petabyte, era escalar horizontal mente y dividir la información a través de múltiples instancias de SQL Server. Para ayudar a garantizar la integridad de los datos mientras se mantiene picos de demanda de servicio de hasta 4,4 millones de usuarios simultáneos, se necesitaba una solución eficiente de mensajería asincrónica entre sus 440 instancias de SQL Server y más de 1000 bases de datos.

MySpace creó una solución para que actúa como punto de coordinación para la entrega de mensajes a través de sus bases de datos distribuidas. La solución trabaja en un modelo de broadcast en la que el despachador de servicios asegura que un cambio originario de una base de datos se entrega al grupo de bases de datos destino relevante para la transaccion mediante la utilización del Service Broker, lo que ha permitido a MySpace realizar la gestión de claves foráneas a través de sus 440 servidores de bases de datos, la activación y desactivación de cuentas de sus millones de usuarios.

MySpace también utiliza Service Broker administrativa para distribuir los nuevos procedimientos almacenados y otras actualizaciones en todos los 440 servidores de bases de datos a través del despachador que crearon.

Tags:

Ideas y nociones

Usando el Resource Governor - Documento

por Jose Mariano Alvarez 25. julio 2009

CPUPerfGraf Entre las nuevas características que se encuentran en el SQL Server 2008 está el Resource Governor (regulador de recursos), que ofrece la capacidad de vigilar y controlar el uso de CPU y memoria.

Este “White Paper” explica varios escenarios de uso práctico del Resource Governor y ofrece orientación sobre las mejores prácticas para emplearlo de manera eficiente. Se encuentra dirigido a los profesionales de IT y administradores de base de datos responsables de la gestión de los servidores SQL Server 2008. Entre las características que cubre el documento se encuentran la forma de utilizar el Resource Governor tomando en cuenta los requerimientos de concurrencia, de alta disponibilidad, la consolidación, la virtualización, o los acuerdos de nivel de servicio (Service Level Agreement o SLA) para los casos de entornos de producción con SQL Server.

En el documento se destacan varios escenarios de uso común, que pueden ayudar a decidir cuándo y dónde utilizar esta tecnología, y un resumen de las mejores prácticas cuando se utiliza el Resource Governor.

Les dejo el enlace para poder descargar el documento (en inglés) desde el sitio de Microsoft

Using the Resource Governor (DOCX)

Si les interesan los conceptos básicos les dejo un par de links a los libros de ayuda:

Introducción al regulador de recursos

Conceptos del regulador de recursos

Tags: , , , , , ,

Documentos

Actualizaciones acumulativas del SQL Server 2008 – 20 Julio 2009

por Jose Mariano Alvarez 22. julio 2009

Se han liberado las nuevas actualizaciones de Julio. Como son acumulativas, cada versión nueva contiene todas las revisiones anteriores.

Es muy recomendable probar las revisiones antes de implementarlas en un entorno de producción. Si fuera posible como regla general, siempre es recomendable que se espere al lanzamiento del próximo Service pack que las incluiría antes de instalarlas.

 

Paquete de actualización acumulativa 6 para SQL Server 2008

Build 10.00.1812 (cumulative update)

Esta actualización es para quienes no han instalado aun el Service pack 1.

El 20 de julio se ha liberado la actualización acumulativa que contiene las revisiones para los problemas del SQL Server 2008 que han sido corregidos desde el lanzamiento de SQL Server 2008. Pueden encontrar más información en:

Cumulative update package 6 for SQL Server 2008

 

Paquete de actualización acumulativa 3 para SQL Server 2008 Service Pack 1

Build 10.00.2723 (cumulative update)

El 20 de julio se ha liberado la actualización acumulativa 3 para el SQL Server 2008 Service Pack 1 que contiene las revisiones para los problemas del SQL Server 2008 que han sido corregidos desde el lanzamiento de SQL Server 2008 Service Pack 1. Pueden encontrar más información en:

Cumulative update package 3 for SQL Server 2008 Service Pack 1

Tags: , ,

Actualizaciones

Se viene el Code Camp Buenos Aires 2009

por Jose Mariano Alvarez 22. julio 2009

bn_CodeCamp2009

Ya falta poco para que se abra la registración del Code Camp Buenos Aires 2009.

Code Camp es un evento totalmente gratuito que realiza el Programa Académico Microsoft junto con estudiantes de informática. Es principalmente realizado por estudiantes con conocimiento avanzado. Se realizan presentaciones en paralelo de distintos temas y demos en vivo de las células de estudio de algunas universidades.

Les dejo el link del sitio donde podran registrarse

http://www.codecamp.com.ar

Tags: ,

Comunidad | Eventos y conferencias

Documento de SQL Server 2008 Failover Clustering

por Jose Mariano Alvarez 12. julio 2009

La gente de SQLCAT ha publicado un nuevo documento. En esta ocasión el documento es un complemento de la documentación existente en los libros en pantalla sobre la planificación, implementación y administración de SQL Server 2008 failover cluster.

Es un largo documento de 175 páginas donde se detallan aspectos de esta tecnología probada y fiable de alta disponibilidad y está lleno de información útil donde hay muchos links a los contenidos existentes de la documentación oficial.

Los principales aspectos que trata son:

  • La arquitectura del clúster
  • Conceptos de cluster de Windows Server y SQL Server 2008.
  • Mejoras y actualizaciones a SQL Server 2008 failover clustering
  • Mantenimiento y administración de SQL Server 2008.

Pueden encontrar el documento en el siguiente link:

SQLCAT - SQL Server 2008 Failover Clustering

Tags: , , , ,

Novedades

Como numerar eficientemente las filas de una consulta select

por Jose Mariano Alvarez 10. julio 2009

Uno de las preguntas más frecuentes es cómo numerar la filas de una consulta. En SQL Server 2005 se introdujo ROW_NUMBER() para poder realizar esta operación fácilmente. Sin embargo en los casos en que no la podemos usar como en SQL Server 2000 existen creencias de que los subquery pueden ser alternativas eficientes y las consecuencias suelen ser catastróficas luego de que el volumen de registros crece.

Usando la tabla AdventureWorks2008.Sales.Customer vamos a probar cuatro estrategias y sus consecuencias.

 

Usando un subquery como habitualmente se sugiere en SQL Server 2000

Select  
    (
        select
            COUNT(*) + 1
        from AdventureWorks2008.Sales.Customer B 
        where b.AccountNumber  < a.AccountNumber
    ) as fila, 
    a.*
from AdventureWorks2008.Sales.Customer a
order by rowguid 

El resultado del plan muestra como se anida un SCAN de la tabla dentro de un NESTED LOOP lo cual genera un severo problema de rendimiento.

  |--Compute Scalar(DEFINE:([Expr1006]=[Expr1004]+(1)))
       |--Nested Loops(Inner Join, OUTER REFERENCES:([a].[CustomerID]))
            |--Compute Scalar(DEFINE:([a].[AccountNumber]=[AdventureWorks2008].[Sales].[Customer].[AccountNumber] as [a].[AccountNumber]))
            |    |--Compute Scalar(DEFINE:([a].[AccountNumber]=isnull('AW'+[AdventureWorks2008].[dbo].[ufnLeadingZeros]([AdventureWorks2008].[Sales].[Customer].[CustomerID] as [a].[CustomerID]),'')))
            |         |--Sort(ORDER BY:([a].[rowguid] ASC))
            |              |--Clustered Index Scan(OBJECT:([AdventureWorks2008].[Sales].[Customer].[PK_Customer_CustomerID] AS [a]))
            |--Compute Scalar(DEFINE:([Expr1004]=CONVERT_IMPLICIT(int,[Expr1010],0)))
                 |--Stream Aggregate(DEFINE:([Expr1010]=Count(*)))
                      |--Index Spool(SEEK:([B].[AccountNumber] < isnull('AW'+[AdventureWorks2008].[dbo].[ufnLeadingZeros]([AdventureWorks2008].[Sales].[Customer].[CustomerID] as [a].[CustomerID]),'')))
                           |--Compute Scalar(DEFINE:([B].[AccountNumber]=isnull('AW'+[AdventureWorks2008].[dbo].[ufnLeadingZeros]([AdventureWorks2008].[Sales].[Customer].[CustomerID] as [B].[CustomerID]),'')))
                                |--Index Scan(OBJECT:([AdventureWorks2008].[Sales].[Customer].[IX_Customer_TerritoryID] AS [B]))

 

Si vemos a continuación los detalles de la cantidad de IO podemos ver claramente como la cantidad de lecturas lógicas es de 1103320,

Table 'Worktable'.
    Scan count 19820,
    logical reads 1103320,
    physical reads 0,
    read-ahead reads 0,
    lob logical reads 0,
    lob physical reads 0,
    lob read-ahead reads 0.


Table 'Customer'.
    Scan count 2,
    logical reads 160,
    physical reads 0,
    read-ahead reads 0,
    lob logical reads 0,
    lob physical reads 0,
    lob read-ahead reads 0.

El resultado de la consulta tardo 1 minuto y 37 segundos

 

 

Usando la nueva sintaxis ROW_NUMBER() introducida en SQL Server 2005

Select
       ROW_NUMBER() OVER (ORDER BY a.AccountNumber ) as fila,
       A.* 
from 
       AdventureWorks2008.Sales.Customer a
order by 
       rowguid 

El resultado del plan muestra no se anida en este caso ningún SCAN sino que es un plan secuancial y muy eficiente.

  |--Sort(ORDER BY:([a].[rowguid] ASC))
       |--Sequence Project(DEFINE:([Expr1002]=row_number))
            |--Segment
                 |--Compute Scalar(DEFINE:([a].[AccountNumber]=[AdventureWorks2008].[Sales].[Customer].[AccountNumber] as [a].[AccountNumber]))
                      |--Sort(ORDER BY:([a].[AccountNumber] ASC))
                           |--Compute Scalar(DEFINE:([a].[AccountNumber]=isnull('AW'+[AdventureWorks2008].[dbo].[ufnLeadingZeros]([AdventureWorks2008].[Sales].[Customer].[CustomerID] as [a].[CustomerID]),'')))
                                |--Clustered Index Scan(OBJECT:([AdventureWorks2008].[Sales].[Customer].[PK_Customer_CustomerID] AS [a]))

 

Vemos como el resultado de aplicar la nueva función ha cambiado y solo se realizan 123 lecturas lógicas.

Table 'Customer'.
    Scan count 1,
    logical reads 123,
    physical reads 0,
    read-ahead reads 0,
    lob logical reads 0,
    lob physical reads 0,
    lob read-ahead reads 0.

 El resultado de la consulta tardo 1 segundo.

 

 

Usando la función IDENTITY() como en SQL Server 2000

En este caso se debe recurrir a una tabla temporal pero vemos que el beneficio es sustancial.

Debido a lo que ocurre con la función IDENTITY() y el ORDER BY se debe crear una tabla temporal para insertar los registros. Les dejo el Enlace a “The behavior of the IDENTITY function when used with SELECT INTO or INSERT .. SELECT queries that contain an ORDER BY clause”.

http://support.microsoft.com/kb/273586

NOTA: Quiero agradecer a Alejandro Mesa quien me hizo el comentario del error en los foros respecto de este comportamiento que yo había omitido en el Post el cual ya se encuentra actualizado y corregido según la documentacióní.

Creamos la tabla temporal para ordenar los registros

CREATE TABLE [dbo].[#Clientes](
    [fila] [int] IDENTITY(1,1) NOT NULL,
    [CustomerID] [int] NULL,
    [PersonID] [int] NULL,
    [StoreID] [int] NULL,
    [TerritoryID] [int] NULL,
    [AccountNumber] [varchar](10) NOT NULL,
    [rowguid] [uniqueidentifier] NOT NULL,
    [ModifiedDate] [datetime] NOT NULL
) ON [PRIMARY]
GO

 

Esta es la parte de la consulta donde se generan los números de fila.

Insert into #Clientes
(
    CustomerID, 
    PersonID, 
    StoreID, 
    TerritoryID, 
    AccountNumber, 
    rowguid, 
    ModifiedDate
)
Select     
    cast(CustomerID as int) as CustomerID , 
    PersonID, 
    StoreID, 
    TerritoryID, 
    AccountNumber, 
    rowguid, 
    ModifiedDate
from AdventureWorks2008.Sales.Customer a
ORDER BY a.AccountNumber 

Ahora vemos nuevamente que no se anida un SCAN en el plan por lo que resulta mucho más eficiente que en el caso del subquery.

  |--Table Insert(OBJECT:([#Clientes]), SET:([#Clientes].[CustomerID] = [Expr1006],[#Clientes].[PersonID] = [AdventureWorks2008].[Sales].[Customer].[PersonID] as [a].[PersonID],[#Clientes].[StoreID] = [AdventureWorks2008].[Sales].[Customer].[StoreID] as [a
       |--Compute Scalar(DEFINE:([Expr1007]=getidentity((-7),(0),N'#Clientes')))
            |--Top(ROWCOUNT est 0)
                 |--Compute Scalar(DEFINE:([a].[AccountNumber]=[AdventureWorks2008].[Sales].[Customer].[AccountNumber] as [a].[AccountNumber], [Expr1006]=CONVERT(int,[AdventureWorks2008].[Sales].[Customer].[CustomerID] as [a].[CustomerID],0)))
                      |--Sort(ORDER BY:([a].[AccountNumber] ASC))
                           |--Compute Scalar(DEFINE:([a].[AccountNumber]=isnull('AW'+[AdventureWorks2008].[dbo].[ufnLeadingZeros]([AdventureWorks2008].[Sales].[Customer].[CustomerID] as [a].[CustomerID]),'')))
                                |--Clustered Index Scan(OBJECT:([AdventureWorks2008].[Sales].[Customer].[PK_Customer_CustomerID] AS [a]))

 

Si vemos los resultados en I/O solo se realizan 123 lecturas logicas

Table 'Customer'.
    Scan count 1,
    logical reads 123,
    physical reads 0,
    read-ahead reads 0,
    lob logical reads 0,
    lob physical reads 0,
    lob read-ahead reads 0.

Select * 
from #Clientes c
order by C.rowguid 

El plan de esta parte es el SCAN y el SORT.

|--Sort(ORDER BY:([c].[rowguid] ASC))
       |--Table Scan(OBJECT:([tempdb].[dbo].[#Clientes] AS [c]))

 

Si vemos los resultados en I/O solo se realizan 167 lecturas logicas

Table '#Clientes_000000000007'.
    Scan count 1,
    logical reads 167,
    physical reads 0,
    read-ahead reads 0,
    lob logical reads 0,
    lob physical reads 0,
    lob read-ahead reads 0.

Queda eliminar la tabla temporal con

drop table #Clientes 

El total acumulado de tiempo fue de 1 segundo.

 

 

Conclusión:

 

Caso Lecturas Tiempo
Subquery 1103480 97 seg
Row_Number() 123 1 seg
Tabla temporal + Identity() 280 1 seg

Vemos que es mucho más eficiente la tercera opción usando una tabla temporal y la función identiy() que la opción de la subquery (subconsulta). Sin embargo esta no es  tan eficiente como en el caso de la nueva sintaxis de SQL Server 2005/8 con ROW_NUMBER(). Por lo tanto si tiene SQL Server 2005 o SQL Server 2008 Lo mejor es usar la funcion ROW_NUMBER() y si tienen SQL Server 2000 la mejor opción es usar la tabla temporal y la función Identity().

 

En todos los casos todas las lecturas fueron lógicas ya que la tabla tenia todas las paginas en memoria.

NOTA: Me falta comparar la alternativa de usar CLR y de usar un cursor de T-Sql.

Tags: , , ,

Artículos

Powered by SQL Total Consulting


View Jose Mariano Alvarez's profile on LinkedIn

 Add to Technorati Favorites 

Calendar

<<  octubre 2017  >>
lumamijuvido
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345

View posts in large calendar

Locations of visitors to this page

Widget Twitter not found.

Root element is missing.X


Valid XHTML 1.0 Transitional

Valid CSS!