ArKZoYd

Made in France by Grégory Guillou

05 février 2010

Perl, DBD::Oracle, GD::Graph, etc

Si vous utilisez Oracle, vous utilisez Perl ! Oracle Remote Diagnostic Agent (aka RDA), l'agent Enterprise Manager, ou l'outil de clone (aka clone.pl) utilisent en effet le langage de script inclus avec le logiciel Oracle et portable sur de nombreux OS. Facile, Perl permet en particulier de manipuler des jeux de données ou de travailler avec des expressions régulières en quelques lignes...

Dans cet article, je vous propose d'utiliser les bibliothèques adéquates pour créer des graphiques à partir de données stockées en base. Et voilà une autre alternative à Java, Excel, APEX, Google Chart ou encore Python pour représenter des données souvent incompréhensibles sans quelques graphiques.

Des bibliothèques utiles

Un des intérêts de Perl réside dans la communauté très active et dans le nombre incroyables de bibliothèques. Pour ce qui suit, installez DBD::Oracle, GD:Graph et Data::Pivot, comme ci-dessous; commencez par installer un client 11g et par configurer les variables d'environnement correspondantes avant de lancer les installations comme ci-dessous, si vous disposez d'un accès Internet:
sudo perl -MCPAN -e shell 

CPAN> install GD::Graph

CPAN> install DBD::Oracle

CPAN> install Data::Pivot
Une fois les bibliothèques installées, vous pouvez simplement accéder à la documentation associées avec perldoc comme ci-dessous :
perldoc DBD::Oracle

Un exemple simple

Vous ne manquez surement pas d'idées pour créer des graphiques. Pour illustrer la combinaison des 3 bibliothèques ci-dessus, voici un exemple qui utilise le contenu d'Oracle AWR pour suivre l'évolution de l'espace occupé dans vos tablespaces.
Notez bien que pour exécuter la requête ci-dessous, vous devez avoir une licence d'Oracle Diagnostic Pack
Si vous venez de créer votre base de données et qu'il n'y a pas véritablement d'historique dans AWR, vous pouvez commencer par lancer le script ci-dessous qui va faire évoluer sur un intervalle de quelques clichés l'espace occupé dans vos tablespaces :
create table X(text varchar2(4000)) tablespace users;

begin
for i in 1..10 loop
for j in 1..10240 loop
insert into X values (rpad('X',1024, 'X'));
end loop;
commit;
dbms_lock.sleep(10);
dbms_workload_repository.create_snapshot;
end loop;
end;
/
drop table X purge;
exec dbms_workload_repository.create_snapshot
La requête suivante extrait les données d'AWR qui correspondent à notre futur graphe:
select vts.tsname, 
to_char(s.END_INTERVAL_TIME, 'YYYY-MM-DD HH24:MI:SS') timestamp,
ts.TABLESPACE_USEDSIZE
from dba_hist_tbspc_space_usage ts,
dba_hist_snapshot s,
dba_hist_tablespace_stat vts
where s.snap_id=ts.snap_id
and s.dbid=ts.dbid
and s.snap_id=vts.snap_id
and s.dbid=vts.dbid
and ts.tablespace_id=vts.ts#(+)
order by 1, 3;

Le programme Perl

Vous imaginez le principe? Voici le programme Perl qui crée le graphique correspondant à la requête. En substance, ce programme:
  • Se connecte à la base de données en "/ as sysdba" et exécute la-dite requête
  • pivote les données selon l'axe X
  • Utilise GD::Graph pour créer un graphe cumulé
  • Enregistre un fichier .PNG correspondant au graphe
Le script complet est disponible ci-dessous:
#!/usr/bin/perl
use strict;
use DBI;
use DBD::Oracle qw(:ora_session_modes);
use Data::Pivot;
use GD::Graph::area;
#use Data::Dumper;

#
# Etape 1. Connexion à la base de données et exécution de la requête
#
my $dbh = DBI->connect('DBI:Oracle:', '', '', { ora_session_mode => ORA_SYSDBA } )
or die "Impossible de se connecter à la base de données: " . DBI->errstr;

my $query=q{
select vts.tsname,
to_char(s.END_INTERVAL_TIME, 'YYYY-MM-DD HH24:MI:SS') timestamp,
ts.TABLESPACE_USEDSIZE
from dba_hist_tbspc_space_usage ts,
dba_hist_snapshot s,
dba_hist_tablespace_stat vts
where s.snap_id=ts.snap_id
and s.dbid=ts.dbid
and s.snap_id=vts.snap_id
and s.dbid=vts.dbid
and ts.tablespace_id=vts.ts#(+)
order by 1, 3
};

my $sth = $dbh->prepare($query)
or die "Impossible de préparer la commande: " . $dbh->errstr;

$sth->execute();

my @dset=$sth->fetchall_arrayref ;

#
# Etape 2. Pivot de la table de données pour afficher
# Y=Tablespace
# X=Time
#
my @xlabel = ('Tablespace', 'Time', '');
my @newdset = pivot( table => @dset,
headings => \@xlabel,
pivot_column => 1,
layout => 'vertical',
row_sum => undef,
row_titles => 0,
format => '%5.2f',
);

shift (@xlabel);

my @ylabel = ();
for my $i ( 0 .. $#newdset ) {
push @ylabel, $newdset[$i][0];
shift (@{$newdset[$i]});
}

unshift (@newdset,\@xlabel);

#
# Etape 2'. Utilisation de Data::Dumper pour afficher le contenu
# des tableaux
#
#print Dumper @newdset;
#print Dumper @ylabel;
#print Dumper @xlabel;

#
# Etape 3. Création du fichier graphique .PNG à partir des tableaux
#
my $mygraph = GD::Graph::area->new(600, 400);
$mygraph->set(
x_label => 'Time',
y_label => 'Used Blocks',
title => 'Space Usage Trend',
# Draw datasets in 'solid', 'dashed' and 'dotted-dashed' lines
line_types => [1],
x_label_skip => 1,
x_labels_vertical => 1,
# Set the thickness of line
line_width => 1,
cumulate => 1,
# Set colors for datasets
# borderclrs => ['lred'],
# dclrs => ['lred'],
) or warn $mygraph->error;

$mygraph->set_legend_font(GD::gdMediumBoldFont);

$mygraph->set_legend(@ylabel);

my $data = GD::Graph::Data->new(\@newdset)
or die GD::Graph::Data->error;

my $myimage = $mygraph->plot($data) or die $mygraph->error;

#
# Etape 4. Enregistrement du fichier correspondant
#
open(IMG, ">mygraphic.png") or die $!;
binmode IMG;
print IMG $myimage->png;
close IMG;

Le résultat

Le résultat est un graphique que vous n'aurez aucun mal à personaliser.

Conclusion

Vous pourrez facilement enrichir cet exemple avec des paramètres, Apache, CGI, GD::Graph3d, GD::Graph::Map et bien d'autres idées... Maintenant, faites-vous plaisir!
(Lire la suite..)

11gR2 Exadata Hybrid Columnar Compression (aka EHCC) et VOS données

Si vous avez assisté à quelques unes des nombreuses présentations à propos d'Oracle 11g Release 2, vous avez sans doute entendu dire que vous pouvez compresser vos données avec des ratios de 10, 20 ou même 50 ! Votre Data Warehouse contient des tables de plusieurs centaines de Go, voire de plusieurs To; le retour sur investissement de cette fonctionnalité pourrait être instantanné dans votre cas et votre société économiserait alors plusieurs dizaines de k€ dès 2010, sans compter la promesse d'améliorer de manière drastique les temps de réponse de vos requêtes pour votre système décisionnel.

Seulement voilà, si la fourchette des taux de compression est si large, c'est que ces taux dépendent pour une bonne partie de vos données. La question pertinente est donc: "Combien pouvez-vous espérer de EHCC dans votre contexte?". La réponse à cette question mérite bien quelques minutes de votre temps et c'est le sujet de cet article.

Echantillon de données

Pour répondre à cette question, échantillonnez vos données dans un système Oracle 11g Release 2 sur Linux x86 ou x86_64. Utilisez la méthode de votre choix: RMAN, DataPump, Database Link, un bon vieux export ou ce que vous voulez. Pour allez plus vite, n'hésitez pas à utilisez la clause SAMPLE des ordres SELECT comme discuté un de mes articles précédents.

DBMS_COMPRESSION

Oracle 11g Release 2 offre une procédure dans le package DBMS_COMPRESSION nommé GET_COMPRESSION_RATIO. Cette procédure réalise la compression dans un tablespace "scratch" pour en déduire la taille du segment compressé. Voici un exemple d'utilisation ci-dessous; je commence par créer une table X qui représente mon échantillon de données dans le schéma scott:
sqlplus / as sysdba

alter user scott identified by tiger;

grant dba to scott;

connect scott/tiger

create table X(text varchar2(4000)) tablespace users;

begin
for i in 1..100000 loop
insert into X values (rpad('X',1024));
end loop;
for i in 1..1000000 loop
insert into X values ('X');
end loop;
end;
/
commit;
Je peux ensuite lancer l'advisor:
set serveroutput on
declare
v_blkcnt_cmp BINARY_INTEGER;
v_blkcnt_uncmp BINARY_INTEGER;
v_row_cmp BINARY_INTEGER;
v_row_uncmp BINARY_INTEGER;
v_cmp_ratio NUMBER;
v_comptype_str varchar2(100);
begin
DBMS_COMPRESSION.GET_COMPRESSION_RATIO (
scratchtbsname => 'USERS',
ownname => user,
tabname => 'X',
partname => null,
comptype => dbms_compression.COMP_FOR_QUERY_HIGH,
blkcnt_cmp => v_blkcnt_cmp,
blkcnt_uncmp => v_blkcnt_uncmp,
row_cmp => v_row_cmp,
row_uncmp => v_row_uncmp,
cmp_ratio => v_cmp_ratio,
comptype_str => v_comptype_str);
dbms_output.put_line('taux de compression: '||to_char(v_cmp_ratio)||' '||v_comptype_str);
end;
/
Le résultat est très encourageant... si vous stockez toujours la même ligne ;-).
Compression Advisor self-check validation successful. select count(*) on both
Uncompressed and EHCC Compressed format = 1000001 rows
taux de compression: 238.6 "Compress For Query High"

Quelques ORA-

Il est possible que vous rencontriez quelques difficultés dans la mise en oeuvre de l'advisor; voici quelques unes de celles que j'ai pu expérimenter :
  • Si vous utilisez une version Oracle 11.2.0.1 sans patch, vous obtiendrez l'erreur ci-dessous; pour faire fonctionner l'advisor, installer le patch : 8896202: ENABLE COMPRESSION ADVISOR TO ESTIMATE EXADATA HCC COMPRESSION RATIOS
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at "SYS.PRVT_COMPRESSION", line 461
ORA-64307: hybrid columnar compression is only supported in tablespaces
residing on Exadata storage
ORA-06512: at "SYS.DBMS_COMPRESSION", line 214
ORA-06512: at line 9
  • Pour utiliser l'advisor vous devez avoir au moins un millions de lignes dans votre table échantillon:
ERROR at line 1:
ORA-20000: Compression Advisor must have at least 1000000 rows in this
table/partition segment (segment has 102400 rows)
ORA-06512: at "SYS.PRVT_COMPRESSION", line 695
ORA-06512: at "SYS.DBMS_COMPRESSION", line 215
ORA-06512: at line 9
  • Enfin l'advisor ne fonctionne pas sous l'utilisateur SYS:
declare
*
ERROR at line 1:
ORA-12988: cannot drop column from table owned by SYS
ORA-06512: at "SYS.PRVT_COMPRESSION", line 695
ORA-06512: at "SYS.DBMS_COMPRESSION", line 215
ORA-06512: at line 9

Conclusion

Et voilà; il n'y a plus qu'à! Et vous qu'est-ce que vous obtenez ?
(Lire la suite..)

Coloriez votre SQL

Si vous avez la chance d'avoir des licenses Oracle Diagnostic Pack, AWR n'a pas de secret pour vous ! Vous avez, sans doute, déjà configuré le framework qui stocke les statistiques d'utilisation de vos bases Oracle 10g et 11g à l'aide de dbms_workload_repository.modify_snapshot_settings. La procédure permet en effet de changer les seuils de capture des ordres SQL les plus consommateurs. Vous pouvez ainsi jouer sur le niveau d'information collectées à propos des ordres SQL les plus consomateurs selon "Elapsed Time", "CPU Time", "User I/O Wait Time", "Gets", "Reads", "Physical Reads", "Executions", "Parse Calls", "Sharable Memory" ou "Version Count". Mais savez-vous qu'il est également possible de forcer les snapshots AWR à capturer les ordres SQL de votre choix ? C'est le propos de la procédure dbms_workload_repository.add_colored_sql qui permet, littéralement et poétiquement, de colorier vos ordres SQL. Dans ce qui suit, vous trouverez un exemple d'utilisation de ce package...

Requête de votre application et SQL_ID

Pour les besoins de l'exemple, nous avons besoin d'une requête de l'application peu consommatrice de sorte qu'elle ne serait, en temps normal et avec les paramétrages par défaut pas collectée par AWR. Voici un exemple de requête sur le schéma SCOTT :
var empno number;
exec :empno:=7788;
select ename
from scott.emp
where empno = :empno;

col sql_text format a55
col sql_id format a15 new_value sqlid

select sql_id, substr(sql_text,1,55) sql_text
from v$sql
where regexp_like(sql_text, 'scott.*[:]empno');

SQL_ID SQL_TEXT
--------------- --------------------------------------------------
chz451r0u50fa select ename from scott.emp where empno = :empn

Coloriez votre requête

Vous pouvez alors colorier votre requête et vérifier dans la vue dba_hist_colored_sql que le SQL_ID est enregistré:
exec dbms_workload_repository.add_colored_sql(sql_id=>'&&sqlid')

SQL> select * from dba_hist_colored_sql;

DBID SQL_ID CREATE_TI
---------- --------------- ---------
394277766 chz451r0u50fa 04-FEB-10

Capturer un cliché

Attendez que le cliché AWR soit généré automatiquement ou forcez la capture d'un nouveau cliché comme ci-dessous:
exec dbms_workload_repository.create_snapshot

Visualiser les détails d'exécution

Pour visualiser le détail d'exécution, vous pouvez utiliser le script awrsqrpt.sql comme ci-dessous:
SQL> @?/rdbms/admin/awrsqrpt

Current Instance
~~~~~~~~~~~~~~~~

DB Id DB Name Inst Num Instance
----------- ------------ -------- ------------
394277766 BLACK 1 BLACK


Specify the Report Type
~~~~~~~~~~~~~~~~~~~~~~~
Would you like an HTML report, or a plain text report?
Enter 'html' for an HTML report, or 'text' for plain text
Defaults to 'html'
Enter value for report_type: text

Type Specified: text


Instances in this Workload Repository schema
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

DB Id Inst Num DB Name Instance Host
------------ -------- ------------ ------------ ------------
* 394277766 1 BLACK BLACK arkzoyd-easy
team

Using 394277766 for database Id
Using 1 for instance number


Specify the number of days of snapshots to choose from
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Entering the number of days (n) will result in the most recent
(n) days of snapshots being listed. Pressing without
specifying a number lists all completed snapshots.


Enter value for num_days: 1

Listing the last day's Completed Snapshots

Snap
Instance DB Name Snap Id Snap Started Level
------------ ------------ --------- ------------------ -----
BLACK BLACK 1 04 Feb 2010 14:00 1
[...]
17 04 Feb 2010 22:00 1
18 04 Feb 2010 22:09 1

Specify the Begin and End Snapshot Ids
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Enter value for begin_snap: 17
Begin Snapshot Id specified: 17

Enter value for end_snap: 18
End Snapshot Id specified: 18


Specify the SQL Id
~~~~~~~~~~~~~~~~~~
Enter value for sql_id: chz451r0u50fa
SQL ID specified: chz451r0u50fa

Specify the Report Name
~~~~~~~~~~~~~~~~~~~~~~~
The default report file name is awrsqlrpt_1_17_18.txt. To use this name,
press to continue, otherwise enter an alternative.

Enter value for report_name: sql_chz451r0u50fa.txt

Using the report name sql_chz451r0u50fa.txt

WORKLOAD REPOSITORY SQL Report

Snapshot Period Summary

DB Name DB Id Instance Inst Num Startup Time Release RAC
------------ ----------- ------------ -------- --------------- ----------- ---
BLACK 394277766 BLACK 1 04-Feb-10 19:03 11.2.0.1.0 NO

Snap Id Snap Time Sessions Curs/Sess
--------- ------------------- -------- ---------
Begin Snap: 17 04-Feb-10 22:00:44 24 1.5
End Snap: 18 04-Feb-10 22:09:43 24 1.4
Elapsed: 8.99 (mins)
DB Time: 0.01 (mins)

SQL Summary DB/Inst: BLACK/BLACK Snaps: 17-18

Elapsed
SQL Id Time (ms)
------------- ----------
chz451r0u50fa 6
Module: sqlplus@arkzoyd-easyteam (TNS V1-V3)
select ename from scott.emp where empno = :empno

-------------------------------------------------------------

SQL ID: chz451r0u50fa DB/Inst: BLACK/BLACK Snaps: 17-18
-> 1st Capture and Last Capture Snap IDs
refer to Snapshot IDs witin the snapshot range
-> select ename from scott.emp where empno = :empno

Plan Hash Total Elapsed 1st Capture Last Capture
# Value Time(ms) Executions Snap ID Snap ID
--- ---------------- ---------------- ------------- ------------- --------------
1 2949544139 6 1 18 18
-------------------------------------------------------------

Plan 1(PHV: 2949544139)
-----------------------

Plan Statistics DB/Inst: BLACK/BLACK Snaps: 17-18
-> % Total DB Time is the Elapsed Time of the SQL statement divided
into the Total Database Time multiplied by 100

Stat Name Statement Per Execution % Snap
---------------------------------------- ---------- -------------- -------
Elapsed Time (ms) 6 5.6 1.0
CPU Time (ms) 4 4.0 0.7
Executions 1 N/A N/A
Buffer Gets 40 40.0 0.2
Disk Reads 1 1.0 1.7
Parse Calls 1 1.0 0.1
Rows 1 1.0 N/A
User I/O Wait Time (ms) 0 N/A N/A
Cluster Wait Time (ms) 0 N/A N/A
Application Wait Time (ms) 0 N/A N/A
Concurrency Wait Time (ms) 0 N/A N/A
Invalidations 0 N/A N/A
Version Count 1 N/A N/A
Sharable Mem(KB) 14 N/A N/A
-------------------------------------------------------------

Execution Plan
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 20 | 2 (0)| 00:00:01 |
| 2 | INDEX UNIQUE SCAN | PK_EMP | 1 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------

Full SQL Text
SQL ID SQL Text
------------ -----------------------------------------------------------------
chz451r0u50f select ename from scott.emp where empno = :empno

Report written to sql_chz451r0u50fa.txt

Décolorer les ordres SQL

Pour décolorer vos ordres SQL, utilisez la procédure dbms_workload_repository.remove_colored_sql:
select * from dba_hist_colored_sql;

DBID SQL_ID CREATE_TI
---------- ------------- ---------
394277766 chz451r0u50fa 04-FEB-10

exec dbms_workload_repository.remove_colored_sql(-
sql_id=>'chz451r0u50fa')

select * from dba_hist_colored_sql;

no rows selected
Cet outil d'Oracle 11g permet de suivre facilement des indicateurs clés sur les requêtes pertinentes pour votre application. Il ne vous reste plus qu'à explorer les vues DBA_HIST_* avec soin...
(Lire la suite..)

26 janvier 2010

1, 2 et 3 OCM

C'est mon très grand plaisir d'accueillir 2 nouvelles Oracle Certified Mistresses (OCM) et Oracle Alumini qui vont devoir me supporter; elles aussi... Bravo Audiane et Isabelle ! Cette bouteille de champagne que je bois ce matin, c'est la votre :-) (Lire la suite..)

16 janvier 2010

Oracle VM : Principes, bénéfices et la solution packagée d'Easyteam


En moins de 9', découvrez Oracle VM, ses bénéfices pour votre entreprise et pour vous ainsi que l'offre Easyteam pour l'implémenter dans votre contexte; Vous découvrirez peut-être la réponse à vos questions:
  • Comment réduire les coûts Oracle mais aussi matériels ?
  • Comment tirer avantages des serveurs multi-cores et consolider vos environnements ?
  • Comment garantir support des produits et performances avec Oracle sur des environnements virtualisés ?
  • Comment déployer, superviser, sauvegarder ou cloner facilement Oracle ?
  • Comment réduire vos risques au minimum ?
  • Comment pouvez-vous être opérationnels en 15 jours ?
  • Comment OracleVM permet de résoudre vos problèmes insolubles jusqu'à présent avec VMWare?
Cette présentation video, vous donnera, à n'en pas douter, de nouvelles perspectives pour qu'Oracle devienne "Facile"(*) pour vous... dès 2010!

(*) Facile grâce à Easyteam?
(Lire la suite..)

15 janvier 2010

Le CPUJan2001 et les nouveaux PSU sont dehors

Le Critical Patch Update de janvier 2010 est dehors; A en croire le système de notation (CVSS), Oracle Database 10g et 11g Release 1 sont de loin les virus les plus déployés sur Unix et Linux. Du coup, j'ai passé ma nuit à mettre à jour tous mes systèmes bases de données, Clusterware et GridControl qui n'étaient pas déjà 11.2 avec les derniers PSU; Tant qu'à faire de passer un patch! Si vous avez encore des bases 10g ou 11g, précipitez-vous... (Lire la suite..)