PCT COST ? Comment 7271 peut-il représenter 0% de 2 ?

Si on effectue une requête SQL et que l’on demande l’affichage de son plan d’exécutio par défaut on obtient le coût individuel de chaque action, ainsi un parcours complet de table ou d’index est associé à un coût global associé à son pourcentage de coût CPU et c’est là que ça se complique un poil. En effet, si on interroge directement les tables ou les vues du dictionnaire la relation en le contenu de la colonne CPU_COST des tables contenant les plans d’exécution rapportée à la colonne COST contenant le coût global de la l’action, on est loin de trouver un rapport quelconque avec le pourcentage affiché.

select * from sys.dual ;

D
-
X

select * from table(dbms_xplan.display_cursor()) ;

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
SQL_ID  cps942q7r3w9m, child number 0
-------------------------------------
select * from sys.dual

Plan hash value: 272002086

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |       |       |     2 (100)|          |
|   1 |  TABLE ACCESS FULL| DUAL |     1 |     2 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------


13 rows selected.

l
  1  select id
  2       , lpad(' ',DEPTH)||OPERATION||' '||OPTIONS operation
  3       , OBJECT_NAME NAME
  4       , CARDINALITY "ROWS"
  5       , BYTES
  6       , COST
  7       , CPU_COST
  8       , IO_COST
  9  from v$sql_plan
 10* where plan_hash_value=272002086
/

        ID OPERATION            NAME  ROWS  BYTES  COST   CPU_COST    IO_COST
---------- -------------------- ---- ----- ------ ----- ---------- ----------
         0 SELECT STATEMENT                           2
         1  TABLE ACCESS FULL   DUAL     1      2     2       7271          2

(suite…)

Créer un plan d’exécution graphique avec les interfaces de programmation (API) google

L’affichage d’un plan d’exécution de manière graphique est toujours appréciable et le web propose pléthores d’API pour le faire. Parmis elles google visualization qui permet entr’autres choses de faire de jolis graphiques et d’afficher de manière simple des organigrammes ou pourquoi pas des plans d’exécution de requêtes SQL.

On peut trouver les plans d’exécution dans diverses tables de la base de donnée. Ici, j’ai choisi d’afficher un plan d’exécution pioché dans la table dba_hist_sql_plan et donc sort d’un historique AWR. Je pré suppose que je connais le SQLID et la valeur de hashage du plan à afficher (plan hash value).

Si on s’intéresse à la brique orgchart de google visualization API on s’apperçoit qu’il suffit de lui donner un tableau javascript contenant au minimum des identifiants uniques dans la première colonne et l’identifiant du pêre dans une deuxième colonne pour que l’arbre s’affiche : de jolies cases bleues contant les identifiants uniques … Ok, ce n’est pas transcendant, mais c’est déjà un premier pas : pas besoin de requête hyérarchique pour afficher une hyérarchie et comble de bonheur le travail est partagé entre la base de donnée et le client

(suite…)

SQLPlus l(e seul)’outil qu’il vous faut pour administrer vos bases de données Oracle

Cet article est repris d’un ancien blog et fusionné avec un autre

SQLPlus est l’outil incontournable du DBA Oracle. Même si beaucoup n’utilisent que des interfaces graphiques, il arrive un moment ou un autre où il doit se connecter à une machine qui ne propose pas cette commodité et dès lors, l’outil basique, livré avec le moteur, devient un passage obligé voire incontournable ou presque.

Je liste ici quelques trucs, astuces, commandes qui permettent d’utiliser SQLPlus de manière sympathique et sans trop de prise de tête.

(suite…)

INDEX FULL SCAN et INDEX FAST FULL SCAN

Suite à un échange à propos du fonctionnement du CBO et plus particulièrement sur les choix de parcours d’index en full scan ou en fast full scan sur le forum developpez.net qui était de la teneur suivante :

Intervenant 1 – Est-il vrai que si on effectue le requête select ename from emp, oracle n’utilisera pas l’index même si celui-ci existe ?
Intervenant 2 – Vrai sauf si la colonne ename ne peut pas être nulle et ce par contrainte, auquel cas un index full scan sera choisi
Intervenant 3 – Ne vouliez vous pas dire index fast full scan ?
Intervenant 2 – Non :
(suite…)

sql2csv ou comment générer un fichier csv depuis SQL*PLUS

La question revient souvent sur les forums : comment produire un fichier csv depuis SQL*Plus

Une solution a été donnée sur le forum Developpez.net, elle est copiée ici dans une version un peu remaniée et très légèrement plus générique

L’appel est simple depuis sqlplus: @sql2csv <nom du fichier contenant la(les) requête(s) à exporter en csv>

-- merci à skuatamad (http://www.developpez.net/forums/u253956/skuatamad/)
  --
  -- 1 paramètre : le nom du script sql à exécuter
  -- En sortie un fichier CSV
  --
  
  store set settings_sqlplus replace
  
  set echo off
  set feedback off
  set linesize 32767
  set pages 0 emb on newp none
  set sqlprompt ''
  set trimspool on
  set long 9999999
  set longc 9999999
  set colsep ';'
  set heading on
  set recsep off
  set headsep on
  set underline off
  
  spool &&1..csv
  @&&1
  spool off
  
  undef 1
  @settings_sqlplus

Par exemple avec cette requête sql stockée dans le fichier sessions.sql :

select sid
     , serial#
     , process
     , sql_id
     , last_call_et
     , status
  from v$session ;
 

On obtient génère le fichier csv de la manière suivante:

SQL> @sessions

       SID    SERIAL# PROCESS      SQL_ID        LAST_CALL_ET STATUS
---------- ---------- ------------ ------------- ------------ --------
       146         10 4312         4gd6b1r53yt88        60116 ACTIVE
       151          2 4308                              60116 ACTIVE
       157          7 3836                              60126 ACTIVE
       159         46 6640:5200    g8730nuf9c1xf            0 ACTIVE
       160          1 3796                              60133 ACTIVE
       161          1 3792         4gd6b1r53yt88        60133 ACTIVE
       162          1 3788                              60133 ACTIVE
       163          1 3784                              60133 ACTIVE
       164          1 3780                              60133 ACTIVE
       165          1 3776                              60133 ACTIVE
       166          1 3772                              60133 ACTIVE
       
       SID    SERIAL# PROCESS      SQL_ID        LAST_CALL_ET STATUS
---------- ---------- ------------ ------------- ------------ --------
       167          1 3768                              60133 ACTIVE
       168          1 3764                              60133 ACTIVE
       169          1 3760                              60133 ACTIVE
       170          1 3756                              60133 ACTIVE
       
15 rows selected.

SQL> @sql2csv sessions
Wrote file settings_sqlplus
       SID;   SERIAL#;PROCESS     ;SQL_ID       ;LAST_CALL_ET;STATUS
       146;        10;4312        ;4gd6b1r53yt88;       60140;ACTIVE
       151;         2;4308        ;             ;       60140;ACTIVE
       157;         7;3836        ;             ;       60150;ACTIVE
       159;        46;6640:5200   ;g8730nuf9c1xf;           0;ACTIVE
       160;         1;3796        ;             ;       60157;ACTIVE
       161;         1;3792        ;4gd6b1r53yt88;       60157;ACTIVE
       162;         1;3788        ;             ;       60157;ACTIVE
       163;         1;3784        ;             ;       60157;ACTIVE
       164;         1;3780        ;             ;       60157;ACTIVE
       165;         1;3776        ;             ;       60157;ACTIVE
       166;         1;3772        ;             ;       60157;ACTIVE
       167;         1;3768        ;             ;       60157;ACTIVE
       168;         1;3764        ;             ;       60157;ACTIVE
       169;         1;3760        ;             ;       60157;ACTIVE
       170;         1;3756        ;             ;       60157;ACTIVE
       
SQL> ho type sessions.csv
       SID;   SERIAL#;PROCESS     ;SQL_ID       ;LAST_CALL_ET;STATUS
       146;        10;4312        ;4gd6b1r53yt88;       60140;ACTIVE
       151;         2;4308        ;             ;       60140;ACTIVE
       157;         7;3836        ;             ;       60150;ACTIVE
       159;        46;6640:5200   ;g8730nuf9c1xf;           0;ACTIVE
       160;         1;3796        ;             ;       60157;ACTIVE
       161;         1;3792        ;4gd6b1r53yt88;       60157;ACTIVE
       162;         1;3788        ;             ;       60157;ACTIVE
       163;         1;3784        ;             ;       60157;ACTIVE
       164;         1;3780        ;             ;       60157;ACTIVE
       165;         1;3776        ;             ;       60157;ACTIVE
       166;         1;3772        ;             ;       60157;ACTIVE
       167;         1;3768        ;             ;       60157;ACTIVE
       168;         1;3764        ;             ;       60157;ACTIVE
       169;         1;3760        ;             ;       60157;ACTIVE
       170;         1;3756        ;             ;       60157;ACTIVE

Convenons-en c’est dune laideur absolue même si dans bien des cas ça suffit.

La version 12 apporte à sqlplus l’option CSV à “SET MARKUP” qui a pour effet de créer un fichier CSV normalisé

set markup csv on delim ";"
 
select OWNER,TABLE_NAME,TABLESPACE_NAME,STATUS,LAST_ANALYZED from all_tables where rownum &lt; 11 ;
 
"OWNER";"TABLE_NAME";"TABLESPACE_NAME";"STATUS";"LAST_ANALYZED"
"SYS";"DUAL";"SYSTEM";"VALID";"24-FEB-21"
"SYS";"SYSTEM_PRIVILEGE_MAP";"SYSTEM";"VALID";"24-JAN-21"
"SYS";"TABLE_PRIVILEGE_MAP";"SYSTEM";"VALID";"24-JAN-21"
"SYS";"USER_PRIVILEGE_MAP";"SYSTEM";"VALID";"24-JAN-21"
"SYS";"STMT_AUDIT_OPTION_MAP";"SYSTEM";"VALID";"24-JAN-21"
"SYS";"AV_DUAL";"SYSTEM";"VALID";"24-JAN-21"
"SYS";"WRR$_REPLAY_CALL_FILTER";"SYSAUX";"VALID";"24-JAN-21"
"SYS";"SCHEDULER_FILEWATCHER_QT";"SYSTEM";"VALID";
"SYS";"HS_BULKLOAD_VIEW_OBJ";"SYSTEM";"VALID";"24-JAN-21"
"SYS";"HS$_PARALLEL_METADATA";"SYSTEM";"VALID";"24-JAN-21"
 
10 rows selected.

Mieux non ?

Scripter en perl sous Oracle

Pearl sous Oracle Server RDBMS

Depuis quelques temps Oracle livre avec ses clients et serveurs RDBMS sont livrés avec perl, pas dans une version récente certes mais qui permet de se connecter à la base et de travailler avec. Avec cette nouveauté, l’avantage est de pouvoir développer des scripts portables et léger pour l’administration des bases et pour un reporting minimal sans passer par de très (trop ?) lourdes et inutiles machines virtuelles (fin de troll … saurez-vous en repérer le début ?). Dans cet article, on donnera les quelques trucs minimaux pour se connecter à une base oracle et travailler avec.

Avertissement

Cet article n’a pas pour but de vous apprendre perl que vous connaissez déjà (non ?) mais bien se remémorer les quelques trucs utiles pour développer rapidement des scripts d’administration portables de windows vers unix en passant par linux et VMS !!!

Au fait, ça existe encore VMS ?

Environnement et bibliothèques perl

Perl est livré dans le répertoir perl de l’ORACLE_HOME, la localistion précise des binaires qui lui sont liés dépendent de l’OS et de la version d’Oracle RDBMS. Par exemple :

  • En version 10.2.0.3 sous windows 2008R2 64bits : %ORACLE_HOME%/perl/bin
  • En version 11.1.0.6 sous windows vista SP2 32bits : %ORACLE_HOME%/perl/5.8.3/bin/MSWin32-x86-multi-thread
  • En version 11.2.0.2 sous AIX 5.3 64bits : %ORACLE_HOME%/perl/bin

Sur les environnements de type UNIX il faut aussi positionner la variable d’environnement PERL5LIB (comme un PATH, par exemple pour AIX 64 bits et oracle 11.2.0.2 PERL5LIB=$ORACLE_HOME/perl/libsite_perl/5.10.0/aix-thread-multi-64all/:$ORACLE_HOME/perl/lib/5.10.0/ ).

Deux bibliothèques nécessaires à la connexion DBI et DBD::ORACLE. Exemples de connexions :

use DBI;

my $cnx;
my $c_usr  = "system";
my $c_pass = "amanger";

$cnx = DBI->connect( "dbi:Oracle:$ENV{ORACLE_SID}", "$c_usr", "$c_pass"
                   , { AutoCommit => 0, PrintError => 0} ) 
        or die PError ("Connexion impossiblen") ;

[TRAITEMENTS]
        
$cnx->disconnect() ;

ou pour une connexion as sysdba :

use DBI;
use DBD::Oracle qw(:ora_session_modes);

my $cnx;
my $c_usr  = "sys";
my $c_pass = "c_o_i";

$cnx = DBI->connect( "dbi:Oracle:$ENV{ORACLE_SID}", "$c_usr", "$c_pass"
                   , { AutoCommit => 0, PrintError => 0,  ora_session_mode => ORA_SYSDBA } ) 
        or die PError ("Connexion impossiblen") ;

[TRAITEMENTS]
        
$cnx->disconnect() ;

Exécuter une requête avec perl

On suppose qu’on dispose d’une connexion dans la variable $cnx.

Une ligne retournée

my $v_sql="select DBID
     , DB_UNIQUE_NAME
     , HOST_NAME
     , STATUS
     , INSTANCE_ROLE
from sys.v_$instance, sys.v_$database";

my $qry = $cnx->prepare($v_sql);
$qry->execute();
my ($dbid, $dbun, $db_hostname, $db_status, $db_role) = $qry->fetchrow_array();
$qry->finish();

Plusieur lignes retournées

my $v_sql="select * 
from sys.dba_objects";

my $qry = $cnx->prepare($v_sql);
$qry->execute();
my @t_objs = $qry->fetchrow_array();
$qry->finish();

Utilisation de bind variables

Notez l’utilisation de DBD ora_types …

use DBD::Oracle qw(:ora_types);

my $v_sql="select * 
from sys.dba_hist_snapshots where snap_id between :deb and :fin ";

my $qry = $cnx->prepare($v_sql);

$qry->bind_param( ":deb" , 1234  , { ora_type => ORA_NUMBER } )  ;
$qry->bind_param( ":fin" , 1256  , { ora_type => ORA_NUMBER } )  ;

$qry->execute();
my @t_snid = $qry->fetchrow_array();
$qry->finish();

Gérer les sorties oracle de type longs

$cnx->{LongReadLen} = 512*1024;
$cnx->{LongTruncOk} = 1;

my $v_sql="select sqlid, sql_fulltext from sys.v_$v_sql";

my $qry = $cnx->prepare($v_sql);
$qry->execute();
my @t_sqlt = $qry->fetchrow_array();
$qry->finish();

PL/SQL

Exécuter une procédure

my $v_sql="begin
 for c in (select lolo, lulu from toto)
 loop
  insert into tutu values (c.lulu, c.toto);
 end loop;
 commit;
end;";

my $qry = $cnx->prepare($v_sql);
$qry->execute();
$qry->finish();

Exécuter une procédure avec des bind variables

my $baz;
my $v_sql="begin foo.barr(:baz); end;";

my $qry = $cnx->prepare($v_sql);
$qry->bind_param_inout(":baz", $baz,400);

$qry->execute();
$qry->finish();

Récupérer la sortie de type dbms_output d’une procédure

$dbh->func( 1000000, 'dbms_output_enable' );

my $baz;
my $v_sql="begin foo.barr(); end;";

my $qry = $cnx->prepare($v_sql);
my $sortie_dbms = $cnx->func( 'dbms_output_get' );

$qry->execute();
$qry->finish();

Ce sont là les fonctionnalités perl liées à la base dont je me sers le plus. Plus d’inforamtion sur le site CPAN notamment concernant le module DBI et le module DBD::Oracle.

Mes Tricks SQL*Plus

Je suis DBA depuis poulala et je m’entête à ne pas utiliser d’interfaces graphiques coassantes ou non pour administrer mes bases de données pour les bonnes (ou mauvaises) raisons que :

  • C’est pas assez hardcore
  • Ça fait des trucs sans me prévenir
  • Faudrait que j’aprenne à m’en servir et j’ai d’autres chats à fouetter
  • J’aime pas wind….s
  • Le seul java que j’aime est de genre féminin
  • On a (presque) toujours un petit SQL*PLUS sous la main

Donc j’utilise SQL*Plus et son interface si (peu) riche. Alors pour les timides qui n’osent pas entrer dans ce formidable outil et qui un jour s’y retrouvent contraints je couche ici quelques raccourcis bien pratiques qui rendent l’outil puissant, formidable voire incontournable si on a besoin d’aller vraiment vite.

Se connecter à une base avec sqlplus

Si votre tnsnames.ora est renseigné

$ sqlplus
[...]
Entrez le nom utilisateur : <utilisateur>/<mot de passe>@<alias tns>
[...]
SQL>

Si votre tnsnames.ora n’est pas renseigné

$ sqlplus
[...]
Entrez le nom utilisateur : <utilisateur>/<mot de passe>@//<serveur>:<port>/<service>
[...]
SQL>

Voir les constantes définies

SQL> def
DEFINE _DATE = "09/10/12" (CHAR)
DEFINE _CONNECT_IDENTIFIER = "//127.0.0.1:1521/orcl" (CHAR)
DEFINE _USER = "SCOTT" (CHAR)
DEFINE _PRIVILEGE = "" (CHAR)
DEFINE _SQLPLUS_RELEASE = "1102000300" (CHAR)
DEFINE _EDITOR = "vi" (CHAR)
DEFINE _O_VERSION = "Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options" (CHAR)
DEFINE _O_RELEASE = "1102000300" (CHAR)
DEFINE _RC = "1" (CHAR)
SQL>

Utiliser un dépôt de scripts centralisé

SQL> def r=http://depot/scripts/sql
SQL> @&r/cre_super_user.sql
Utilisateur cree, compte verouille

On peut s’amuser à écrire les scripts dans un langage web comme PHP et donc protéger l’accès au scripts (plus ou moins).

Affecter et visualiser les variables de liaison (bind variables) définies dans la session

SQL> variable toto number
SQL> exec :toto:=7
SQL> variable titi number
SQL> exec :titi:=9
SQL> print

TOTO
----------
7

TITI
----------
9

Sauvegarder et restaurer les settings avant de les modifier

Sauvegarder

SQL> store set settings_sqlplus replace

Restaurer

SQL> @settings_sqlplus

Créer un ficher de sortie propre

SQL> set ver off       -- evite l'affichage des réécritures de constantes
SQL> set lin 32767 -- taille maxi d'une ligne
SQL> set trimspool on -- enlève les blancs en fin de ligne dans le fichier de sortie
SQL> set pages 50000 -- taille maxi d'une page ou set pages 0 emb on newp none L. Schneider :
-- http://laurentschneider.com/wordpress/2007/06/sqlplus-pagesize-explained.html
SQL> set termout off -- évite la sortie sur écran, seul le fichier sera renseigné
SQL> set echo off -- évite l'affichage des requêtes et donc leur écriture
SQL> set feed off -- évite les infos de fin de requêtes (n lignes ...)
SQL> set timi off -- évite le chronométrage en fin de requête
SQL> set autot off -- évite la production d'un plan en fin de requête
SQL> set long 9999999 -- permet l'affichage de longs de 9999999 octets
SQL> set longc 9999999 -- permet l'affichage de longs de 9999999 caractères*

SQL> clear computes -- supprime les agrégations automatiques de colonnes
SQL> clear columns -- supprime les formatages de colonnes
SQL> clear breaks -- supprime les sauts

SQL> TTITLE off -- supprime les titres de haut de requête (ou de pages)
SQL> BTITLE off -- supprime les titres de bas de requête
SQL> REPHEADER off -- supprime les en-tête de rapports
SQL> REPFOOTER off -- supprime les pieds de rapports

SQL> spool <fichier de sortie>
SQL> -- instructions
SQL> spool off

Concatener des constantes

SQL> def NOM_FIC=monfic
SQL> spool &&MON_FIC..txt
SQL> -- instructions
SQL> spool off

Impossible de se connecter mais analyse requise

$ sqlplus -prelim

SQL*Plus: Release 11.2.0.3.0 Production on Mer. Oct. 10 08:36:15 2012

Copyright (c) 1982, 2011, Oracle. All rights reserved.

Entrez le nom utilisateur : / as sysdba
SQL>

Cette connexion est dite préliminaire et ne permet que d’utiliser oradebug ou de faire un shutdown abort
Voilà déjà de quoi s’amuser. Avec ces quelques infos/trucs vous pouvez administrer efficacement tout un parc de bases de données sans passer par des interfaces lourdes et (bien souvent) inutiles. Reste à connaitre le SQL et le catalogue Oracle mais après tout vous êtes DBA non ?

Ajouter une instance RAC en mode silencieux avec DBCA

La commande est “ultra-simple” :

dbca -silent 
-addInstance
-gdbName $DBUN
-nodelist $NODELIST
-listeners $LISTENERS
-sysDBAUserName SYS
-sysDBAPassword $SYSPASSWD

Où DBUN est le Database Unique Name de la base de donnée, NODELIST la liste de hostnames de noeuds du RAC, LISTENERS représente la liste des listener locaux et SYSPASSWD le mot de passe de l’utilisateur SYS

Calcul des statistiques

Afficher les valeurs des paramètres utlisés par défaut par dbms_stats

col sname for a30
col SPARE4 for a50

select SNAME, spare4 from SYS.OPTSTAT_HIST_CONTROL$ ;

SNAME SPARE4
------------------------------ --------------------------------------------------
SKIP_TIME
STATS_RETENTION
TRACE 0
DEBUG 0
SYS_FLAGS 1
CASCADE DBMS_STATS.AUTO_CASCADE
ESTIMATE_PERCENT DBMS_STATS.AUTO_SAMPLE_SIZE
DEGREE NULL
METHOD_OPT FOR ALL COLUMNS SIZE AUTO
NO_INVALIDATE TRUE
GRANULARITY AUTO
AUTOSTATS_TARGET AUTO

12 rows selected.

Les valeurs ici ne sont déjà pas les valeurs utilisée par oracle par défaut, NO_INVALIDATE a été modifiée

Ecrire une procédure de calcul des statistiques

Pour un client, j’ai écrit très rapidement cette procédure de calcul de statistiques. Très (trop) imparfaite

create or replace procedure sys.calc_stats is
/*
* Procédure de calcul des statistiques ****************************
*
* Les statistiques son calculees sur les tables dont le cumul des modifications
* (insert / delete / updates) dépasse 5% du volume de la table. Elle invalide
* les plans en memoire et ignore ertains utilisateurs. Son parallelisme est de 4
* et les statistiques ne sont pas calculees sur les index de la table
*
* ******************************************************************************
* Version 1.0 pour ************ sur ORA 102040
* ******************************************************************************
*/
begin
for c in (
select tm.table_name tbn
, t.owner tbo
from ( select table_name
, table_owner
, sum(inserts) inserts
, sum(deletes) deletes
, sum(updates) updates
from dba_tab_modifications
where table_owner not in ( 'SYS', 'SYSTEM', 'SYSMAN', 'TOOLS'
, 'DBSNMP', 'ANONYMOUS', 'WMSYS', 'GOLDENGATE'
, 'XDB', 'TOAD', 'OUTLN', 'TSMSYS', 'ORDSYS')
group by table_name, table_owner ) tm
inner join dba_tables t
on ( t.owner=tm.table_owner
and t.table_name=tm.table_name )
where 1=1
and t.owner not in ( 'SYS', 'SYSTEM', 'SYSMAN', 'TOOLS'
, 'DBSNMP', 'ANONYMOUS', 'WMSYS', 'GOLDENGATE'
, 'XDB', 'TOAD', 'OUTLN', 'TSMSYS', 'ORDSYS')
and (tm.inserts+tm.updates+tm.deletes)/(nvl(t.num_rows,0)+1) > 0.05
order by nvl(t.num_rows,0) asc )
loop
dbms_stats.gather_table_stats(c.tbo, c.tbn, null, null, null, 'for all indexed columns size repeat', 4, 'ALL', FALSE, null, null, null, FALSE );
end loop;
end;
/

Manque du paramétrage et de l’automatisme

Paramétrage
  • seuil de calcul
  • no_invalidate
Automatismes
  • Echantillonnage
  • Cascade

A faire évoluer donc …