<?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>Dans la tête de Doc Malkovich &#187; optimisations</title>
	<atom:link href="https://blog.developpez.com/jmalkovich/pcategory/optimisations/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/jmalkovich</link>
	<description>Réflexions et humeurs sur la Business Intelligence</description>
	<lastBuildDate>Tue, 26 Aug 2014 11:54:41 +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>Innovation : le GPU à la rescousse de l&#8217;OLAP</title>
		<link>https://blog.developpez.com/jmalkovich/p9543/bi/innovation_le_gpu_a_la_rescousse_de_l_ol</link>
		<comments>https://blog.developpez.com/jmalkovich/p9543/bi/innovation_le_gpu_a_la_rescousse_de_l_ol#comments</comments>
		<pubDate>Mon, 29 Nov 2010 12:34:25 +0000</pubDate>
		<dc:creator><![CDATA[doc malkovich]]></dc:creator>
				<category><![CDATA[bi]]></category>
		<category><![CDATA[innovation / veille]]></category>
		<category><![CDATA[optimisations]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Si vous êtes un PC gamer vous ne devez pas être insensible à ce terme. Le GPU est un processeur spécifique aux cartes graphiques. Très utilisé dans les jeux, il est dédié aux traitements mathématiques coûteux pour afficher des scènes &#8230; <a href="https://blog.developpez.com/jmalkovich/p9543/bi/innovation_le_gpu_a_la_rescousse_de_l_ol">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Si vous êtes un PC gamer vous ne devez pas être insensible à ce terme. Le GPU est un processeur spécifique aux cartes graphiques. Très utilisé dans les jeux, il est dédié aux traitements mathématiques coûteux pour afficher des scènes en 3D de plus en plus réalistes. </p>
<p>Alors, quel est le rapport entre GPU et la BI me direz-vous ?<br />
<span id="more-39"></span></p>
<p>Et bien le GPU ne sert pas qu&rsquo;à afficher de jolies scènes en 3D, et les fabricants comme nVidia ou AMD offrent la puissance de calcul du GPU aux développeurs. Ainsi de nombreuses applications permettent d&rsquo;encoder des vidéos plus rapidement via le GPU comme Nero Move It ou Cyberlink MediaShow Espresso. Un article sur Clubic explique très bien <a href="http://www.clubic.com/article-275354-1-encoder-carte-graphique.html">l&rsquo;intérêt des GPU</a> et on en parle aussi sur <a href="http://www.developpez.net/forums/d954851/club-professionnels-informatique/actualites/nvidia-met-gpu-computing-disposition-developpeurs-utilisent-visual-studio/">developpez</a>.<br />
<img src="http://ftp-developpez.com/gordon-fowler/NVIDIA.png" alt="" title="" /></p>
<p>En résumé le GPU est bien plus performant dans les calculs simples sur de grosses volumétries comme en 3D &#8230;<br />
Et là on comprend mieux l&rsquo;intérêt de l&rsquo;utiliser pour la BI où les données se comptent en Téra ! </p>
<p>C&rsquo;est du côté de l&rsquo;opensource que les éditeurs se sont lancé avec <a href="http://www.jedox.com/fr/produits/palo-gpu-accelerator.html">Jedox et PALO 3.2</a> qui offre un serveur OLAP de bonne facture. Optimisé avec des cartes nVidia le gain annoncé est important : de 20 à 30 fois &#8230; Mais comme d&rsquo;habitude il faudra attendre un certain temps avant de connaître les performances réelles.</p>
<p>Deux bémols à propos de cette solution :<br />
&#8211; la solution est propre à un seul constructeur, en l&rsquo;occurence nVidia<br />
&#8211; les GPU sont du côté serveur et non du côté client. Donc pas de partie du dernier Call Of Duty au boulot :p</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Optimisation du Refresh d&#8217;une Vue Matérialisée</title>
		<link>https://blog.developpez.com/jmalkovich/p9499/oracle/optimisation_du_refresh_d_une_vue_materi</link>
		<comments>https://blog.developpez.com/jmalkovich/p9499/oracle/optimisation_du_refresh_d_une_vue_materi#comments</comments>
		<pubDate>Tue, 16 Nov 2010 12:45:26 +0000</pubDate>
		<dc:creator><![CDATA[doc malkovich]]></dc:creator>
				<category><![CDATA[optimisations]]></category>
		<category><![CDATA[oracle]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Etrange &#8230; Pour optimiser le refresh des vues matérialisées en refresh full, il vaut mieux les supprimer et les recréer que de les rafraîchir &#8230;( en 10g ) Ainsi un refresh d&#8217;une VM prend 1h, alors que la suppression / &#8230; <a href="https://blog.developpez.com/jmalkovich/p9499/oracle/optimisation_du_refresh_d_une_vue_materi">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Etrange &#8230;</p>
<p>Pour optimiser le refresh des vues matérialisées en refresh full, il vaut mieux les supprimer et les recréer que de les rafraîchir &#8230;( en 10g )<br />
Ainsi un refresh d&rsquo;une VM prend 1h, alors que la suppression / création prend moins de 10 minutes <img src="http://www.developpez.net/forums/images/smilies/calim2.gif" /> !</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Un hint dans BO</title>
		<link>https://blog.developpez.com/jmalkovich/p9387/oracle/un_hint_dans_bo</link>
		<comments>https://blog.developpez.com/jmalkovich/p9387/oracle/un_hint_dans_bo#comments</comments>
		<pubDate>Thu, 14 Oct 2010 12:19:59 +0000</pubDate>
		<dc:creator><![CDATA[doc malkovich]]></dc:creator>
				<category><![CDATA[business objects]]></category>
		<category><![CDATA[optimisations]]></category>
		<category><![CDATA[oracle]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Des fois les plans d&#8217;exécution adoptés par le moteur d&#8217;Oracle ne sont pas forcément les meilleurs. Même si les stats à jour, une requête peut mettre un certain temps, voire ne jamais se terminer ! La solution made in DBA &#8230; <a href="https://blog.developpez.com/jmalkovich/p9387/oracle/un_hint_dans_bo">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Des fois les plans d&rsquo;exécution adoptés par le moteur d&rsquo;Oracle ne sont pas forcément les meilleurs.<br />
Même si les stats à jour, une requête peut mettre un certain temps, voire ne jamais se terminer !</p>
<p>La solution made in DBA consiste généralement à rajouter un hint, c&rsquo;est à dire une petite ligne de code pour forcer le plan d&rsquo;exécution.<br />
<span id="more-17"></span></p>
<p>Exemple :</p>
<blockquote>
<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">SELECT /*+ FULL(SALES) */ <br />
&nbsp; ... <br />
FROM &nbsp;<br />
&nbsp; SALES, &nbsp;<br />
&nbsp; .... <br />
-- ici on ne passe par les index, on lit la table complètement</div></div>
</blockquote>
<p>Pour coder ce hint dans Business Objects, on peut :</p>
<ul>
<li>modifier le sql généré<br />
C&rsquo;est dommage, on perd la fonctionnalité de sql dynamique de BO, avec tous les inconvénients que cela engendre : maintenance difficile, désynchronisation de la requête avec l&rsquo;univers.</li>
<li>modifier la propriété hint de la connexion.<br />
Mais toutes les requêtes seront impactées, ou il faut créer une nouvelle connexion.</li>
<li>créer un nouvel objet</li>
</ul>
<p>Cette dernière solution est à privilégier.<br />
Il suffit de créer un objet technique pointant sur une constante ( 0, 1 ou NULL ), à mettre en 1ère position dans l&rsquo;éditeur de requête.</p>
<p><img src="http://blog.developpez.com/media/bo_hint.gif" width="475" height="401" alt="bo_hint" /></p>
<p>La formule de l&rsquo;objet est </p>
<blockquote><p><code class="codecolorer text default"><span class="text">/*+ FULL(SALES) */ 0</span></code></p></blockquote>
<p>Et on le définit sur la table SALES ( bouton Tables &#8230; ) pour éviter les alertes lors de la vérification de l&rsquo;intégrité de l&rsquo;univers.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Update Oracle 10g massif optimisé / Merge</title>
		<link>https://blog.developpez.com/jmalkovich/p9339/oracle/update_oracle_10g_massif_optimise_merge</link>
		<comments>https://blog.developpez.com/jmalkovich/p9339/oracle/update_oracle_10g_massif_optimise_merge#comments</comments>
		<pubDate>Fri, 01 Oct 2010 12:08:20 +0000</pubDate>
		<dc:creator><![CDATA[doc malkovich]]></dc:creator>
				<category><![CDATA[optimisations]]></category>
		<category><![CDATA[oracle]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Oracle 10g apportait dans son lot de nouveautés l&#8217;instruction MERGE qui correspond à un INSERT or UPDATE, mode d&#8217;alimentation bien connu de nos chers ETL. Les ETL gérant ce mode très bien, j&#8217;avoue n&#8217;en avoir jamais vu l&#8217;utilité, à part &#8230; <a href="https://blog.developpez.com/jmalkovich/p9339/oracle/update_oracle_10g_massif_optimise_merge">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Oracle 10g apportait dans son lot de nouveautés l&rsquo;instruction MERGE qui correspond à un INSERT or UPDATE, mode d&rsquo;alimentation bien connu de nos chers ETL.<br />
Les ETL gérant ce mode très bien, j&rsquo;avoue n&rsquo;en avoir jamais vu l&rsquo;utilité, à part la simplification d&rsquo;écriture dans un script SQL quand on n&rsquo;a pas d&rsquo;ETL sous la main.<br />
Jusqu&rsquo;à ce que je tombe sur un Update somme toute assez classique mais qui durait des plombes.<br />
<span id="more-3"></span><br />
On a une table &laquo;&nbsp;echeancier&nbsp;&raquo; avec un identifiant, une date et un montant.<br />
L&rsquo;update fait la somme des montants à venir :</p>
<blockquote>
<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">UPDATE avenir <br />
SET montant=(SELECT sum(montant) FROM echeancier <br />
WHERE echeancier.id=avenir.id <br />
AND echeancier.datecheance &gt; :dateparametre <br />
AND ( autres filtres ) ;</div></div>
</blockquote>
<p>Oracle utilise bien les index, mais comme la volumétrie est importante, la mise à jour est très longue ( 1h15 ).</p>
<p>La solution classique est de passer par une table temporaire, puis de faire l&rsquo;update. Mais il faut pouvoir créer une table, voire gérer les droits &#8230; Bref, pas très pratique.</p>
<p>Le Merge permet de faire un update massif, sans passer par une table intermédiaire.</p>
<p>Le sql transformé donne :</p>
<blockquote>
<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">MERGE INTO avenir &nbsp;<br />
USING &nbsp;<br />
( SELECT id, sum(montant) montant <br />
FROM echeancier <br />
WHERE echeancier.datecheance &gt; :dateparametre <br />
AND ( autres filtres ) &nbsp; ) x <br />
ON ( avenir.id = x.id ) <br />
WHEN MATCHED THEN UPDATE SET montant=x.montant;</div></div>
</blockquote>
<p>Oracle n&rsquo;utilise plus les index, mais on passe de 1h 15 à 2&prime; 20.<br />
( 2&rsquo;40 en passant par une table temporaire )</p>
<p>Que du bonheur</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sélectionner l&#8217;enregistrement max en une seule fois &#8211; la clause magique keep</title>
		<link>https://blog.developpez.com/jmalkovich/p9315/oracle/selectionner_l_enregistrement_max_en_une</link>
		<comments>https://blog.developpez.com/jmalkovich/p9315/oracle/selectionner_l_enregistrement_max_en_une#comments</comments>
		<pubDate>Thu, 23 Sep 2010 11:48:46 +0000</pubDate>
		<dc:creator><![CDATA[doc malkovich]]></dc:creator>
				<category><![CDATA[business objects]]></category>
		<category><![CDATA[odi / sunopsis]]></category>
		<category><![CDATA[optimisations]]></category>
		<category><![CDATA[oracle]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Une problématique récurrente dans les traitements décisionnels est de récupérer le dernier enregistrement d&#8217;une série, par exemple les dernières opérations des clients en ayant en source une table contenant toutes les opérations. Avoir uniquement la dernière date d&#8217;opération est simple, &#8230; <a href="https://blog.developpez.com/jmalkovich/p9315/oracle/selectionner_l_enregistrement_max_en_une">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Une problématique récurrente dans les traitements décisionnels est de récupérer le dernier enregistrement d&rsquo;une série, par exemple les dernières opérations des clients en ayant en source une table contenant toutes les opérations.<br />
<span id="more-36"></span><br />
Avoir uniquement la dernière date d&rsquo;opération est simple, rapide et à portée de tous:</p>
<blockquote>
<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">/* exemple ** <br />
with operations <br />
as ( &nbsp;<br />
select 1 idclient, sysdate dat, 4 val from dual union all <br />
select 1 idclient, sysdate+1 dat, 8 val from dual union all <br />
select 1 idclient, sysdate+2 dat, 7 val from dual union all <br />
select 2 idclient, sysdate dat, 2 val from dual ) */ <br />
select idclient, max(dat) from operations group by idclient</div></div>
</blockquote>
<p>Par contre si on veut récupérer d&rsquo;autres informations de cet enregistrement, il faut passer par une sous-requête :</p>
<blockquote>
<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">select idclient, &nbsp;dat, &nbsp;val <br />
from operations a <br />
where a.dat=(select max(b.dat) from operations b where b.idclient=a.idclient )</div></div>
</blockquote>
<p>Le problème est ( entre autres ) qu&rsquo;on passe 2 fois sur la table operations, ce qui dégrade les performances. </p>
<p>Oracle propose depuis la 9i les fonctions analytiques, ce qui est bien pratique pour gérer ce type de problème.<br />
On utilisera par exemple la fonction row_number(), mais on aura toujours une sous-requête :</p>
<blockquote>
<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">select idclient, dat, val from ( <br />
&nbsp; select idclient, dat, val, <br />
&nbsp; &nbsp; row_number() over(partition by idclient order by dat desc) num <br />
&nbsp; from operations <br />
) <br />
where num=1</div></div>
</blockquote>
<p>Cette solution n&rsquo;est pas forcément simple à implémenter du fait de la sous-requête. Un ETL comme Sunopsis/ODI ne gère pas les sous-requêtes, il faut passer par des vues et du coup on perdra le lien dans l&rsquo;analyse d&rsquo;impact de l&rsquo;outil.<br />
Solution miracle, on a une requête en one-shot avec la clause keep :</p>
<blockquote>
<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">select idclient, <br />
&nbsp; max(dat), <br />
&nbsp; max(val) keep (dense_rank last &nbsp;order by dat) val <br />
from operations <br />
group by idclient</div></div>
</blockquote>
<p>Cerise sur le gâteau, on peut aussi utiliser ce type de clause dans un univers Business Objects, cela évite de passer par une table dérivée ou du sql en dur.</p>
<p>Que du bonheur.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
