Compresión en SQL Server 2008
Enrique Catalá
Solid Quality Mentors
ecatala@solidq.com
Compresión en SQL Server 2008
Agenda

• Motivación
• Aproximaciones en SQL Server 2008
• Backup comprimidos
• Compresión de datos
•
•

FILA
PÁGINA

• Cómo estimar el ahorro
• Cómo aplicar compresión
• A quién aplicar compresión
Compresión en SQL Server 2008
Motivación

• Cada día se almacena:
• Más información – Terabytes con cierta frecuencia
• Más variopinta – imágenes, videos, audio, gráficos, mapas
• Retos de grandes BDs
• Tamaño de base de datos
• Manejabilidad de la BD (backup, índices, chekdb, …)
• Mecanismo: compresión
• A nivel de fichero:
o NTFS
o BD: backups de base de datos
o A nivel de OLTP Sería complicado de manejar comprimir/descomprimir trozos grandes

• A nivel de fila / página:
o compresión/descompresión de trozos pequeños de información
Compresión en SQL Server 2008
Motivación

• Si reducimos la información almacenada
•

Tablas/índices más pequeños
o Más fácil de gestionar

•

Ficheros más pequeños
o Más fácil de copiar

• Se tiende a guardar demasiada información
• Otros fabricantes ya lo cubren:
Almacenamiento

CPU

Mejora
Rendimiento

Oracle

-29%

+10%

+10%

DB2

-39%

+10%

+6%
Compresión en SQL Server 2008
Aproximaciones
• A nivel de fichero
•

Compresión de BACKUP

•
•
•

Ninguno (como hasta ahora*)
Compresión de fila – ROW
Compresión de página – PAGE

• A nivel de datos

* Vardecimal cubierto desde SQL 2005 SP2
Compresión en SQL Server 2008
Aproximación– BACKUP

• BACKUP comprimido (Ratios 5:1)
•
•
•

Depende de los datos
Similar a otros fabricantes. Algoritmo propietario
Resultados (para BACKUP y RESTORE)
o Menos I/O y menos tiempo
o Más CPU
– Depende de carga OLTP, pero asumible a partir de 4 Cores

• Todos pueden RESTORE con compresión
•

Sólo Enterprise Edition BACKUP con compresión
Compresión en SQL Server 2008
BACKUP
• Sintaxis:
•

BACKUP DATABASE ... WITH COMPRESSION

•

EXEC sp_configure 'backup compression default', '1'

•
•
•
•

Sin compresión: 131 segundos (2,685 Mb/s) – 361 Mb
Con compresión: 49 segundos (7,081 Mb/s) – 44 Mb
Ratio 8:1 en tamaño
Ratio 2.6:1 en tiempo

• Por defecto deshabilitado

• Rendimiento real* para AdventureWorks:

• Compresion NTFS: 600 segundos – 117 Mb (posterior)
• Compresión NTFS: 270 segundos – 117 Mb

• Cálculo del rendimiento real en vuestros sistemas:
•

SELECT backup_size/compressed_backup_size FROM msdb..backupset;
* Virtual Server 2005 R2 800Mb Ram, W2003 R2, HP dv9000
DEMO

Compresión de
backups
Compresión en SQL Server 2008
Consideraciones compresion BACKUP

• No es posible tener en un mismo conjunto, BACKUPS
comprimidos y descomprimidos

• Uso intensivo de CPU. Podemos limitar su impacto

creando un resource pool que limite el uso de CPU a
un 20% como máximo

• Versiones anteriores de SQL Server no pueden
restaurar backups comprimidos

• No es necesario especificar nada en el RESTORE
Compresión en SQL Server 2008
Formatos de compresión – ROW

• Compresión a nivel de fila
• Eficiencia en almacenamiento de cada columna
• Conceptualmente, casi todas las columnas son de longitud
•

variable.
Nulos de longitud fija = nada de espacio

• Arreglar “errores” de elección de tipos de datos:
•
•
•

Smallint, int, bigint, decimal, numeric, smallmoney, money
Datetime, datetime2, timestamp
Char, nchar
Compresión en SQL Server 2008
Compresión de filas: Consideraciones

• Se puede aplicar a:
•
•
•
•
•

Tablas almacenadas como HEAP
Tablas almacenadas como índices agrupados
Índices no agrupados
Vistas indexadas
Tablas e índices particionados (inclusive de forma independiente
cada partición)

• La compresión no se activa en los índices no agrupados

de forma automática
• La compresión no varia al crear un índice agrupado sobre
un HEAP
• OJO! No soluciona la fragmentación…REINDEXA!
Compresión en SQL Server 2008
Formatos de compresión – ROW
DateId

CarrierTracking

OfferID

PriceDisc

20070601

4911-403C-98

10

0.00

20070601

4911-403C-99

10

0.00

20070602

6431

10

0.00

20070602

6431-4D57-83

10

0.00

20070602

6431-4D57-84

10

0.00

20070602

6431-4D57-85

10

100.00

20070603

4E0A-4F89-AE

10

0.00

DateId

CarrierTracking

OfferID

PriceDisc

20070601

4911-403C-98

10

0.00

20070601

4911-403C-99

10

0.00

20070602

6431

10

0.00

20070602

6431-4D57-83

10

0.00

20070602

6431-4D57-84

10

0.00

20070602

6431-4D57-85

10

100.00

20070603

4E0A-4F89-AE

10

0.00

• Microsoft® SQL

Server™ 2005 Service
Pack 2 (SP2)

• VarDecimal

• Habilita que valores

decimales puedan ser
almacenados en
tamaño variable

• Máxima precisión

requería 17 bytes!!!
Compresión en SQL Server 2008
Formatos de compresión – ROW
DateId

CarrierTracking

OfferID

PriceDisc

20070601

4911-403C-98

10

0.00

20070601

4911-403C-99

10

0.00

20070602

6431

10

0.00

20070602

6431-4D57-83

10

0.00

20070602

6431-4D57-84

10

0.00

20070602

6431-4D57-85

10

100.00

20070603

4E0A-4F89-AE

10

0.00

• Columnas de tamaño
fijo:

• SQL Server 2008 extiende
la lógica a tipos de datos
fijos:
o int, bigint, datetime, char, etc.

DateId

CarrierTracking

OfferID

PriceDisc

20070601

4911-403C-98

10

0.00

20070601

4911-403C-99

10

0.00

20070602

6431

10

0.00

20070602

6431-4D57-83

10

0.00

20070602

6431-4D57-84

10

0.00

20070602

6431-4D57-85

10

100.00

20070603

4E0A-4F89-AE

10

0.00
DEMO

• Vardecimal en
SQL 2005

• Compresión de
filas
Compresión en SQL Server 2008
Formatos de compresión – PAGE

• A nivel de página
• Un paso más allá de compresión de fila
• Secuencia de 3 fases:
1. Compresión de fila (visto anteriormente)
2. Compresión de prefijos
3. Compresión de diccionario

• Cuanto más frecuencia, mayor eficiencia de
almacenamiento
Compresión en SQL Server 2008
Formatos de compresión – PAGE – Prefijos
• Segundo paso: reemplazo de prefijos

• Los prefijos se almacenan en un área de la página
(anchor record)

• Prefijos por columna
• Cada columna su lista de prefijos
• No se expande a todas las columnas

• Formato de almacenamiento
Compresión en SQL Server 2008

Formatos de compresión – PAGE – Prefijos
DateId

CarrierTracking

OfferID

PriceDisc

20070601

4911-403C_9 8

10

0.00

20070601

4911-403C_9 9

10

0.00

20070602

6431-4D57_8 2

10

0.00

20070602

6431-4D57_8 3

10

0.00

20070602

6431-4D57_8 4

10

0.00

20070602

6431-4D57_8 5

10

100.00

20070603

4E0A-4F89_AE

10

0.00

DateId

CarrierTracking

OfferID

PriceDisc

200706011

4911-403C_98

8

12

8

11

6431-4D57_82

3

2

3

2

3

2

3

2

3

7

2

11

7

2

11

7

2

11

3
4

7

2
3

11

5

2

4E0A-4F89-AE

2

7

prefijos:

•

0.00

10

2

9

• Compresión mediante

100.00
3

•

Lista de prefijos se
almacena en la página,
para prefijos comunes
para cada columna
Cada valor encontrado
se reemplaza por:
o Token para el prefijo
o Sufijo para el valor
Compresión en SQL Server 2008

Formatos de compresión – PAGE – Diccionario
DateId

CarrierTracking

1 200706011
4

2

OfferID
3

4911-403C-9C

PriceDisc
6431-4D57-82

10

1 1

2 8

4

0.00

1 1

2 9

4

0.00

1 2

3

4

0.00

1 2

3 3

4

0.00

1 2

3 4

4

0.00

1 2

3 5

4

100.00

4

0.00

• Compresión por

4

1 3

4E0A-4F89-AE

DateId

CarrierTracking

1 200706011
1

1

1

1

1

1

2 9

1

2

3

1

2

1
1

2

3

10

3

4911-403C-9C

2 8

1 3

2

2

OfferID

4

PriceDisc

6431-4D57-82

0.00
4

4

4

4

4

4

3 3

4

4

2

3 4

4

4

2

3 5

4

4E0A-4F89-AE

4
4

100.00
4

diccionario:
• Un valor común de

•

diccionario se almacena en
la página
Los valores comunes son
reemplazados por tokens

• Un ratio de compresión de
2X a 7X para anticipación
de datos reales en tablas
de hecho en un almacén
de datos
Compresión en SQL Server 2008
Compresión de páginas: Consideraciones
• OJO! Compresión de página en HEAPs solo se
realiza con:
•
•
•

BULK INSERT
INSERT INTO…WITH(TABLOCK)
REBUILD con reactivación de compresión por página

• Sentencias DML no se comprimen en HEAPs

• Nosotros hemos de lanzar un ALTER TABLE…WITH
COMPRESSION = PAGE
Compresión en SQL Server 2008
Compresión: Tipos de datos
• No afecta a:
• Varchar,nvarchar,image,text,ntext
• XML, FILESTREAM, varbinary y sql_variant
• Date, time (ya extremadamente compactos)

• Beneficio obtenido 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
…

•
•
•
•
• En todos los tipos de datos, NULL y 0 no ocupan ningun byte
Compresión en SQL Server 2008
Compresión de filas: Sintaxis

• Crear tabla con compresión habilitada (ROW ó
PAGE):

CREATE TABLE T1
(c1 int, c2 nvarchar(50) )
WITH (DATA_COMPRESSION = ROW);

CREATE TABLE PartitionTable1 (col1 int, col2
varchar(max)) ON myRangePS1 (col1)
WITH (
DATA_COMPRESSION = ROW ON PARTITIONS (1),
DATA_COMPRESSION = PAGE ON PARTITIONS (2 TO 4) );

• Activar compresión en tabla ya existente:
ALTER TABLE T1 REBUILD WITH
(DATA_COMPRESSION = ROW);

• Desactivar compresión en tabla:
ALTER TABLE T1 REBUILD WITH
(DATA_COMPRESSION = NONE);
DEMO

Compresión de
páginas
Compresión en SQL Server 2008
BACKUP

• Resultados
Normal

Row
Page

Tiempo (segs)
Espacio (kb)
23
54.90%
36.002 73.62%
51
136.468
14
69.57%
37.159 70.08%
46
124.188
6
64.71%
35.952 63.91%
17
99.616
Compresión en SQL Server 2008

Consideraciones extra
• La compresión puede ser ONLINE u OFFLINE
• Compresión ONLINE con un único thread (paginación
no beneficiada)
• En un HEAP, si existen índices no agrupados, han de ser
recreados para apuntar a las nuevas ubicaciones de las
páginas recién comprimidas
• Se soporta vardecimal por compatibilidad con SQL
2005, pero se considera depreciado debido a
compresión por fila
• Convivencia vardecimal – ROW y PAGE compression
pero sin beneficio
Compresión en SQL Server 2008
Consideraciones extra

• La compresión permite almacenar mas

información por página, pero no por fila

• SQL Server garantiza que la descompresión de
un dato es siempre posible (cabe)
•

No se puede comprimir una tabla donde el tamaño
máximo de una fila + sobrecarga de compresión, superan
8060 bytes
Compresión en SQL Server 2008
Resumen

• Motivación
• Aproximaciones en SQL Server 2008
• Backup comprimidos
• Compresión de datos
•
•

FILA
PÁGINA

• Cómo estimar el ahorro
• Cómo aplicar compresión
• A quién aplicar compresión

Compresión en SQL Server 2008

  • 1.
    Compresión en SQLServer 2008 Enrique Catalá Solid Quality Mentors ecatala@solidq.com
  • 2.
    Compresión en SQLServer 2008 Agenda • Motivación • Aproximaciones en SQL Server 2008 • Backup comprimidos • Compresión de datos • • FILA PÁGINA • Cómo estimar el ahorro • Cómo aplicar compresión • A quién aplicar compresión
  • 3.
    Compresión en SQLServer 2008 Motivación • Cada día se almacena: • Más información – Terabytes con cierta frecuencia • Más variopinta – imágenes, videos, audio, gráficos, mapas • Retos de grandes BDs • Tamaño de base de datos • Manejabilidad de la BD (backup, índices, chekdb, …) • Mecanismo: compresión • A nivel de fichero: o NTFS o BD: backups de base de datos o A nivel de OLTP Sería complicado de manejar comprimir/descomprimir trozos grandes • A nivel de fila / página: o compresión/descompresión de trozos pequeños de información
  • 4.
    Compresión en SQLServer 2008 Motivación • Si reducimos la información almacenada • Tablas/índices más pequeños o Más fácil de gestionar • Ficheros más pequeños o Más fácil de copiar • Se tiende a guardar demasiada información • Otros fabricantes ya lo cubren: Almacenamiento CPU Mejora Rendimiento Oracle -29% +10% +10% DB2 -39% +10% +6%
  • 5.
    Compresión en SQLServer 2008 Aproximaciones • A nivel de fichero • Compresión de BACKUP • • • Ninguno (como hasta ahora*) Compresión de fila – ROW Compresión de página – PAGE • A nivel de datos * Vardecimal cubierto desde SQL 2005 SP2
  • 6.
    Compresión en SQLServer 2008 Aproximación– BACKUP • BACKUP comprimido (Ratios 5:1) • • • Depende de los datos Similar a otros fabricantes. Algoritmo propietario Resultados (para BACKUP y RESTORE) o Menos I/O y menos tiempo o Más CPU – Depende de carga OLTP, pero asumible a partir de 4 Cores • Todos pueden RESTORE con compresión • Sólo Enterprise Edition BACKUP con compresión
  • 7.
    Compresión en SQLServer 2008 BACKUP • Sintaxis: • BACKUP DATABASE ... WITH COMPRESSION • EXEC sp_configure 'backup compression default', '1' • • • • Sin compresión: 131 segundos (2,685 Mb/s) – 361 Mb Con compresión: 49 segundos (7,081 Mb/s) – 44 Mb Ratio 8:1 en tamaño Ratio 2.6:1 en tiempo • Por defecto deshabilitado • Rendimiento real* para AdventureWorks: • Compresion NTFS: 600 segundos – 117 Mb (posterior) • Compresión NTFS: 270 segundos – 117 Mb • Cálculo del rendimiento real en vuestros sistemas: • SELECT backup_size/compressed_backup_size FROM msdb..backupset; * Virtual Server 2005 R2 800Mb Ram, W2003 R2, HP dv9000
  • 8.
  • 9.
    Compresión en SQLServer 2008 Consideraciones compresion BACKUP • No es posible tener en un mismo conjunto, BACKUPS comprimidos y descomprimidos • Uso intensivo de CPU. Podemos limitar su impacto creando un resource pool que limite el uso de CPU a un 20% como máximo • Versiones anteriores de SQL Server no pueden restaurar backups comprimidos • No es necesario especificar nada en el RESTORE
  • 10.
    Compresión en SQLServer 2008 Formatos de compresión – ROW • Compresión a nivel de fila • Eficiencia en almacenamiento de cada columna • Conceptualmente, casi todas las columnas son de longitud • variable. Nulos de longitud fija = nada de espacio • Arreglar “errores” de elección de tipos de datos: • • • Smallint, int, bigint, decimal, numeric, smallmoney, money Datetime, datetime2, timestamp Char, nchar
  • 11.
    Compresión en SQLServer 2008 Compresión de filas: Consideraciones • Se puede aplicar a: • • • • • Tablas almacenadas como HEAP Tablas almacenadas como índices agrupados Índices no agrupados Vistas indexadas Tablas e índices particionados (inclusive de forma independiente cada partición) • La compresión no se activa en los índices no agrupados de forma automática • La compresión no varia al crear un índice agrupado sobre un HEAP • OJO! No soluciona la fragmentación…REINDEXA!
  • 12.
    Compresión en SQLServer 2008 Formatos de compresión – ROW DateId CarrierTracking OfferID PriceDisc 20070601 4911-403C-98 10 0.00 20070601 4911-403C-99 10 0.00 20070602 6431 10 0.00 20070602 6431-4D57-83 10 0.00 20070602 6431-4D57-84 10 0.00 20070602 6431-4D57-85 10 100.00 20070603 4E0A-4F89-AE 10 0.00 DateId CarrierTracking OfferID PriceDisc 20070601 4911-403C-98 10 0.00 20070601 4911-403C-99 10 0.00 20070602 6431 10 0.00 20070602 6431-4D57-83 10 0.00 20070602 6431-4D57-84 10 0.00 20070602 6431-4D57-85 10 100.00 20070603 4E0A-4F89-AE 10 0.00 • Microsoft® SQL Server™ 2005 Service Pack 2 (SP2) • VarDecimal • Habilita que valores decimales puedan ser almacenados en tamaño variable • Máxima precisión requería 17 bytes!!!
  • 13.
    Compresión en SQLServer 2008 Formatos de compresión – ROW DateId CarrierTracking OfferID PriceDisc 20070601 4911-403C-98 10 0.00 20070601 4911-403C-99 10 0.00 20070602 6431 10 0.00 20070602 6431-4D57-83 10 0.00 20070602 6431-4D57-84 10 0.00 20070602 6431-4D57-85 10 100.00 20070603 4E0A-4F89-AE 10 0.00 • Columnas de tamaño fijo: • SQL Server 2008 extiende la lógica a tipos de datos fijos: o int, bigint, datetime, char, etc. DateId CarrierTracking OfferID PriceDisc 20070601 4911-403C-98 10 0.00 20070601 4911-403C-99 10 0.00 20070602 6431 10 0.00 20070602 6431-4D57-83 10 0.00 20070602 6431-4D57-84 10 0.00 20070602 6431-4D57-85 10 100.00 20070603 4E0A-4F89-AE 10 0.00
  • 14.
    DEMO • Vardecimal en SQL2005 • Compresión de filas
  • 15.
    Compresión en SQLServer 2008 Formatos de compresión – PAGE • A nivel de página • Un paso más allá de compresión de fila • Secuencia de 3 fases: 1. Compresión de fila (visto anteriormente) 2. Compresión de prefijos 3. Compresión de diccionario • Cuanto más frecuencia, mayor eficiencia de almacenamiento
  • 16.
    Compresión en SQLServer 2008 Formatos de compresión – PAGE – Prefijos • Segundo paso: reemplazo de prefijos • Los prefijos se almacenan en un área de la página (anchor record) • Prefijos por columna • Cada columna su lista de prefijos • No se expande a todas las columnas • Formato de almacenamiento
  • 17.
    Compresión en SQLServer 2008 Formatos de compresión – PAGE – Prefijos DateId CarrierTracking OfferID PriceDisc 20070601 4911-403C_9 8 10 0.00 20070601 4911-403C_9 9 10 0.00 20070602 6431-4D57_8 2 10 0.00 20070602 6431-4D57_8 3 10 0.00 20070602 6431-4D57_8 4 10 0.00 20070602 6431-4D57_8 5 10 100.00 20070603 4E0A-4F89_AE 10 0.00 DateId CarrierTracking OfferID PriceDisc 200706011 4911-403C_98 8 12 8 11 6431-4D57_82 3 2 3 2 3 2 3 2 3 7 2 11 7 2 11 7 2 11 3 4 7 2 3 11 5 2 4E0A-4F89-AE 2 7 prefijos: • 0.00 10 2 9 • Compresión mediante 100.00 3 • Lista de prefijos se almacena en la página, para prefijos comunes para cada columna Cada valor encontrado se reemplaza por: o Token para el prefijo o Sufijo para el valor
  • 18.
    Compresión en SQLServer 2008 Formatos de compresión – PAGE – Diccionario DateId CarrierTracking 1 200706011 4 2 OfferID 3 4911-403C-9C PriceDisc 6431-4D57-82 10 1 1 2 8 4 0.00 1 1 2 9 4 0.00 1 2 3 4 0.00 1 2 3 3 4 0.00 1 2 3 4 4 0.00 1 2 3 5 4 100.00 4 0.00 • Compresión por 4 1 3 4E0A-4F89-AE DateId CarrierTracking 1 200706011 1 1 1 1 1 1 2 9 1 2 3 1 2 1 1 2 3 10 3 4911-403C-9C 2 8 1 3 2 2 OfferID 4 PriceDisc 6431-4D57-82 0.00 4 4 4 4 4 4 3 3 4 4 2 3 4 4 4 2 3 5 4 4E0A-4F89-AE 4 4 100.00 4 diccionario: • Un valor común de • diccionario se almacena en la página Los valores comunes son reemplazados por tokens • Un ratio de compresión de 2X a 7X para anticipación de datos reales en tablas de hecho en un almacén de datos
  • 19.
    Compresión en SQLServer 2008 Compresión de páginas: Consideraciones • OJO! Compresión de página en HEAPs solo se realiza con: • • • BULK INSERT INSERT INTO…WITH(TABLOCK) REBUILD con reactivación de compresión por página • Sentencias DML no se comprimen en HEAPs • Nosotros hemos de lanzar un ALTER TABLE…WITH COMPRESSION = PAGE
  • 20.
    Compresión en SQLServer 2008 Compresión: Tipos de datos • No afecta a: • Varchar,nvarchar,image,text,ntext • XML, FILESTREAM, varbinary y sql_variant • Date, time (ya extremadamente compactos) • Beneficio obtenido 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 … • • • • • En todos los tipos de datos, NULL y 0 no ocupan ningun byte
  • 21.
    Compresión en SQLServer 2008 Compresión de filas: Sintaxis • Crear tabla con compresión habilitada (ROW ó PAGE): CREATE TABLE T1 (c1 int, c2 nvarchar(50) ) WITH (DATA_COMPRESSION = ROW); CREATE TABLE PartitionTable1 (col1 int, col2 varchar(max)) ON myRangePS1 (col1) WITH ( DATA_COMPRESSION = ROW ON PARTITIONS (1), DATA_COMPRESSION = PAGE ON PARTITIONS (2 TO 4) ); • Activar compresión en tabla ya existente: ALTER TABLE T1 REBUILD WITH (DATA_COMPRESSION = ROW); • Desactivar compresión en tabla: ALTER TABLE T1 REBUILD WITH (DATA_COMPRESSION = NONE);
  • 22.
  • 23.
    Compresión en SQLServer 2008 BACKUP • Resultados Normal Row Page Tiempo (segs) Espacio (kb) 23 54.90% 36.002 73.62% 51 136.468 14 69.57% 37.159 70.08% 46 124.188 6 64.71% 35.952 63.91% 17 99.616
  • 24.
    Compresión en SQLServer 2008 Consideraciones extra • La compresión puede ser ONLINE u OFFLINE • Compresión ONLINE con un único thread (paginación no beneficiada) • En un HEAP, si existen índices no agrupados, han de ser recreados para apuntar a las nuevas ubicaciones de las páginas recién comprimidas • Se soporta vardecimal por compatibilidad con SQL 2005, pero se considera depreciado debido a compresión por fila • Convivencia vardecimal – ROW y PAGE compression pero sin beneficio
  • 25.
    Compresión en SQLServer 2008 Consideraciones extra • La compresión permite almacenar mas información por página, pero no por fila • SQL Server garantiza que la descompresión de un dato es siempre posible (cabe) • No se puede comprimir una tabla donde el tamaño máximo de una fila + sobrecarga de compresión, superan 8060 bytes
  • 26.
    Compresión en SQLServer 2008 Resumen • Motivación • Aproximaciones en SQL Server 2008 • Backup comprimidos • Compresión de datos • • FILA PÁGINA • Cómo estimar el ahorro • Cómo aplicar compresión • A quién aplicar compresión

Notas del editor