10
Optimización de SQL Server (SQL Server Tuning) Para poner a punto SQL Server es necesario ajustar la configuración, opciones, y valores de setup basadas en las observaciones de las características de trabajo del servidor. Típicamente estas observaciones se hacen durante el periodo de trabajo mas critico de servidor para perfeccionar las cargas de trabajo más pesadas. Las recomendaciones de afinación siguientes son aquéllas que generalmente tienen el mayor impacto en el trabajo de Servidor. Sin embargo, la aplicación de estas recomendaciones puede producir resultados diferentes que dependen del ambiente particular del Servidor. Memoria La memoria de SQL Server esta dividida en dos espacios, el cache de procedimientos, y el cache de datos. El Servidor SQL distribuye eficazmente la memoria entre el cache de procedimiento y el cache de datos usando los parámetros de configuración del cache de procedimiento. La distribución de la memoria restante entre procedimientos y datos, se encarga de mantener los objetos mas usados en sus respectivos caches de memoria. Por consiguiente, los procedimientos almacenados mayormente usados deben estar en el cache de procedimientos, mientras que la mayoría de índices y tablas usadas mas frecuentemente deben estar en el cache de datos. La mejor manera de determinar cómo es usada la memoria por el Servidor de SQL es ejecutar DBCC MEMUSAGE. Esta sentencia indica la cantidad de memoria asignada al Servidor de SQL en el comienzo, los 12 objetos más grandes en el cache de procedimientos, y los 20 objetos más grandes en el cache de datos. Por consiguiente, las recomendaciones son basadas en el uso de estos datos que determinaran el tamaño óptimo para los caches. Optimizando el Cache de Datos El cache de datos está compuesto de la memoria sobrante del Servidor de SQL una vez que los requisitos del cache de procedimiento han sido satisfechos. Lo mejor es tener bastante espacio del cache para contener la mayoría los índices usados y un porcentaje respetable de las tablas mas accedidas frecuentemente, reduciendo las entradas/salidas físicas. Usted también puede usar la sentencia DBCC MEMUSAGE para ver los 20 objetos más grandes del cache de datos y puede determinar un tamaño considerable para el cache de datos basado en los tamaños de estos objetos. Usted también puede determinar el tamaño de las tablas e índices accedidas mas frecuentemente aplicando las fórmulas del tamaño cedidas por Appendix A of Microsoft SQL Server Administrator's Companion. Habiendo calculado estos tamaños, usted puede elegir asignar bastante memoria al Servidor de SQL y contener la íntegramente los objetos de las bases de datos en el cache. Optimizando el Cache de Procedimientos.

Optimización de SQL Server

Embed Size (px)

Citation preview

Page 1: Optimización de SQL Server

Optimización de SQL Server (SQL Server Tuning)

Para poner a punto SQL Server es necesario ajustar la configuración, opciones, y valores de setup basadas en las observaciones de las características de trabajo del servidor. Típicamente estas observaciones se hacen durante el periodo de trabajo mas critico de servidor para perfeccionar las cargas de trabajo más pesadas. Las recomendaciones de afinación siguientes son aquéllas que generalmente tienen el mayor impacto en el trabajo de Servidor. Sin embargo, la aplicación de estas recomendaciones puede producir resultados diferentes que dependen del ambiente particular del Servidor.

Memoria

La memoria de SQL Server esta dividida en dos espacios, el cache de procedimientos, y el cache de datos. El Servidor SQL distribuye eficazmente la memoria entre el cache de procedimiento y el cache de datos usando los parámetros de configuración del cache de procedimiento. La distribución de la memoria restante entre procedimientos y datos, se encarga de mantener los objetos mas usados en sus respectivos caches de memoria. Por consiguiente, los procedimientos almacenados mayormente usados deben estar en el cache de procedimientos, mientras que la mayoría de índices y tablas usadas mas frecuentemente deben estar en el cache de datos.

La mejor manera de determinar cómo es usada la memoria por el Servidor de SQL es ejecutar DBCC MEMUSAGE. Esta sentencia indica la cantidad de memoria asignada al Servidor de SQL en el comienzo, los 12 objetos más grandes en el cache de procedimientos, y los 20 objetos más grandes en el cache de datos. Por consiguiente, las recomendaciones son basadas en el uso de estos datos que determinaran el tamaño óptimo para los caches.

Optimizando el Cache de Datos

El cache de datos está compuesto de la memoria sobrante del Servidor de SQL una vez que los requisitos del cache de procedimiento han sido satisfechos. Lo mejor es tener bastante espacio del cache para contener la mayoría los índices usados y un porcentaje respetable de las tablas mas accedidas frecuentemente, reduciendo las entradas/salidas físicas. Usted también puede usar la sentencia DBCC MEMUSAGE para ver los 20 objetos más grandes del cache de datos y puede determinar un tamaño considerable para el cache de datos basado en los tamaños de estos objetos. Usted también puede determinar el tamaño de las tablas e índices accedidas mas frecuentemente aplicando las fórmulas del tamaño cedidas por Appendix A of Microsoft SQL Server Administrator's Companion. Habiendo calculado estos tamaños, usted puede elegir asignar bastante memoria al Servidor de SQL y contener la íntegramente los objetos de las bases de datos en el cache.

Optimizando el Cache de Procedimientos.

Al poner a punto el cache de procedimiento, lo mejor es determinar el tamaño óptimo para contener los procedimientos almacenados más activos. En realidad lo que se busca es prevenir las lecturas a procedimientos almacenados en disco porque esto es muy costoso. Es más, si el cache de procedimiento es bastante grande , los procedimientos no se descargaran del cache por los nuevos procedimientos cargados en el. (Recuerde que el Servidor de SQL guardará una copia duplicada de cada procedimiento que se accede por más de un usuario.) por defecto, el Servidor de SQL distribuye 30 por ciento de memoria disponible al cache de procedimientos después que el kernel de SQL se ha asignado. La tarea es determinar si este 30 por ciento es poco, suficiente, o demasiado basado en el tamaño de objetos del cache de procedimientos. Es importante no disminuir el cache de procedimientos debajo de 5 por ciento.

Usted puede determinar si el cache de procedimientos es bastante grande ejecutando los procedimientos almacenados mas frecuentemente usados y ejecutando la sentencia DBCC MEMUSAGE; esto mostrara los 12 procedimientos almacenados más grandes en el cache de procedimientos. Si usted tiene más de 12 procedimientos almacenados, puede continuar ejecutando los demás procedimientos y

Page 2: Optimización de SQL Server

ejecutar cada vez la sentencia DBCC MEMUSAGE para ver si uno de los procedimientos previamente ejecutados ha permanecido en el cache. Usted también puede ejecutar cada procedimiento almacenado y obtener su tamaño de ejecución usando DBCC MEMUSAGE. Después de que usted ha ejecutado todos los procedimientos que son llamados con mas frecuencia y ha obtenido sus tamaños, sume éstos valores y obtenga el tamaño total necesario del cache para todos los procedimientos.

TEMPDB en RAM

Las consultas ejecutadas contra el Servidor de SQL que usan espacio de trabajo temporal como las operaciones, GROUP BY, tablas temporales, uniones de tablas (JOIN), son beneficiadas si la tempdb se encuentra en RAM. Sin embargo, para poner la tempdb en RAM, usted debe tener mas memoria disponible que la asignada a Windows NT Server y SQL Server. Por consiguiente, si la tempdb esta actualmente en 25 MB de tamaño, entonces la memoria total requerida para el sistema es: 16 MB para el Windows NT más (XX) la memoria para SQL Server mas 25 MB para el tempdb.

Distintas formas de optimizar las consultas realizadas en SQL.

El lenguaje SQL es no procedimental, es decir, en las sentencias se indica que queremos conseguir y no como lo tiene que hacer el interprete para conseguirlo. Esto es pura teoría, pues en la práctica a todos los gestores de SQL hay que especificar sus propios truquitos para optimizar el rendimiento.

Por tanto, muchas veces no basta con especificar una sentencia SQL correcta, sino que además, hay que indicarle como tiene que hacerlo si queremos que el tiempo de respuesta sea el mínimo. En este apartado veremos como mejorar el tiempo de respuesta de nuestro interprete ante unas determinadas situaciones:

Diseño de las tablas

Normaliza las tablas, al menos hasta la tercera forma normal, para asegurar que no hay duplicidad de datos y se aprovecha al máximo el almacenamiento en las tablas. Si hay que desnormalizar alguna tabla piensa en la ocupación y en el rendimiento antes de proceder.

Los primeros campos de cada tabla deben ser aquellos campos requeridos y dentro de los requeridos primero se definen los de longitud fija y después los de longitud variable.

Ajusta al máximo el tamaño de los campos para no desperdiciar espacio. Es muy habitual dejar un campo de texto para observaciones en las tablas. Si este campo se va

a utilizar con poca frecuencia o si se ha definido con gran tamaño, por si acaso, es mejor crear una nueva tabla que contenga la clave primaria de la primera y el campo para observaciones.

Gestión y elección de los índices

Los índices son campos elegidos arbitrariamente por el constructor de la base de datos que permiten la búsqueda a partir de dicho campo a una velocidad notablemente superior. Sin embargo, esta ventaja se ve contrarrestada por el hecho de ocupar mucha más memoria (el doble más o menos) y de requerir para su inserción y actualización un tiempo de proceso superior.

Evidentemente, no podemos indexar todos los campos de una tabla extensa ya que doblamos el tamaño de la base de datos. Igualmente, tampoco sirve de mucho el indexar todos los campos en una tabla pequeña ya que las selecciones pueden efectuarse rápidamente de todos modos.

Un caso en el que los índices pueden resultar muy útiles es cuando realizamos peticiones simultáneas sobre varias tablas. En este caso, el proceso de selección puede acelerarse sensiblemente si indexamos los campos que sirven de nexo entre las dos tablas.

Los índices pueden resultar contraproducentes si los introducimos sobre campos triviales a partir de los cuales no se realiza ningún tipo de petición ya que, además del problema de memoria ya mencionado, estamos ralentizando otras tareas de la base de datos como son la edición, inserción y borrado. Es por

Page 3: Optimización de SQL Server

ello que vale la pena pensárselo dos veces antes de indexar un campo que no sirve de criterio para búsquedas o que es usado con muy poca frecuencia por razones de mantenimiento.

Campos a Seleccionar

En la medida de lo posible hay que evitar que las sentencias SQL estén embebidas dentro del código de la aplicación. Es mucho más eficaz usar vistas o procedimientos almacenados por que el gestor los guarda compilados. Si se trata de una sentencia embebida el gestor debe compilarla antes de ejecutarla.

Seleccionar exclusivamente aquellos que se necesiten No utilizar nunca SELECT * por que el gestor debe leer primero la estructura de la tabla antes

de ejecutar la sentencia Si utilizas varias tablas en la consulta especifica siempre a que tabla pertenece cada campo, le

ahorras al gestor el tiempo de localizar a que tabla pertenece el campo. En lugar de SELECT Nombre, Factura FROM Clientes, Facturacion WHERE IdCliente = IdClienteFacturado, usa: SELECT Clientes.Nombre, Facturacion.Factura WHERE Clientes.IdCliente = Facturacion.IdClienteFacturado.

Campos de Filtro

Se procurará elegir en la cláusula WHERE aquellos campos que formen parte de la clave del fichero por el cual interrogamos. Además se especificarán en el mismo orden en el que estén definidos en la clave.

Interrogar siempre por campos que sean clave. Si deseamos interrogar por campos pertenecientes a índices compuestos es mejor utilizar todos

los campos de todos los índices. Supongamos que tenemos un índice formado por el campo NOMBRE y el campo APELLIDO y otro índice formado por el campo EDAD. La sentencia WHERE NOMBRE='Juan' AND APELLIDO Like '%' AND EDAD = 20 sería más optima que WHERE NOMBRE = 'Juan' AND EDAD = 20 por que el gestor, en este segundo caso, no puede usar el primer índice y ambas sentencias son equivalentes por que la condición APELLIDO Like '%' devolvería todos los registros.

Orden de las Tablas

Cuando se utilizan varias tablas dentro de la consulta hay que tener cuidado con el orden empleado en la cláusula FROM. Si deseamos saber cuantos alumnos se matricularon en el año 1996 y escribimos: FROM Alumnos, Matriculas WHERE Alumno.IdAlumno = Matriculas.IdAlumno AND Matriculas.Año = 1996 el gestor recorrerá todos los alumnos para buscar sus matriculas y devolver las correspondientes. Si escribimos FROM Matriculas, Alumnos WHERE Matriculas.Año = 1996 AND Matriculas.IdAlumno = Alumnos.IdAlumnos, el gestor filtra las matrículas y después selecciona los alumnos, de esta forma tiene que recorrer menos registros.

Preguntas y respuestas acerca de SQL

Errores de E/S, creación de reflejos de la base de datos, etc.

Paul S. Randal

P He empezado a ejecutar comprobaciones de coherencia con regularidad en las bases de datos que administro e, incluso, he agregado algunas alertas del Agente SQL para localizar los errores de E/S que

Page 4: Optimización de SQL Server

se indican en las consultas de los usuarios. No sé si la lógica que he implementado en las comprobaciones y las alertas funcionará, ya que mis bases de datos no tienen daños. ¿Cómo puedo crear daños en una base de datos de prueba para asegurarme de que todo lo que he configurado funciona correctamente? Además, ¿qué más puedo hacer para detectar los errores de E/S?R En SQL Server® 2000, el truco para crear una base de datos dañada en la que realizar pruebas consistía en eliminar manualmente una fila de la tabla sysindexes de una base de datos de prueba. Pero con SQL Server 2005, dañar una tabla del sistema de esta manera es muy difícil. La mejor manera de dañar una base de datos de prueba es usar un editor hexadecimal para alterar un archivo de datos con la base de datos cerrada. Estos son los pasos que debe seguir:

Cierre la base de datos para que los archivos de datos no estén bloqueados. (Tenga cuidado de no separar la base de datos porque, si daña la página incorrecta, tal vez no pueda unirla de nuevo).

Elija una parte del archivo de más de 100 páginas aproximadamente (por lo menos de 819.200 bytes) con intervalos de 8.192 bytes (límite de página). De esta forma puede evitar las páginas de metadatos importantes y los mapas de bits de asignación, lo que le permite iniciar la base de datos y ejecutar DBCC CHECKDB en ella.

Escriba algunos bytes de ceros en la parte elegida del archivo. Al usar esta técnica la introducción de algunos daños en el encabezado de la página está prácticamente garantizada.

Dicho esto, la forma más rápida de dañar una base de datos de prueba es usar una que ya esté creada. Puede encontrar ejemplos de bases datos dañadas de SQL Server 2000 y SQL Server 2005 (con explicaciones) en mi blog (en go.microsoft.com/fwlink/?LinkId=115151).En cuanto a la segunda pregunta con respecto a lo que se debe hacer para detectar los errores de E/S: debe habilitar las sumas de comprobación de las páginas. Esta característica se introdujo en SQL Server 2005 para proteger una página entera de la base de datos de los errores introducidos por el subsistema de E/S.

Básicamente, al escribir una página en el disco, lo último que hace SQL Server es calcular una suma de comprobación de los 8 KB de la página y marcarla en la página. Al leer una página del disco, si tiene una suma de comprobación de página, se calculará de nuevo y se comparará con la que se almacena en la página. Si no coinciden, significa que algún elemento ajeno a SQL Server dañó la página y se produce un error 824. El error se muestra en la conexión que provocó la lectura de la página, además de registrarse en el registro de error de SQL Server y en el registro de eventos de aplicación de Windows®.

Las sumas de comprobación de página están activadas de forma predeterminada en todas bases de datos creadas en SQL Server 2005 y SQL Server 2008. Sin embargo, hay que habilitarlas manualmente en las bases de datos actualizadas a partir de versiones anteriores de SQL Server. Para habilitar las sumas de comprobación de página, use este código:

Copiar código

ALTER DATABASE mydb SET PAGE_VERIFY CHECKSUM;

Sugerencia: cambie el puerto predeterminado de SQL Server

De forma predeterminada, el puerto configurado de las instancias de SQL Server es el 1433. Una vez que una instancia use este puerto, no podrá ocuparlo ninguna otra. Por lo tanto, si instala una segunda instancia (con nombre) de escucha en la red mediante tcp, necesitará otro puerto. En algunos casos, el administrador puede cambiar el puerto por razones de ofuscación (aunque esta forma de ofuscación es secundaria y se puede interrumpir fácilmente mediante un escáner de puerto). Por supuesto, deberá configurar el cliente para usar un puerto diferente. Existen tres enfoques típicos de hacerlo.

Primero, suponiendo que el administrador cambió el puerto de una instancia a 5555, puede especificar simplemente el número de puerto de la instancia dentro del nombre del equipo al que desea conectar

Page 5: Optimización de SQL Server

mediante la sintaxis MiNombreDeServidor,5555. Si se vuelve a cambiar el puerto, los clientes deberán cambiar sus connectionStrings de nuevo.

Otra opción es usar alias de SQL Server, que se configuran en el cliente. Además de especificar un nombre de alias, debe indicar el nombre de servidor, el nombre de puerto y el protocolo. Una vez configurado, el alias se puede usar como nombre de servidor para conectarse a la instancia de la base de datos. La ventaja que aporta esta opción es que un administrador de dominio puede implementar los cambios de configuración del servidor, ya que la configuración se almacena en el registro.

La tercera opción de las instancias con nombre en las que el usuario sólo conoce el nombre de la instancia y especifica el nombre con la estructura NombreDeEquipo\NombreDeInstancia dentro de connectionString es usar el servicio Explorador de SQL Server. Esto ya se ha implementado en SQL Server 2000 como parte de un servicio en ejecución. No obstante, en SQL Server 2005, se creó el servicio Explorador de SQL Server como servicio independiente. Además del descubrimiento de instancias del equipo, responde a las solicitudes entrantes del protocolo de datagramas de usuario (UDP) en el puerto 1434 con el número de puerto adecuado para la instancia solicitada, lo que permite la redirección del cliente y la compatibilidad de una conexión transparente.

—Jens K. Suessmeyer, consultor de bases de datos en Microsoft

P Para eliminar la fragmentación de la base de datos, he configurado un plan de mantenimiento nocturno que regenera todos los índices de la base de datos de producción que se ejecuta en SQL Server 2005 Enterprise Edition con SP2. He observado que, de esta forma, la base de datos crece demasiado, por eso, agregué un paso para reducir el espacio extra, ya que no hay mucho espacio en el disco. Ahora parece que la regeneración no funciona. ¿Qué pasa?

R Se ha encontrado con un problema al que suelen enfrentarse muchos usuarios cuando intentan configurar un plan de mantenimiento. Ha entrado en un ciclo de reducción y crecimiento.

Al regenerar un índice, se crea una nueva copia del índice antes de eliminar el índice existente. Este procedimiento necesita espacio extra en los archivos de la base de datos (generalmente el mismo espacio que use el índice actual). En SQL Server 2000, también se necesita el espacio extra para ordenar las filas del índice (aproximadamente un 20 por ciento del tamaño del índice), pero ese requisito se ha eliminado en la regeneración de un índice sencillo en SQL Server 2005.

A veces, los administradores desean quitar el espacio extra creado durante la regeneración del índice, por lo que realizan una operación de reducción al plan de mantenimiento después de la regeneración. Sin embargo, poca gente sabe que esta reducción provocará la fragmentación del índice debido a la naturaleza de su algoritmo. Esto significa que el índice regenerado y desfragmentado recientemente se fragmentará de inmediato, lo que anulará el efecto de regeneración en primer lugar.

Ya que el archivo de la base de datos volverá a aumentar la próxima vez que se regenere el índice, es preferible que la base de datos tenga espacio extra y evitar que se ejecute la reducción. (Además, el continuo crecimiento y reducción de los archivos de la base de datos causará la fragmentación de los archivos a nivel de sistema operativo, lo que puede provocar un rendimiento insuficiente al igual que la fragmentación del índice.

Por último, debería plantearse la posibilidad de reducir la frecuencia con que regenera los índices. Incluso puede tratar de usar un método alternativo, como el antiguo DBCC INDEXDEFRAG que escribí para SQL Server 2000 o la nueva sintaxis ALTER INDEX REORGANIZE en SQL Server 2005 y SQL Server 2008.

Hay unas notas técnicas de gran utilidad en las que se trata la fragmentación de índices y ofrece orientación acerca de cuándo eliminar la fragmentación (en go.microsoft.com/fwlink/?LinkId=115154). Aunque este texto se escribió para SQL Server 2000, los conceptos son los mismos.

Page 6: Optimización de SQL Server

P Hemos estado evaluando la estrategia de recuperación de desastres en mi organización y creo que la creación de reflejos de bases de datos es el procedimiento correcto en nuestra situación. El servidor que intento proteger tiene muchas bases de datos no relacionadas (resultado de un proyecto previo de consolidación de servidores) y quiero usar la creación de reflejos de bases de datos para todas. Mi pregunta es la siguiente: ¿cuántas bases de datos se pueden reflejar antes de que se reduzca el rendimiento?

R La respuesta a esta pregunta es muy típica: depende. Las directrices publicadas aconsejan no reflejar más de 10 bases de datos por instancia, pero depende de cada usuario. Hay que tener en cuenta los siguientes factores para la instalación del hardware:

¿De cuánta memoria disponen las instancias principal y reflejada? (Lo idea sería que dispongan de la misma.)

¿Cuánta capacidad de procesamiento tienen las instancias principal y reflejada? (También debería ser la misma.)

¿Cuánto ancho de banda tiene el subsistema de E/S de la instancia reflejada? (Debería tener tanto como el de la principal.)

¿Cuántos registros de transacciones genera la carga de trabajo en cada base de datos? ¿Cuánto ancho de banda de red está disponible entre las instancias principal y la reflejada?

Los últimos dos factores son los más importantes. Si el ancho de banda de red disponible entre las dos instancias no es suficiente para encargarse la velocidad de generación de registros de transacciones combinados por segundo de todas las bases de datos reflejadas, el rendimiento disminuirá en las bases de datos principales. SQL Server 2008 ayuda a mejorar una parte de esta carga mediante la compresión de secuencias de registro.El siguiente aspecto más importante a tener en cuenta en la creación de reflejos es la memoria y los requisitos de los subprocesos. Todas las bases de datos reflejadas ocupan un subproceso además de memoria. Si un servidor de baja potencia tiene una muchas bases de datos reflejadas, esto puede suponer una carga excesiva para el servidor al combinarlas con la carga de trabajo habitual.

Además, debe tener en cuenta cómo llevará a cabo la creación de reflejos de bases de datos. En el modo sincrónico, las transacciones de la base de datos principal no se pueden confirmar hasta que todos los registros de transacciones se hayan copiado en el registro de transacciones de la base de datos reflejada. Por lo tanto, cualquier retraso causado por una red sobrecargada podría provocar un problema de rendimiento de la carga de trabajo de la principal.

En el modo asincrónico, las transacciones se pueden confirmar en la principal sin tener que esperar, aunque un retraso de la red podría aumentar el número de registros de transacciones en espera de envío. Esto puede causar problemas relacionados con el tamaño del registro de transacciones. O, lo que es peor, los registros de transacciones que no se hayan enviado se perderán en caso de error. Por lo tanto, cuantos más registros de transacciones queden sin enviar, mayor será la probabilidad de perder datos en una situación de recuperación.

Las situaciones pueden ser muy diferentes y he detectado algunos ejemplos interesantes en entornos de producción reales. Por ejemplo, advertí un entorno con 150 bases de datos con una actividad muy pequeña y sin sincronización. Las 150 bases de datos se reflejaron sin problemas.

Por el contrario, también pude ver una configuración que solamente tenía tres bases de datos muy cargadas sin una conexión de red buena. En esa situación, apenas se pudo reflejar una base de datos antes de que la falta de ancho de banda de la red degradara la carga de trabajo.

La clave del éxito es, en primer lugar, realizar el cálculo de generación de registros. Si parece que el ancho de banda de red disponible puede ser compatible con el número de las bases de datos que desea reflejar, no debería haber ningún problema. Pruebe su configuración antes de ponerlo en ejecución y asegúrese de incluir todas operaciones que podrían generar un registro de transacciones (especialmente todo el mantenimiento de bases de datos que pueda realizar).

Page 7: Optimización de SQL Server

Paul S. Randal es el director general de SQLskills.com y uno de los profesionales más valorados (MVP) de SQL Server. Trabajó en el equipo del motor de almacenamiento de SQL Server de Microsoft de 1999 a 2007. Paul escribió las directrices de reparación de DBCC CHECKDB para SQL Server 2005 y fue responsable del motor de almacenamiento del núcleo durante el desarrollo de SQL Server 2008. Es experto en recuperación de desastres, en alta disponibilidad y en el mantenimiento de bases de datos, además de moderador habitual en congresos. Además, es autor de un blog: SQLskills.com/blogs/paul.

© 2008 Microsoft Corporation and CMP Media, LLC. Reservados todos los derechos. Queda prohibida la reproducción parcial o total sin previa autorización.