<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Oracle - Concepts et Exemples &#187; compression</title>
	<atom:link href="https://blog.developpez.com/pachot/tag/compression/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/pachot</link>
	<description>Les fonctionalités et concepts d&#039;Oracle à partir de traductions et de démos</description>
	<lastBuildDate>Sun, 03 Apr 2016 20:36:21 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.42</generator>
	<item>
		<title>12c: les niveaux de compression changent de nom</title>
		<link>https://blog.developpez.com/pachot/compression_ratio/</link>
		<comments>https://blog.developpez.com/pachot/compression_ratio/#comments</comments>
		<pubDate>Tue, 12 Nov 2013 15:27:57 +0000</pubDate>
		<dc:creator><![CDATA[pachot]]></dc:creator>
				<category><![CDATA[12c]]></category>
		<category><![CDATA[compression]]></category>
		<category><![CDATA[HCC]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/pachot/?p=767</guid>
		<description><![CDATA[En 12c les niveaux de compression changent de noms, en présisant le stockage en ligne ou colonne en ligne (ROW STORE): les colonnes d&#8217;une même ligne sont ensembles, les lignes sont stockées les unes à la suite des autres dans &#8230; <a href="https://blog.developpez.com/pachot/compression_ratio/">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>En 12c les niveaux de compression changent de noms, en présisant le stockage en ligne ou colonne</p>
<ul>
<li>en ligne (ROW STORE): les colonnes d&rsquo;une même ligne sont ensembles, les lignes sont stockées les unes à la suite des autres dans des blocs
</li>
<li>ou en colonne (COLUMN STORE): les valeurs des colonnes de plusieurs lignes sont regroupées en vecteurs, Les vecteurs sont stockés dans le Compression Unit<br />
Si vous avez déjà utilisé des <a href="http://docs.oracle.com/cd/E16655_01/appdev.121/e18410/ch_nine.htm#ZZPRE846" title="Host Array">Host Array</a> pour insérer en bulk, c&rsquo;est un peu la même idée. On a une meilleur compression lorsqu&rsquo;on retrouve les mêmes valeurs d&rsquo;une ligne à l&rsquo;autre.
</li>
</ul>
<p><strong>Sans option Advanced compression:</strong></p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">NOCOMPRESS</div></div>
<p>Pas de compression</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ROW STORE COMPRESS BASIC</div></div>
<p>Basic Table Compression (aka &lsquo;COMPRESS&rsquo; ou &lsquo;ROW STORE COMPRESS&rsquo;)<br />
Lors des insert en direct-path, au niveau de chaque bloc, les valeurs dupliquées ne sont stockées qu&rsquo;une fois (en utilisant des pointeurs &#8211; utile seulement pour des tailles supérieures à quelques octets)<br />
Lors de DML conventionnel, les lignes sont décompressées, donc utile en chargement de masse seulement.</p>
<p><strong>Avec option Advanced Compression</strong></p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ROW STORE COMPRESS ADVANCED</div></div>
<p>Advanced Table Compression (aka &lsquo;COMPRESS FOR OLTP&rsquo;)<br />
Même chose que BASIC, mais le DML conventionnel permet de compresser aussi.</p>
<p><strong>sous Exadata et ZFS, avec stockage colonne</strong></p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">COLUMN STORE COMPRESS FOR QUERY LOW/HIGH</div></div>
<p>Warehouse compression (aka Hybrid Columnar Compression QUERY LOW/HIGH)<br />
Stockage en colonne dans des Compression Unit, utilise plus de CPU (surtout en HIGH)<br />
Lors des inserts en direct-path seulement, le DML conventionnel remet les lignes en stockage ligne, donc avec moins bon taux de compression et chained rows.<br />
QUERY: Valable pour des données qui ne sont pas modifiées, mais la lecture est rapide (l&rsquo;économie d&rsquo;I/O compense le surplus de CPU)</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">COLUMN STORE COMPRESS FOR ARCHIVE LOW/HIGH</div></div>
<p>Archive compression (aka Hybrid Columnar Compression ARCHIVE LOW/HIGH)<br />
Stockage en colonne dans des Compression Unit, utilise plus de CPU (surtout en HIGH)<br />
Lors des inserts en direct-path seulement, le DML conventionnel remet les lignes en stockage ligne, donc avec moins bon taux de compression et chained rows.<br />
ARCHIVE: Valable pour des données qui ne sont pas modifiées et peu lues (car forte utilisation CPU pour décompresser aussi)</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Compression SQL*Net, par Jonathan Lewis</title>
		<link>https://blog.developpez.com/pachot/jl_sqlnet_compression/</link>
		<comments>https://blog.developpez.com/pachot/jl_sqlnet_compression/#comments</comments>
		<pubDate>Mon, 10 May 2010 20:04:54 +0000</pubDate>
		<dc:creator><![CDATA[pachot]]></dc:creator>
				<category><![CDATA[Jonathan Lewis]]></category>
		<category><![CDATA[compression]]></category>
		<category><![CDATA[SQL*Net]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Cet article est la traduction d&#8217;un article de Jonathan Lewis publié sur son blog. L&#8217;article original en anglais se trouve ici. Il montre un fonctionnalité peu connue: la compression des données transférées par SQL*Net lorsque il y a répétition de &#8230; <a href="https://blog.developpez.com/pachot/jl_sqlnet_compression/">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<blockquote><p><ins>Cet article est la traduction d&rsquo;un article de Jonathan Lewis publié sur son blog. L&rsquo;article original en anglais se trouve <a href="http://jonathanlewis.wordpress.com/2010/05/07/sqlnet-compression/">ici</a>.<br />
<br />
Il montre un fonctionnalité peu connue: la compression des données transférées par SQL*Net lorsque il y a répétition de valeurs d&rsquo;une ligne à l&rsquo;autre. Et l&rsquo;avantage de récupérer ces données triées sur ces colonnes répétitives.<br />
</ins></p></blockquote>
<p>Voici une petite démonstration que j&rsquo;avais l&rsquo;intention d&rsquo;écrire depuis ces dernières années.<br />
C&rsquo;est très simple: je crée une table, et je l&rsquo;interroge plusieurs fois.</p>
<p><span id="more-13"></span></p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">execute dbms_random.seed(0) <br />
&nbsp;<br />
create table t1 <br />
as <br />
with generator as ( <br />
&nbsp; select &nbsp;--+ materialize <br />
&nbsp; &nbsp; rownum &nbsp; id <br />
&nbsp; from &nbsp;all_objects <br />
&nbsp; where &nbsp;rownum &amp;lt;= 3000 <br />
) <br />
select <br />
&nbsp; lpad(dbms_random.string(&amp;#039;U&amp;#039;,2),40,&amp;#039;X&amp;#039;) &nbsp;v1 <br />
from <br />
&nbsp; generator &nbsp;v1, <br />
&nbsp; generator &nbsp;v2 <br />
where <br />
&nbsp; rownum &amp;lt;= 10000 <br />
; <br />
&nbsp;<br />
break on report <br />
compute sum of number_of_groups on report <br />
&nbsp;<br />
select <br />
&nbsp; group_size, count(*) &nbsp;number_of_groups <br />
from <br />
&nbsp; ( <br />
&nbsp; select <br />
&nbsp; &nbsp; v1, count(*) group_size <br />
&nbsp; from <br />
&nbsp; &nbsp; t1 <br />
&nbsp; group by <br />
&nbsp; &nbsp; v1 <br />
&nbsp; ) <br />
group by <br />
&nbsp; group_size <br />
order by <br />
&nbsp; group_size <br />
;</div></div>
<p>Les données sont dans une seule colonne: une chaîne de 2 caractères aléatoires, complétée à 40 caractères avec des &lsquo;X&rsquo;.<br />
La première requête montre comment les données sont distribuées:</p>
<pre>GROUP_SIZE NUMBER_OF_GROUPS
---------- ----------------
         5                2
         6                5
         7                6
         8               15
         9               27
        10               30
        11               51
        12               55
        13               63
        14               59
        15               78
        16               65
        17               63
        18               54
        19               21
        20               35
        21               19
        22               14
        23                8
        24                5
        26                1
           ----------------
sum                     676
</pre>
<p>Avec la manière dont j&rsquo;ai écrit cette requête, vous pouvez voir qu&rsquo;il y a deux paires de caractères qui apparaissent cinq fois chacune, une paire de caractères qui apparaît 26 fois, et 78 paires de caractères qui apparaissent 15 fois chacune. cela veut dire qu&rsquo;il y a une certaine répétition, et un total de 676 paires de caractères différentes (ce qui n&rsquo;est pas trop surprenant vu que j&rsquo;ai pris 10000 fois de manière aléatoire une paire de lettres de l&rsquo;alphabet majuscule , et que 26 * 26 = 676).</p>
<p>Donc faisons une requête sur toutes ces données à partir de SQL*Plus:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">set arraysize 1000 <br />
set autotrace traceonly statistics <br />
select &nbsp;v1 from &nbsp;t1 ; <br />
select &nbsp;v1 from &nbsp;t1 order by v1; <br />
set autotrace off</div></div>
<p>La sortie n&rsquo;est pas trop grande vu que j&rsquo;ai défini <strong>autotrace</strong> pour n&rsquo;afficher que la trace, et seulement les statistiques. Voici les résultats de la première requête:</p>
<pre>10000 rows selected.

Elapsed: 00:00:00.07

Statistics
----------------------------------------------------------
          4  recursive calls
          0  db block gets
        143  consistent gets
          0  physical reads
          0  redo size
     425479  bytes sent via SQL*Net to client
        494  bytes received via SQL*Net from client
         11  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      10000  rows processed

</pre>
<p>Nous avons récupéré 10000 lignes (<em>rows processed</em>), fait 11 allers-retours réseau (<em>SQL*Net roundtrips</em>), et le volume reçu par le client via SQL*Net est de 420Ko. Avec 10000 lignes qui font environ 40 caractères par ligne, ce chiffre de 420Ko n&rsquo;est pas surprenant. </p>
<p>Mais à quoi vont ressembler les statistiques lors de la seconde requête (celle où j&rsquo;ai ajouté une clause <i><strong>order by</strong></i>):</p>
<pre>
10000 rows selected.

Elapsed: 00:00:00.04

Statistics
----------------------------------------------------------
          4  recursive calls
          0  db block gets
        133  consistent gets
          0  physical reads
          0  redo size
      79287  bytes sent via SQL*Net to client
        494  bytes received via SQL*Net from client
         11  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
      10000  rows processed

</pre>
<p>On peut noter noter que la requête s&rsquo;est terminée plus vite (mais comparer 0,07 secondes à 0,03 seconde n&rsquo;est pas très significatifs). Par contre ce qui est vraiment intéressant, c&rsquo;est que le volume de données transférées sur le réseau est seulement 75Ko environ &#8211; soit pas loin de 6 fois moins de ce qu&rsquo;on pourrait attendre.</p>
<p>Il y a deux questions qui se posent ici:
<ul>
<li>comment avons-nous reçu 10000 lignes d&rsquo;environ 40 octets chacunes, dans seulement 79Ko de données transmises ?</li>
<li>Et, pour pour celui qui observe bien, comment se fait-il que le nombre d&rsquo;aller-retours (SQL*Net roundtrips) n&rsquo;ait pas diminué ? (Je laisse la deuxième question pour un prochain article &#8211; il y a trop de choses à dire là dessus.)</li>
</ul>
<p>Depuis des années, au moins depuis la version 8.0, SQL*Net a été en mesure de faire de la compression (ou plutôt de la &laquo;&nbsp;dé-duplication&nbsp;&raquo;). Si un paquet SQL*Net (appelé &lsquo;SDU&rsquo; &#8211; <em>single session data unit</em> ) contient une répétition de donnée et qui suit le bon pattern, alors SQL*Net peut supprimer les doublons avant la transmission (et bien sûr les remettre lors de la réception).</p>
<p>Le pattern en question est (ou semble être) décrit par: <i>&laquo;&nbsp;Est-ce la ligne a la même valeur que la ligne précédente pour la colonne X ? Si oui alors je n&rsquo;ai pas besoin d&rsquo;envoyer à nouveau le contenu de la colonne X.&nbsp;&raquo;</i> Donc, la dé-duplication se fait d&rsquo;une ligne à l&rsquo;autre: ce n&rsquo;est pas une comparaison entre colonnes, ni une comparaison sur l&rsquo;ensemble du paquet. Cela signifie que si nous trions nos lignes de manière appropriée, nous pouvons maximiser le volume de données pour lequel on aura souvent <i>&laquo;&nbsp;les colonnes de cette ligne&nbsp;&raquo;</i> qui sont souvent identiques aux <i>&laquo;&nbsp;colonnes correspondantes de la ligne précédente&nbsp;&raquo;.</i></p>
<p>Dans mon exemple, evidemment, l&rsquo; <i>order by</i> assure que qu&rsquo;au moins 5 lignes consécutives sont identiques, et celà peut aller jusqu&rsquo;à 26 lignes, ce qui permet d&rsquo;éliminer un nombre important de chaines de 40 caractères.</p>
<p><b>Note:</b> Je peux m&rsquo;avancer à dire que cette dé-duplication fonctionne au moins depuis la version 8 d&rsquo;Oracle (ou plutôt, de SQL*Net) parce que j&rsquo;avais eu une discussion sur les fonctionnalités &lsquo;objet-relationnel&rsquo; juste après la parution de la 8.0<br />
Quelqu&rsquo;un avait essayé de me persuader qu&rsquo;il valait mieux envoyer sur le réseau des <i>&laquo;&nbsp;objets parents incluant plusieurs enregistrements fils&nbsp;&raquo;</i> plutôt que d&rsquo;envoyer <i>&laquo;&nbsp;la jointure du parent avec les fils&nbsp;&raquo;</i>. Leur argument était que l&rsquo;approche objet réduisait le trafic réseau car la jointure répétait les colonnes du parent avec chaque fils contrairement à la méthode objet. Mais, comme j&rsquo;ai pu le souligner, le SQL peut répéter les colonnes, mais SQL*Net élimine cette redondance. (En fait, dans certains cas, l&rsquo;approche objet augmentait le trafic réseau à cause des messages envoyés par le client pour obtenir la définition du type objet &#8211; mais je ne sais pas si c&rsquo;est toujours le cas.)</p>
<blockquote><p><ins>En réponse à un commentaire de Alberto Dell&rsquo;Era, Jonathan Lewis précise que cette dé-duplication se fait dans les deux sens. Il cite un cas particulier d&rsquo;un chargement Informatica où le mode &lsquo;<em>array insert</em>&lsquo; était plus rapide, grâce au moindre volume réseau, que le mode &lsquo;<em>direct-path</em>&lsquo; qui envoit des blocs complets.<br />
</ins></p></blockquote>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
