domingo, 29 de marzo de 2009

Conseguir conectividad Wireless para maquinas virtuales hyper-v

En alguna ocasión alguien me realizó la pregunta y puesto que la respuesta puede no ser demasiado obvia…aquí dejo el post para responderla.

Si directamente lo que no sabemos es como hacer para tener Wireless en Windows Server 2008, aquí van unos sencillos pasos:

  • Administrar servidor

image

  • Añadir características

image

  • Añadir soporte Wireless

image

NOTA: para mas información, recomiendo visitar http://www.win2008workstation.com/wordpress/2008/03/08/enable-wireless-networking/

Una vez tengamos el servicio de Wireless sobre W2k8 funcionando, los pasos para hacer que nuestras máquinas virtuales tengan conectividad a internet mediante Wireless son sencillos:

  • Instalamos la interfaz de red loopback. Para ello nos vamos al administrador de dispositivos

image

image

  • Añadimos hardware

image

  • Indicamos que añadiremos el hardware de forma manual a partir de una lista

image 

  • Indicaremos que específicamente deseamos adaptadores de red

image

  • Elegiremos de Microsoft, el “Microsoft Loopback Adapter”

image

Una vez lo tengamos agregado y finalicemos el asistente, lo siguiente que tendremos que hacer es darle conectividad a la nueva interfaz loopback a través de nuestra salida a internet Wireless. Para ello, basta con crear un puente entre la interfaz loopback y la wireless seleccionando ambas tarjetas y pulsando sobre boton derecho->Bridge connections.

image

Por último, solo falta crearnos la tarjeta virtual hyper-v desde el administrador hyper-v

  • Entramos en “Virtual Network Manager…”

image

  • Seleccionamos una red de tipo “External” para tener conectividad hacia fuera.

image

  • Seleccionamos como tarjeta de red la “Microsoft Loopback Adapter”

image

  • Por último solo falta entrar en las propiedades de nuestra máquina virtual y seleccionar la tarjeta de red virtual ;)

image 

Muy facil, como veis ;)

Migración de SQL Server 2000 a 2008 y SQL Profiler

Cuando uno se plantea una migración de SQL Server, no solo se plantea analizar el propio servidor y las BBDDs, sino que debe plantearse también las aplicaciones cliente. Un argumento más para tener en cuenta en pro del uso de procedimientos almacenados es que el Sql Server Upgrade Advisor (SSUA a partir de ahora) es capaz de analizar los objetos de la BBDD y por lo tanto será capaz de detectar código “deprecated” en el mismo. Puesto que las aplicaciones cliente en ocasiones generan T-SQL ad-hoc, la aplicación SSUA nos provee de análisis de trazas de profiler capturadas. De este modo, podremos generar una traza de profiler sobre el servidor X y posteriormente pasársela al SSUA y que nos diga si realmente existen sentencias depreciadas que hayan sido originadas por nuestras aplicaciones.

Para ello, hagamos lo siguiente:

  • Abrir SQL Server Profiler 2000 (nótese que pongo 2000, no 2008 – ver final del post-)
  • Capturar una traza “Replay”. Puesto que capturar una traza replay genera una alta cantidad de información, lo primero que podemos hacer es crear una traza que contenga los eventos SQL:BatchStarting, SQL:SmtpStarting y RPC:Starting. Esta traza ocupará bastante menos que la de Replay y podremos realizar los análisis de forma previa mas rápidos.

image

  • Dejar correr la traza para capturar las consultas que llegan desde aplicaciones cliente (en nuestro caso, únicamente he lanzado una select depreciada que veremos al final).
  • Una vez capturada información durante un tiempo prudencial y representativo (1 semana?), la podemos salvar a fichero (eso en el caso de que no la hayamos scriptado, claro)

image

  • Una vez tenemos la traza de profiler a buen recaudo, procederemos a analizarla con el SSUA 2008

image

  • Nos conectamos a SQL Server 2000 (no hace falta que sea producción, podemos usar cualquier SQL Server 2000 que tengamos por ahí)

image

  • Una vez indicado el servidor, indicaremos que deseamos analizar únicamente la traza de profiler (en la versión SSUA 2005, no era posible analizar únicamente profiler sin especificar BBDD)

image

  • Una vez hecho esto, SSUA se pondrá a realizar el análisis de la traza de profiler. En este punto, la aplicación se conectará contra la instancia de SQL Server 2000 indicada y comenzará a realizar el análisis. para ello, ni mas ni menos se pone a ejecutar queries como un loco, para ver si alguna de las reglas de validación de queries depreciadas es violada (podemos activar el profiler si tenemos curiosidad y ver que tipo de información recupera).

image

image

  • Para este ejemplo, puesto que solo me interesa analizar la traza, los mensajes relativos a la instancia de SQL Server no son relevantes, por eso los obvio y me centro en únicamente el que se encuentra señalado en rojo.

image

image

Como vemos, el mensaje me indica que en el fichero de trazas se encuentra un SQL Batch concreto (el que se puede apreciar en la imagen). Se nos proporciona información relativa a como solucionarlo y cual es su problema (no se ve en la imagen, pero está detrás), aunque lo importante aquí es que hemos sido capaces de detectar correctamente una sentencia generada de forma AD-HOC por alguna de nuestras aplicaciones (ya nos preocuparemos nosotros de detectar quien ha originado la petición, viendo la traza de profiler).

IMPORTANTE: La traza de profiler ha de ser generada con la versión de SQL Profiler del motor SQL Server que deseemos migrar (SQL 2000 o 2005), puesto que optimizaciones en la estructura del fichero de trazas entre versiones de SQL Server hacen imposible su lectura en compatibilidad hacia atrás. Quiero decir, que si por error creáis la traza de profiler, desde SQL Profiler 2008, SSUA no va a ser capaz de analizarla y por algun tipo de bug no nos avisará de ello.

martes, 24 de marzo de 2009

Compresión de datos en SQL Server 2008 (II de III)

Como ya se comentó en el anterior post, en SQL Server 2008 no solo tenemos compresión de datos a nivel de backup, sino también a nivel datos con compresión de página y compresión de fila. En esta ocasión voy a hablar sobre la compresión a nivel de datos.

La idea de poder comprimir la información almacenada en la base de datos, evidentemente produce tanto un ahorro de espacio en disco como una mejora de rendimiento del servidor que trataremos mas adelante. Por otro lado, el mero hecho de poder comprimir tipos de datos antes considerados como estáticos, nos permite mitigar malas decisiones de diseño en nuestras bases de datos; pensemos por ejemplo en la típica situación de una mala elección de un tipo de datos ( char(255) ) por desconocimiento, que no se puede modificar por problemas de compatibilidad de las herramientas que las explotan.
Algo que debemos tener presente es que SQL Server garantiza que la descompresión de un dato siempre sea posible; esto quiere decir que el tamaño de una fila + sobrecarga por compresión no puede ser superior a 8060 bytes y eso lo garantizará el propio motor. Dicho de otro modo, la compresión de datos permite almacenar mas información por página, pero no por fila.
En este post no voy a hablar simplemente de lo que podemos ahorrarnos usando compresión, sino mas bien lo encamino a demostraros el por qué debemos pensarnos seriamente si nos conviene activarlo de una forma u otra en función de nuestros datos almacenados.
Además, conviene que en nuestro escenario, si tenemos volúmenes comprimidos donde almacenar la información de backups por ejemplo, las deshabilitemos y midamos el rendimiento ya que quizás ahora no sea necesario que se trate de comprimir algo que ya lo está. Para más información http://msdn.microsoft.com/en-us/library/ms190954.aspx apartado “Data Compression”

Compresión a nivel de fila

La compresión a nivel de fila se puede aplicar a:
  • Tablas almacenadas como HEAP (sin índices clustered)
  • Tablas almacenadas como índices agrupados
  • Índices no agrupados
  • Vistas indexadas
  • Tablas e índices particionados (inclusive de forma independiente cada partición)
Algo que debemos conocer es que la compresión no se activa en los índices no agrupados de forma automática. Por ello, si queremos que el índice no agrupado se encuentre comprimido deberemos especificarlo. Por otro lado, si tenemos una tabla almacenada como un HEAP comprimida y le creamos un índice agrupado, la compresión en este caso si que se conserva.
Y por si alguien está pensando en que esto tuviera que ver con la fragmentación…no es así, por lo que no se te ocurra eliminar los planes de mantenimiento de re indexación y reorganización de índices ;)
image
Imagen gráfica que representa la compresión a nivel de fila para tipo de datos int y numeric
Existe una tabla que indica a qué tipos de datos se aplica esta compresión (varchar, por si lo estás pensando, no obtiene mejoria con este tipo de compresión).
Para más información sobre datos beneficiados por compresión de fila: http://msdn.microsoft.com/en-us/library/cc280576.aspx

Compresión a nivel de página

SQL Server 2008 nos permite ir mas allá en la compresión de datos gracias a la compresión de páginas. Se trata de un paso mas en el proceso de compresión que nos permite exprimir todavía mas el ratio de compresión conseguido. Pero ojo porque no todo es oro lo que reluce en este caso ya que el coste de CPU extra para conseguirlo puede no ser justificado si lo comparamos con la compresión de datos a nivel de fila. Este nivel de compresión solo está justificado para comprimir tablas con un alto índice de repetición de datos por página que puedan aplicar la compresión de prefijos y de diccionario.
Internamente, SQL Server realiza la compresión en estas 3 fases:
  1. Compresión de fila (visto anteriormente)
  2. Compresión mediante prefijos
  3. Compresión mediante diccionario
Enseguida veremos en qué consisten los pasos 2 y 3, pero antes de nada me gustaría recalcar de nuevo que cuanta mas frecuencia de aparición, mayor eficiencia de almacenamiento y que se trata de una compresión a nivel de página por lo que únicamente cuando la página se encuentra llena, se produce compresión a nivel de página, sino únicamente se quedará comprimida mediante row compression.

Compresión mediante prefijos

Los prefijos se almacenan en un área de la página llamada anchor record y , cada columna posee su propia lista de prefijos lo cual quiere decir (y recalco) que no se expande a otras columnas. En la siguiente imagen se puede ver el paso de compresión mediante prefijos.
image
Proceso de compresión mediante prefijos

Quisiera recalcar la palabra prefijos, puesto que puede dar lugar a que pensemos que la compresión de página no funciona si no entendemos bien lo que realmente hace para conseguirla. En la demo de mas abajo entenderéis por qué digo esto.

Compresión mediante diccionario

Una vez aplicada la compresión mediante prefijos, se realiza una pasada para aplicar la compresión mediante diccionario, que reserva en la página, un diccionario donde almacenar los prefijos comunes y substituirlos por tokens. Esto es a nivel de página, por lo que cada página posee su propio diccionario y no es extensible a otras páginas.
image
Proceso de compresión mediante diccionario

Demostraciones

Vamos a ensuciarnos las manos ya, una vez vista la parte teórica. Para ello, voy a utilizar un caso que me viene al pelo para demostraros que no siempre la compresión de página es la mejor y que siempre depende de la distribución de datos que tengamos en nuestras tablas. El script de la demostración lo tenéis mas abajo, voy a exponer sus resultados de entrada para no marearos:
Partiendo de una tabla con 1.000.000 de filas cuyas columnas son de tipos de datos bigint y varchar(200) y datos:
image
Vamos a ver su distribución de datos por páginas sin comprimir:
image
Si activamos la compresión a nivel de fila:
image
Si activamos la compresión a nivel de página:
image
Viendo la columna page_count, que nos indica el nº de páginas que posee el índice clústered (la tabla, vamos) nos damos cuenta que hay un descenso grande de páginas entre no tener la tabla comprimida y tenerla comprimida por fila, pero que únicamente hay una página de diferencia en el nivel hoja de aplicar compresión de página a solo aplicar compresión de fila.
Evidentemente estamos viendo que el sobrecoste del procesamiento de compresión de prefijos y de diccionario no está sirviendo prácticamente para nada (una página en un millon de filas…).
¿por qué la compresión de página no obtiene prácticamente ningún beneficio, comparado con la compresión a nivel de fila?
Pues ni mas ni menos que porque casi no hay prefijos comunes. Cuando veáis el script os daréis cuenta que la columna de tipo varchar posee un comienzo con muy poca repetición ( usa NEWID() ) y que luego nosotros rellenamos con caracteres repetidos al final. Puesto que no hay prefijos repetidos, no va a comprimir los carácteres finales y de poco nos sirve comprimir a nivel de página.
Por lo tanto, la única compresión que está realizándose es la compresión de fila de la columna id. Es más, solo está realizándose la compresión de la columna id, porque las columnas de tipo varchar no són comprimibles a nivel de fila (de nuevo os refiero a la url http://msdn.microsoft.com/en-us/library/cc280576.aspx)
¿Qué ocurre por tanto si existen prefijos comunes?
En este caso voy a hacer un poco el caso extremo en el que todas las filas tengan en una columna con un prefijo idéntico (ni que decir tiene que en mas de un sitio he visto eso y se suele llamar bug de aplicación cliente ;)
La tabla de antes, pero con prefijos comunes quedará así:
image
Sin comprimir:
image
Compresión a nivel de fila:
image
Compresión a nivel de página:
image
Nótese la grandísima diferencia en este caso de la compresión por página. Eso es debido como ya hemos comentado, a que ahora si que hay prefijos comunes y se pueden aplicar los algoritmos de compresión sobre el texto. En cualquier caso, quiero recalcar que la compresión a nivel de fila es exáctamente igual que en el caso anterior, solo ha aplicado sobre bigint, no sobre varchar.
Código con valores sin prefijos similares:
-- ECB:
--
use Northwind
go
if exists (select * from sys.tables where name = 'varchar_variable_dcha2')
    drop table dbo.varchar_variable_dcha2
go
CREATE TABLE [dbo].varchar_variable_dcha2(
  id bigint identity primary key,
    c varchar(200) NULL
)
go

declare @i int
set @i = 1
while @i<=10 -- 1.000.000 filas
begin    
    INSERT INTO dbo.varchar_variable_dcha2
    SELECT top (100000)
       replace(cast(NEWID() as varchar(100)), '-','') + REPLICATE('a', 200-32)
    FROM [Northwind].[dbo].[Orders]
    CROSS JOIN [Northwind].[dbo].[Order Details]

  print cast (@i as varchar(100))
  set @i=@i+1
end
go

select top(10) * from dbo.varchar_variable_dcha2
go
SELECT so.name, si.name, index_level, index_type_desc,
    page_count, record_count,
    avg_fragmentation_in_percent, avg_page_space_used_in_percent
FROM
sys.objects so
join sys.indexes si
on so.object_id = si.object_id
join sys.dm_db_index_physical_stats (
    db_id (),
    object_id('dbo.varchar_variable_dcha2'),
    NULL, NULL, 'DETAILED') v
on v.object_id = si.object_id
and v.index_id = si.index_id
order by index_level
go
   
ALTER TABLE dbo.varchar_variable_dcha2
REBUILD WITH (DATA_COMPRESSION = ROW);
go

SELECT so.name, si.name, index_level, index_type_desc,
    page_count, record_count,
    avg_fragmentation_in_percent, avg_page_space_used_in_percent
FROM
sys.objects so
join sys.indexes si
on so.object_id = si.object_id
join sys.dm_db_index_physical_stats (
    db_id (),
    object_id('dbo.varchar_variable_dcha2'),
    NULL, NULL, 'DETAILED') v
on v.object_id = si.object_id
and v.index_id = si.index_id
order by index_level
go

ALTER TABLE dbo.varchar_variable_dcha2
REBUILD WITH (DATA_COMPRESSION = PAGE);
go
SELECT so.name, si.name, index_level, index_type_desc,
    page_count, record_count,
    avg_fragmentation_in_percent, avg_page_space_used_in_percent
FROM
sys.objects so
join sys.indexes si
on so.object_id = si.object_id
join sys.dm_db_index_physical_stats (
    db_id (),
    object_id('dbo.varchar_variable_dcha2'),
    NULL, NULL, 'DETAILED') v
on v.object_id = si.object_id
and v.index_id = si.index_id
order by index_level
go



Código con valores de prefijos similares:



-- ECB:
--
use Northwind
go
if exists (select * from sys.tables where name = 'varchar_variable_dcha2')
    drop table dbo.varchar_variable_dcha2
go
CREATE TABLE [dbo].varchar_variable_dcha2(
  id bigint identity primary key,
    c varchar(200) NULL
)
go

declare @i int
set @i = 1
while @i<=10 -- 1.000.000 filas
begin    
    INSERT INTO dbo.varchar_variable_dcha2
    SELECT top (100000)
        REPLICATE('a', 200-32)
    FROM [Northwind].[dbo].[Orders]
    CROSS JOIN [Northwind].[dbo].[Order Details]

  print cast (@i as varchar(100))
  set @i=@i+1
end
go

select top(10) * from dbo.varchar_variable_dcha2
go
SELECT so.name, si.name, index_level, index_type_desc,
    page_count, record_count,
    avg_fragmentation_in_percent, avg_page_space_used_in_percent
FROM
sys.objects so
join sys.indexes si
on so.object_id = si.object_id
join sys.dm_db_index_physical_stats (
    db_id (),
    object_id('dbo.varchar_variable_dcha2'),
    NULL, NULL, 'DETAILED') v
on v.object_id = si.object_id
and v.index_id = si.index_id
order by index_level
go
   
ALTER TABLE dbo.varchar_variable_dcha2
REBUILD WITH (DATA_COMPRESSION = ROW);
go

SELECT so.name, si.name, index_level, index_type_desc,
    page_count, record_count,
    avg_fragmentation_in_percent, avg_page_space_used_in_percent
FROM
sys.objects so
join sys.indexes si
on so.object_id = si.object_id
join sys.dm_db_index_physical_stats (
    db_id (),
    object_id('dbo.varchar_variable_dcha2'),
    NULL, NULL, 'DETAILED') v
on v.object_id = si.object_id
and v.index_id = si.index_id
order by index_level
go

ALTER TABLE dbo.varchar_variable_dcha2
REBUILD WITH (DATA_COMPRESSION = PAGE);
go
SELECT so.name, si.name, index_level, index_type_desc,
    page_count, record_count,
    avg_fragmentation_in_percent, avg_page_space_used_in_percent
FROM
sys.objects so
join sys.indexes si
on so.object_id = si.object_id
join sys.dm_db_index_physical_stats (
    db_id (),
    object_id('dbo.varchar_variable_dcha2'),
    NULL, NULL, 'DETAILED') v
on v.object_id = si.object_id
and v.index_id = si.index_id
order by index_level
go



Resumen

La compresión de datos a nivel de fila no afecta a los siguientes tipos de datos:
  • Varchar,nvarchar,image,text,ntext
  • XML, FILESTREAM, varbinary y sql_variant
  • Date, time (ya extremadamente compactos)
El beneficio se obtiene por tanto en otros tipos de datos:
  • datetime, datetime2, datetimeoffset: ahorra 2 bytes si no almacena segundos
  • char: solo ocupa lo necesario (como varchar)
  • int, bigint,float, real,…: solo usa lo necesario
  • binary: no almacena los ceros que puede evitar
Además, en todos los tipos de datos, NULL y 0 no ocupan ningún byte
<><><><> <><><><> <><><><>
image
Por último y no menos importante, la compresión de datos solo implica tareas administrativas de SQL Server, nuestras aplicaciones son completamente agnósticas a nuestros cambios ;)

GUSENET: Migración De SQL 2000 a 2008 y Windows 7

Este próximo viernes 27/03/2009 vamos a estar Rubén Garrigos y uno mismo en el evento de GUSENET donde trataremos el tema de la migración de SQL Server 2000 a 2008. Aparte de la consabida teoria, contaremos desde nuestra experiencia en grandes proyectos, problemas reales con los que uno se puede enfrentar y las soluciones propuestas para llevar a cabo con éxito una migración.

El link de registro en MSDN: http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032409964&Culture=es-ES

Agenda:
16:30 : Planifica y vencerás: Migrando de SQL Server 2000 a SQL Server 2008
Rubén Garrigós y Enrique Catalá de SolidQ
17:30: Preguntas.
18:00: Descanso.
18:30: Un acercamiento a Windows 7.
Javier Yagüe (coordinador dotnetclub de UA).
Y Oscar Montesinos de JPA,sl
19:30: Ofertas de empleo y debate del grupo.

Lugar: Universidad de Murcia. Aula 0.01 de la Facultad de Informática del Campus de Espinardo(Murcia)

domingo, 15 de marzo de 2009

Compresión de datos en SQL Server 2008 (I de III)

Hoy me apetece escribir sobre las ventajas de usar la compresión en SQL Server 2008. Es un tema que ya discutí en algo de profundidad el año pasado en nuestro SUMMIT 08, pero que no por ello está en desuso sino todo lo contrario.

Ahora que ya se empiezan a ver SQL Server 2008 en clientes y que las migraciones hacia 2008 están cada vez mas a la orden del día, es un excelente momento para tratar un tema que a mas de uno le puede sacar de un aprieto. Y es que hoy en día cada vez se almacena más y más información en nuestras bases de datos y de manera mas variopinta (imágenes, vídeos, …)

Uno de los retos que tenemos ahora por tanto es que el tamaño de nuestras bases de datos puede llegar a ser inmanejable (terabytes), y que cada vez queremos más y más rendimiento en las mismas (como es de esperar ;). Para apoyarnos en la solución de estos retos, SQL Server 2008 proporciona compresión de datos.

¿Para qué nos puede servir comprimir la información?

  • Tablas e índices mas pequeños requieren menos lecturas/escrituras para mantenerlos
  • Ficheros mas pequeños son mas rápidos de copiar/generar/utilizar (backups, por ejemplo)

¿Qué mecanismos de compresión nos aporta SQL Server 2008?

Nos aporta por un lado la posibilidad de realizar backups comprimidos (nivel de fichero); así como compresión de páginas y filas (nivel de datos).

Compresión de backups

Realmente podemos pensar que la compresión de backups es simplemente una mejora que repercutirá simplemente en nuestros requerimientos de capacidad en disco. Bueno, pues no es eso solo ya que a poco que pensemos un momento nos daremos cuenta que hoy en día el principal limitante con el que nos encontramos es precisamente los cuellos de botella que suponen los discos donde se almacena la información. Sea por lo que sea, cuanto menos tengas que leer/escribir de disco, mas rápido irá todo (premisa que explota SQL Server hasta la saciedad gracias al excelente uso de la memoria RAM, que evita en gran medida ir a disco si no es necesario).

Dicho esto, veamos unos cuantos datos reales de backups sobre AdventureWorks (en los 3 casos el de SQL 2005):

MotorTiempoMb/sTamaño
SQL 20054.125 sec41.692 MB/sec168,019 kb
SQL 2008 sin compresión3.219 sec45.873 MB/sec135,256 Kb
SQL 2008 con compresión2.327 sec57.986 MB/sec34,976 kb

Veamos los mismos en restauración:

MotorTiempoMb/s
SQL 20054.171 sec41.233 MB/sec
SQL 2008 sin compresión3.569 sec36.865 MB/sec
SQL 2008 con compresión1.920 sec68.526 MB/sec

NOTA: Quadcore Q9300 2.50Ghz, 4Gb Ram, Win2k8 x64 EE, SQL 2K5 x64 SP3, SQL 2K8 x64, Unidad de disco 2xSeagate ST3320613AS ATA en RAID 0

Evidentemente, uno ve los números y piensa que efectivamente lo que ha de hacer es comprimir los backups por defecto. Para ello podemos lanzar la ejecución:

   1:  EXEC sp_configure 'backup compression default', '1'
   2:  GO
   3:  RECONFIGURE
Sobre si en nuestro sistema es útil realizar este tipo de acciones…lo trataremos en un siguiente post.

Pero ¿cuanto ratio de compresión estamos obteniendo?

Para saberlo basta con lanzar la siguiente query:


   1:  SELECT backup_size/compressed_backup_size
   2:  FROM msdb..backupset

Con ella obtendremos el ratio de compresión alcanzado en cada backup, que será de 1 en el caso de que no hayamos comprimido y mayor que uno en el caso de haberlo hecho.

Para las pruebas anteriores, el valor medio del ratio de compresión me ha salido de 3.867, lo cual es bastante y nos da una idea de por qué un backup en SQL Server 2005 ocupa tantísimo a comparación del de SQL 2008 comprimido.

En el siguiente post, trataré en profundidad este tema, que seguro a mas de uno le interesa ;) Entre otras cosas hablaré del coste CPU de utilizar compresión, así como métodos para aprovechar resource governor en este sentido.

Falta por tanto hablar de rendimiento y de compresión de datos, que lo dejaré para dos posts de aqui en adelante. Estad atentos ;)

sábado, 7 de marzo de 2009

Planificación de una migración de SQL Server 2000 a SQL Server 2008

Es bastante frecuente encontrar hoy en día aplicaciones de producción en las que BBBDDs trabajan todavía contra SQL Server 2000. Pese a que SQL Server 2000 es un buen motor de BBDD que probablemente está dando un servicio excelente para nuestra aplicación de producción, no hemos de olvidar que el soporte de SQL Server 2000 ha finalizado y han aparecido versiones mas eficientes (2005 y recientemente 2008). Es ahora el momento en el que se plantean numerosas situaciones que involucran una migración de todo un sistema de producción basado en SQL Server 2000 a SQL Server 2008.

Antes de nada, solo quiero comentar que SQL Server 2008 permite la migración “in place” de un SQL Server 2000, pero que la próxima versión de SQL Server no lo hará. Por otro lado, pese a que permite la migración “in place”, esta solo podrá ser llevada a cabo si el host se trata de un Windows Server 2003, ya que no está certificado SQL Server 2008 sobre Windows Server 2000, y SQL Server 2000 no está certificado para Windows Server 2008…(vaya lio ;)

A continuación vemos algunas cosas que debemos conocer si estamos en la tesitura de realizar migraciones “in place”:

  1. Si vamos a migrar “in place”, asegurarse que tenemos SP2 de Win2k3 como mínimo instalado y SP4 de SQL Server 2000 aplicado.
  2. No se puede instalar si existe algún reinicio pendiente (por ejemplo por alguna actualización de windows pendiente).
  3. Debemos actualizar a una edición de la misma rama o superior, nunca inferior (no podremos pasar de SQL 2000 Enterprise a SQL 2008 Standard, por ejemplo)
  4. No es posible pasar de x32 a x64 “in place”, a menos que hagamos una estrategia de detach-and-restore, lo que nos obligaria (como es lógico) a recrear logins, jobs,… y a que en algun momento convivieran las dos instancias en el mismo servidor.
  5. No están soportadas actualizaciones “in place” en clústers de IA64
  6. No se va a poder actualizar SSAS 2000 si está clusterizado (esto último no lo he podido validar personalmente)
image

image

Todas estas validaciones las realiza SQL Server 2008 al intentar realizar la actualización in place. En el CD de instalación, podremos elegir la opción de actualizar de un SQL server 2000 (ver imagen de arriba). En la imagen de la derecha podemos ver como al intentar realizar la actualización, se ha detectado un reinicio pendiente y nos indica que para poder seguir debemos realizarlo.

 

Pero este post no trata de como migrar el motor, sino de cómo planificaremos nuestra migración. Para ello disponemos de una herramienta llamada SQL Server 2008 Upgrade Advisor. Lo que tenemos que hacer es instalar dicha herramienta que viene con el propio CD de instalación de SQL Server 2008 o mediante descarga directa aquí.

Esta herramienta, entre otras cosas nos permite realizar un análisis de la instancia SQL Server 2000 deseada, detectando que cambios deben llevarse a cabo para la actualización a 2008, así como la información del por qué (links explicando cada una de las “amenazas” detectadas).

Al contrario que la herramienta de actualización del motor propiamente dicha, en este caso la herramienta está pensada para instalarse en un equipo diferente al de producción, por lo que está preparada para solicitar la instancia a analizar, así como el usuario (con permiso sysadmin) que necesitemos para conectar y realizar el análisis.

image
image image
   

Ahora que ya conocemos algo acerca de Upgrade Advisor y como conectarnos, vamos a ver qué hacer para realizar el análisis.

Análisis motor relacional:

En relación al análisis del motor relacional, una de las cosas que debemos saber es que esta herramienta no realiza por nosotros un análisis de la tipología de consultas que se lanzan contra el servidor. Recordemos que en SQL Server 2008, se implementan las políticas descontinuadas. Esto quiere decir que existe sintaxis T-SQL que no es compatible en SQL Server 2008. Esto es muy importante y puede producirnos un verdadero dolor de cabeza si migramos el motor de BBDD y no nos hemos centrado en analizar estas cosas.

La herramienta, sí que realiza este análisis a los objetos existentes en las BBDDs de la instancia a migrar (procedimientos almacenados, funciones, …) pero no sabe que consultas ad-hoc le mandan las aplicaciones, y para eso nosotros tendremos que poner de nuestra parte.

Lo que debemos hacer por tanto es definirnos una traza de SQL Profiler, que capture los eventos RPC:Completed y SMTP:BatchCompleted durante el tiempo que estimemos conveniente (una semana, un día,…) para que las aplicaciones que funcionan contra  las BBDD se muevan a sus anchas y envíen todas las peticiones al motor que necesiten.

image

Una vez tengamos la/s traza/s capturadas, las utilizaremos mas adelante para analizarlas y determinar si existe alguna consulta depreciada, para actuar en consecuencia (modificar la aplicación para que la consulta en cuestión cambie de sintaxis).

Podemos mientras, analizar los objetos de la instancia simplemente haciendo click en Upgrade Advisor y seleccionando que partes deseamos analizar (se entiende que todas ;)

image

Al final del análisis, se nos mostrará un report que tendremos que estudiar con detenimiento y con el que sabremos cuanto trabajo nos va a costar migrar la BBDD (si existen incompatibilidades) y qué deberemos modificar para ello.

Por otro lado, analizar la traza es tan facil como seleccionarla en la sección de análisis del motor relacional

image

Análisis SSAS

El análisis de SSAS lo realiza la propia herramienta

image

En este punto me gustaría puntualizar que Microsoft no recomienda realizar un upgrade de SSAS 2000 a 2008 in place y que la mejor estrategia es instalar un SSAS2008  y luego utilizar el SSAS migration assistant para migrar de una instancia a la otra. Después de migrar, desinstalar SSAS2000.

Análisis DTS

El análisis de los DTS se puede realizar o bien de SQL server o bien de DTS que residan en sistema de ficheros

image

Este es un tema sobre el que espero poder escribir bastante en un futuro ya que hay muchas variables a tener en cuenta, pero para comenzar, seguro que a mas de uno le asombra la potencia de las herramientas suministradas por Microsoft para ayudarnos a tal fin.

I´ll be back…

Si, sé que esto debería haberlo hecho antes…pero entre pitos y flautas siempre encontraba tiempo para hacer otras cosas antes que para dedicarlo a mi blog…Esta frase que seguro todos recordareis por haber salido de la boca de “el chuache” (a.k.a Terminator ) ha rezumbado durante mucho tiempo en mi cabeza hasta que por fin me he decidido…Ese “volveré” se ha converido desde este momento en un “he vuelto”, asique a partir de ya, volveré a retomar esta bitácora que tenia olvidada.

Un saludo a todos!