Emuler la compression HCC avec la VM ZFS

Pour faire suite à l’article de Jean Pierre Carret, ici , la VM ZFS Virtual Box une fois configurée, va vous permettre de tester la compression HCC qu’Oracle propose uniquement sur ce type de matériel (ainsi que sur les appliances Exadata).

Voici comment, avec quelques exemples pour constater tout l’intérêt de cette fonctionnalité.
Quelques rappels sur les basiques du mécanisme vous sont donnés dans cet article d’Oracle.
 
Voici une synthèse de ma traduction et de ma compréhension :
La technologie Oracle de compression « Hybrid Columnar Compression » permet d’obtenir des taux élevés de compression compris entre x6 et x15 suivant une des quatre options disponibles.
Cette fonctionnalité fait partie intégrante de la version Enterprise Edition et ne nécessite pas l’acquisition d’option supplémentaire (ce qui est suffisamment rare pour être souligné).
Comme son nom l’indique, l’algorithme utilise une combinaison colonnes/lignes pour le stockage de l’information permettant le regroupement efficace des valeurs des colonnes via l’entité « Compression Unit » qui permet de ranger les colonnes d’un ensemble de lignes :
ZFS_HCC_CU
Pour pouvoir utiliser cette méthode, il y a donc quelques restrictions.
Il faut soit :
– Avoir une infrastructure à base d’appliance EXADATA
– Utiliser pour le stockage une baie ZFS
– Utiliser une baie Pillar Axiom 600
Il est possible mais difficile de simuler une appliance Exadata (les VMs d’émulation sont rares et on ne les trouve pas facilement), je ne connais pas d’émulation d’une baie Pillar, par contre l’article de mon collègue cité plus haut permet de disposer d’une pseudo baie de stockage ZFS, et c’est cela qui est intéressant.
Si l’on s’en tient à suivre les étapes décrites dans l’article, on se retrouve avec une partition accessible au travers du protocole iSCSI sur laquelle on peut créer un système de fichiers.
J’ai donc une première VM Oracle Linux sur laquelle j’ai installé une version 12.1.0.2 Oracle Enterprise Edition, et un point de montage « /oraZFS_iscsi » qui est associé à la VM émulation de mon stockage ZFS.
Avec cet environnement, je crée un tablespace sur un sous-répertoire de ce partage :

SQL> create tablespace TESTCOMP datafile '/oraZFS_iscsi/oradata/O1212/testcomp01.dbf' size 1G ;

Et je tente la création d’une table avec une compression de type HCC :

SQL> create table COMP1 compress for query low tablespace users as select * from dba_objects ;
create table COMP1 compress for query low tablespace users as select * from dba_objects
                                                                         *
ERROR at line 1:
ORA-64307:  La compression en colonnes hybrides Exadata n'est pas prise en charge pour les tablespaces sur ce type de stockage

Comme on le voit, l’ensemble des conditions pour cette compression n’est pas respecté, l’utilisation d’un système de fichiers et du protocole iSCSI ne fonctionne pas.
Je suis donc passé sur une configuration différente qui va utiliser les protocoles NFS et dNFS (Oracle Direct NFS) sans ASM (cas validé dans la note de référence).
Pour cela, au travers de l’interface d’administration du ZFS, il faut aller dans la section « Shares » et créer un partage « File System » sous le projet déjà existant.
ZFS_SHARE_FS01
Ici, en résultat mon partage « /zfs1 » qui est exporté en tant que « /export/zfs1 » :
ZFS_SHARE_FS02
Ce que l’on vérifie depuis la VM Oracle Linux par la commande « showmount » :

[root@ele1ole6 ~]# showmount -e myZFS
Export list for myZFS:
/export/zfs1 (everyone)

Je peux monter ce partage avec les options nécessaires via l’ajout de la ligne suivante dans le fichier « /etc/fstab » :

myZFS:/export/zfs1     /orazfs nfs     rw,bg,hard,nointr,rsize=1048576,wsize=1048576,tcp,vers=3,actimeo=0,timeo=600 0 0

A noter que « myZFS » est défini avec l’adresse de la machine virtuelle ZFS Storage sur le réseau interne Virtual Box dans le fichier « /etc/hosts ».
La commande « # /etc/mount /orazfs » effectué sous le compte root permet l’accès au partage :

[root@ele1ole6 ~]# df -h /orazfs
Filesystem            Size  Used Avail Use% Mounted on
myZFS:/export/zfs1
                       43G  1.0G   42G   3% /orazfs

Pour l’utilisation de dNFS (Oracle Direct NFS), deux actions sont à réaliser :
1) Faire en sorte que le noyau Oracle utilise bien la librairie dNFS. Ce module est dynamique en version 12.1 et ne nécessite aucun arrêt des bases associées aux binaires :

[root@ele1ole6 ~]# su - oracle
[oracle@ele1ole6 ~]$ . oraenv
ORACLE_SID = [oracle] ? OR1212
The Oracle base remains unchanged with value /u01/app/oracle
[oracle@ele1ole6 ~]$ cd $ORACLE_HOME/rdbms/lib
[oracle@ele1ole6 lib]$ make -f ins_rdbms.mk dnfs_on
rm -f /u01/app/oracle/product/12.1.0.2/rdbms/lib/odm/libnfsodm12.so; \
    cp /u01/app/oracle/product/12.1.0.2/lib/libnfsodm12.so /u01/app/oracle/product/12.1.0.2/rdbms/lib/odm/libnfsodm12.so

2) Créer un fichier de configuration pour dNFS, par exemple « /etc/oranfstab » avec les informations suivantes :

[oracle@ele1ole6 lib]$ cat /etc/oranfstab
server: myZFS                     --> Le serveur ZFS
local: 192.168.56.101             -->  L'adresse de l'interface du serveur Oracle Linux qui accède le partage
path: 192.168.56.102              --> l'adresse de l'interface du serveur ZFS qui sert le partage
export: /export/zfs1 mount: /orazfs  -->  Export NFS et point de montage

A condition que les droits soient suffisants, on peut créer une arborescence pour les fichiers de la base de données :

 $ mkdir -p /orazfs/oradata/OR1212 

Puis, créer un tablespace de travail qui utilise ce partage :

$ sqlplus / as sysdba
SQL> create tablespace TESTCOMP2 datafile '/oraZFS/oradata/O1212/testcomp2_01.dbf' size 1G ;

Et une table utilisant un des choix de la compression HCC dans ce tablespace. Il n’y a pas d’erreur sur la création de la table et on peut visualiser les attributs liés à la compression (colonnes COMPRESS et COMPRESS_FOR de la vue DBA_TABLES) :

SQL> create table COMP1 compress for query low tablespace TESTCOMP2  as select * from dba_objects ;
Table created
SQL> select table_name, compression , compress_for from dba_tables where tablespace_name='TESTCOMP' ;
TABLE_NAME COMPRESS COMPRESS_FOR
-------- ------------------------------
T1         DISABLED
COMP1      ENABLED  QUERY LOW

On vérifie aussi que le protocole dNFS est bien utilisé en visualisant les fichiers ouverts sur le canal dNFS :

SQL> select filename,filesize from v$dnfs_files ;
FILENAME                                   FILESIZE
----------------------------------------------------
/orazfs/oradata/OR1212/tescomp01.dbf       1073750016

Maintenant que la configuration est valide, réalisons quelques essais pour prouver que le modèle du schéma suivant est vrai :
ZFS_HCC_OPTIONS
Création d’une table non compressée de 555 000 lignes à partir de la table SH.CUSTOMERS du schéma d’exemple qui en contient au départ 55 500 lignes.

SQL> create table NOCOMP_CUSTOMERS tablespace TESTCOMP as select * from SH.customers where 1=2 ;

Puis 10 fois :

SQL>  insert into NOCOMP_CUSTOMERS select * from SH.CUSTOMERS ;
SQL> Commit ;

Création des tables compressées suivant les différents algorithmes disponibles dans l’ordre de la compression la plus basse à la plus haute :

SQL> create table COMP_QUERY_LOW_CUST compress for query low tablespace TESTCOMP as select * from NOCOMP_CUSTOMERS ;
SQL> create table COMP_QUERY_HIGH_CUST compress for query high tablespace TESTCOMP as select * from NOCOMP_CUSTOMERS ;
SQL> create table COMP_ARCH_LOW_CUST compress for archive low tablespace TESTCOMP as select * from NOCOMP_CUSTOMERS ;
SQL> create table COMP_ARCH_HIGH_CUST compress for archive high tablespace TESTCOMP as select * from NOCOMP_CUSTOMERS ;

Vérifions maintenant le résultat, d’abord au travers des attributs des tables :

 1* select table_name, compression , compress_for from dba_tables where table_name like '%COMP_%' and tablespace_name='TESTCOMP'
SQL> /
TABLE_NAME           COMPRESS COMPRESS_FOR
-------------------- -------- ------------------------------
NOCOMP_CUSTOMERS     DISABLED
COMP_QUERY_LOW_CUST  ENABLED  QUERY LOW
COMP_QUERY_HIGH_CUST ENABLED  QUERY HIGH
COMP_ARCH_LOW_CUST   ENABLED  ARCHIVE LOW
COMP_ARCH_HIGH_CUST  ENABLED  ARCHIVE HIGH

Et surtout au niveau de la taille, du nombre de blocs et d’extents pris pour chacune :

SQL> select segment_name, sum(bytes)/1024/1024 "Mo" , sum(blocks) "Blocs" , sum(extents) "Extents"
  from dba_segments where segment_name like '%COMP_%' and tablespace_name='TESTCOMP'
  group by segment_name order by sum(bytes) asc ;
  2    3
SEGMENT_NAME                 Mo      Blocs    Extents
-------------------- ---------- ---------- ----------
COMP_ARCH_HIGH_CUST          10       1280         25
COMP_ARCH_LOW_CUST           14       1792         29
COMP_QUERY_HIGH_CUST         17       2176         32
COMP_QUERY_LOW_CUST          29       3712         44
NOCOMP_CUSTOMERS            120      15360         86

L’évolution suit bien ce qui est documenté avec 10 Mo pour la compression la plus forte (ratio x12) et 29 Mo pour la compression la plus faible (ratio x4,1).
Du coup, on peut vérifier la validité et le taux d’erreurs du package DBMS_COMPRESSION().
Son usage pour la version 12c est décrit dans la note MOS « How to Use DBMS_COMPRESSION.GET_COMPRESSION_RATIO in 12c (Doc ID 1589879.1) »
Avec un appel par type de compression de la forme :

 SET SERVEROUTPUT ON
DECLARE
  l_blkcnt_cmp    PLS_INTEGER;
  l_blkcnt_uncmp  PLS_INTEGER;
  l_row_cmp       PLS_INTEGER;
  l_row_uncmp     PLS_INTEGER;
  l_cmp_ratio     NUMBER;
  l_comptype_str  VARCHAR2(32767);
BEGIN
  DBMS_COMPRESSION.get_compression_ratio (
    scratchtbsname  => 'TESTCOMP',
    ownname         => 'SYS',
    objname         => 'NOCOMP_CUSTOMERS',
    subobjname      => NULL,
    comptype        => DBMS_COMPRESSION.comp_archive_high,
    blkcnt_cmp      => l_blkcnt_cmp,
    blkcnt_uncmp    => l_blkcnt_uncmp,
    row_cmp         => l_row_cmp,
    row_uncmp       => l_row_uncmp,
    cmp_ratio       => l_cmp_ratio,
    comptype_str    => l_comptype_str,
    subset_numrows  => DBMS_COMPRESSION.comp_ratio_allrows,
    objtype         => DBMS_COMPRESSION.objtype_table
  );
  DBMS_OUTPUT.put_line('Number of blocks used (compressed)       : ' ||  l_blkcnt_cmp);
  DBMS_OUTPUT.put_line('Number of blocks used (uncompressed)     : ' ||  l_blkcnt_uncmp);
  DBMS_OUTPUT.put_line('Number of rows in a block (compressed)   : ' ||  l_row_cmp);
  DBMS_OUTPUT.put_line('Number of rows in a block (uncompressed) : ' ||  l_row_uncmp);
  DBMS_OUTPUT.put_line('Compression ratio                        : ' ||  l_cmp_ratio);
  DBMS_OUTPUT.put_line('Compression type                         : ' ||  l_comptype_str);
END;
/

Note : Attention à bien positionner le langage du client SQL*PLUS sur AMERICAN_AMERICA sinon vous serez systématiquement arrêté par le bloc d’erreur :

ERROR at line 1:
ORA-06502: PL/SQL : erreur numerique ou erreur sur une valeur: character to number conversion error
ORA-06512: a "SYS.PRVT_COMPRESSION", ligne 1269
ORA-06512: a "SYS.PRVT_COMPRESSION", ligne 237
ORA-06512: a "SYS.DBMS_COMPRESSION", ligne 218
ORA-06512: a ligne 9

Ce qui nous donne les résultats suivants pour les quatre modes :
Résultat pour « Query low » :

Compression Advisor self-check validation successful. select count(*) on both
Uncompressed and EHCC Compressed format = 555000 rows
Number of blocks used (compressed)       : 3740
Number of blocks used (uncompressed)     : 15153
Number of rows in a block (compressed)   : 148
Number of rows in a block (uncompressed) : 36
Compression ratio                        : 4
Compression type                         : "Compress Query Low"

Résultat pour « Query high » :

Compression Advisor self-check validation successful. select count(*) on both
Uncompressed and EHCC Compressed format = 555000 rows
Number of blocks used (compressed)       : 2214
Number of blocks used (uncompressed)     : 15153
Number of rows in a block (compressed)   : 251
Number of rows in a block (uncompressed) : 36
Compression ratio                        : 6.8
Compression type                         : "Compress Query High"

Résultat pour « Archive Low » :

Compression Advisor self-check validation successful. select count(*) on both
Uncompressed and EHCC Compressed format = 555000 rows
Number of blocks used (compressed)       : 1695
Number of blocks used (uncompressed)     : 15154
Number of rows in a block (compressed)   : 327
Number of rows in a block (uncompressed) : 36
Compression ratio                        : 8.9
Compression type                         : "Compress Archive Low"

Résultat pour « Archive High » :

Compression Advisor self-check validation successful. select count(*) on both
Uncompressed and EHCC Compressed format = 555000 rows
Number of blocks used (compressed)       : 1355
Number of blocks used (uncompressed)     : 15154
Number of rows in a block (compressed)   : 410
Number of rows in a block (uncompressed) : 36
Compression ratio                        : 11.1
Compression type                         : "Compress Archive High"

Et le tableau de synthèse nous donnant le taux d’erreurs du package, en rappelant la prise en compte de toutes les lignes dans le paramétrage de l’appel :
ZFS_SYNTHESE_ERREUR
Moins de 2% d’erreurs pour les taux de compression les plus faibles, par contre près de 6% pour les taux de compression les plus forts, dans un sens ou dans l’autre !
Sur les volumes élevés que l’on va souhaiter traiter l’incidence risque d’être notable, attention à cette marge dans vos estimations.
Maintenant que cette infrastructure est en place, il y a de quoi continuer à expérimenter, par exemple en regardant de plus prêt l’impact sur les performances pour chacun des modes.
Nous pensons chez EASYTEAM que si vous êtes dans une architecture où elle est disponible, cette fonctionnalité est primordiale pour la gestion du cycle de vie de vos données et la gestion de vos évolutions de stockage.
N’hésitez pas à vous faire la main et à commencer à l’appréhender au travers l’utilisation de cette émulation.
Et contactez-nous si vous envisagez son implémentation.
 

1 réflexion sur “Emuler la compression HCC avec la VM ZFS”

  1. Thanks man, you save me few hours. I tried to run DBMS_COMPRESSION.get_compression_ratio with other than american NLSs.

Les commentaires sont fermés.