Últimamente estoy participando en bastantes proyectos de migración de SQL Server 2000 a SQL Server 2008 R2. Independientemente de la arquitectura existente en cada cliente, siempre hemos de conocer la topologia de consultas que se lanzan y sobre todo QUIEN las lanza.En un proyecto de migración nunca podemos dejar cabos sueltos y menos cuando uno de los cabos sueltos puede llevar a que aplicaciones (sean o no críticas) no funcionen.
La opción más sensata siempre es crear una traza de profiler para SQL Server 2000, que nos capture durante un tiempo prudencialmente amplio y significativo, la actividad de nuestro servidor
¿Qué nos interesa conocer?
- La consulta que ha sido lanzada (posteriormente lo utilizaremos para que SSUA analice si hay patrones conflictivos)
- El hostname desde donde se lanza
- El login utilizado
- El nombre de la aplicación
- La BBDD sobre la que se está ejecutando la consulta
Dicho esto, nos podemos hacer una idea de los eventos e información que necesitamos capturar en SQL Server profiler…y ahora viene la parte divertida…la explotación de esos datos 🙂
1: -- Create table with data
2: --
3: CREATE TABLE [dbo].ExternalConnectionAnalysis(
4: [ServerName] [nvarchar](256) NOT NULL,
5: [databaseid] [int] NULL,
6: [applicationname] [nvarchar](256) NULL,
7: [hostname] [nvarchar](256) NULL,
8: [loginname] [nvarchar](256) NULL,
9: queries_executed bigint not null
10: ) ON [PRIMARY]
11: GO
12:
13: -- Insert data
14: INSERT into dbo.ExternalConnectionAnalysis(ServerName, databaseid, applicationname, hostname, loginname,queries_executed)
15: SELECT 'my_server_name' AS ServerName , databaseid, applicationname, hostname, loginname,COUNT(*)
16: FROM ::fn_trace_gettable('path_to_trc_file.trc', default)
17: GROUP BY databaseid, applicationname, hostname, loginname
18: go
Tenemos esa opción que evidentemente te lee el fichero de traza .trc (y los que vengan detrás en caso de haberse creado con multiples ficheros) y agrupa por la información que queremos, o podemos optar por una forma algo más rebuscada y eficiente para procesar los datos como esta otra:
1: declare @srvname sysname = 'my_server_name'
2: declare @trcpath varchar(max) = 'PATH_TO_FILE_WITH_TRACE_DATA.trc'
3: ;
4:
5: with existent_data as(
6: select ServerName, databaseid, applicationname,hostname,loginname
7: from dbo.ExternalConnectionAnalisys
8: where ServerName = @srvname
9: ),
10: trc as (
11: SELECT @srvname AS ServerName , trc.databaseid, trc.applicationname, trc.hostname, trc.loginname
12: FROM ::fn_trace_gettable(@trcpath, default) trc
13: )
14: INSERT into dbo.ExternalConnectionAnalysis(ServerName, databaseid, applicationname, hostname, loginname,queries_executed)
15: SELECT @srvname AS ServerName , trc.databaseid, trc.applicationname, trc.hostname, trc.loginname ,COUNT(*)
16: FROM trc left join existent_data ed on
17: (trc.DatabaseID = ed.databaseid
18: and trc.ApplicationName = ed.applicationname
19: and trc.HostName = ed.hostname
20: and trc.LoginName = ed.loginname
21: )
22: where ed.databaseid is null or ed.applicationname is null or ed.hostname is null or ed.loginname is null
23: GROUP BY trc.databaseid, trc.applicationname, trc.hostname, trc.loginname
La gran ventaja de utilizar la consulta anterior radica principalmente en que es una consulta que solo añadirá las nuevas filas con información que le vayamos proponiendo. Es decir, que como es normal, tendremos ficheros de traza a traves del tiempo (cada dia previsiblemente tendremos .trc nuevos) y los podremos procesar independiemente de tener todos los ficheros de traza y procesarlos de golpe.
Evidentemente es una gran ventaja…pero otra ventaja oculta es si miras un poco más alla de la simple consulta y te das cuenta de que al utilizar el left join y el group by, nuestro SQL Server ha generado un plan de ejecución eficiente mediante un fantástico MERGE JOIN
Queda a tu disposición probar la consulta sin el left join, mediante un cruce de los de toda la vida y ver que ocurre…y sobre todo el tiempo que tarda, por culpa del super LOOP JOIN que te mete
Salu2!