4 décembre 2008
4
04
/12
/décembre
/2008
20:19
Bonsoir,
Pour commencer ce mois de décembre, on va laisser un petit les nouveautés d'ORACLE 11 et revenir à notre quotidien : A savoir, les problèmes de performance.
Lorsque vous (ou un de vos clients) a des problèmes de performance une chose que beaucoup oublient de vérifier est le pourcentage de lignes chainées. Et pourtant ceci, peut avoir un impact non négligeable sur les performances.
Qu'est ce qu'une ligne chainée ?
Lors de la création d'une table, vous définissez une valeur pour le paramètre PCTFREE. La, je suis un peu optimiste. En admettant que vous ne soyez pas DBA, ou qu'Oracle n'est pas votre quotidien, vous créez une table avec 10 comme valeur pour PCTFREE. Il s'agit de la valeur par défaut. L'unité de mesure d'un tablespace étant le block, cela signifie que lorsque vous inserez des lignes dans une table, oracle gardera 10% d'espace libre par block pour les futures mises à jour (update).
Si lors d'une mise à jour, il n'y a plus d'espace dans le block contenant la ligne, Oracle mettre l'information dans un autre block qui sera chainée via le ROWID (numéro de sécu de la ligne).
Le souci, c'est que lorsque l'on va vouloir récupérer des informations de la table portant sur une ligne chainée, Oracle devra lire deux blocks au lieu d'un, et c'est la que les performances peuvent se dégrader. Car si un trop grand nombre de lignes sont chainées, on va multiplier les lectures.
Alors maintenant que l'on sait ce qu'est une ligne chainée; comment fait-on pour les identifier ?
Ce n'est pas très compliqué, il suffit d'analyzer la table voulue avec la commande suivante:
ANALYZE TABLE ma_table LIST CHAINED ROWS INTO Chained_Rows;
Et la ! forte probalité d'avoir une belle ORA-01495, table de ligne de chaine indiquée introuvable.
Comme souvent Oracle offre des outils, mais l'installation par défaut les laisse de coté.
Il faut créer la table Chaine_Rows
Pour cela vous pouvez utiliser le script utlchain.sql qui se trouve dans $ORACLE_HOME\RDBMS\admin
Il s'agit simplement d'un CREATE TABLE. Comme je suis gentil, je vous mets le script.
create table CHAINED_ROWS (
Elle s'appelle CHAINED_ROWS, rien ne vous empeche de l'appeler autrement. Disons que c'est plus sage.
Soit vous créer la table dans le schema pour lequel vous voulez analyzer des tables ou alors vous la créer sur un schema à part (voir en SYSTEM), en prenant soin de créer un synonym public.
Donc une fois la table crée, on peut relancer l'analyze.
Juste pour la forme un petit exemple tout simple.
CREATE TABLE T_2 (col1 number, col2 number);
BEGIN
FOR i IN 1..100000 LOOP
INSERT INTO T_2 VALUES (i,1);
END LOOP;
COMMIT;
END;
/
et puis un jour, le fonctionnel changeant (si si , ca arrive), on décide d'ajouter une colonne col3 de type NVARCHAR2(50)
ALTER TABLE T_2 ADD (col3 nvarchar2(50));
et comme si ca ne suffisait pas on décide de l'initialiser avec la valeur "VIDE" (j'en connais qui font ca)
UPDATE T_2 SET COL3='VIDE';
COMMIT;
Et bien de facon inconsciente, vous venez de participer à la dégradation des performances de votre base.
Démonstration:
ANALYZE TABLE T_2 LIST CHAINED ROWS INTO CHAINED_ROWS;
SELECT COUNT(*) FROM CHAINED_ROWS;
Résultat :plus de 69000 lignes chainées dans mon cas (taille de block=8K). 70% de lignes chainées alors qu'Oracle recommande d'agir à partir de 5% de lignes chainées.
Essayez de projeter cela sur un schema avec de nombreuses tables contenant de nombreuses colonnes, et vous comprendrez mieux pourquoi votre base rame !
ATTENTION : Ne pas confondre les "lignes chainées" avec la valeur le la colonne CHAIN_CNT de la table USER_TABLES.
Et après, maintenant que l'on sait ou se trouve le mal, il sera plus simple de l'éradiquer !
Allez je vous laisse réfléchir un petit peu sur le sujet, et on en reparle demain ou lundi. NE soyez pas timides, faites des propositions !!
LAO
Pour commencer ce mois de décembre, on va laisser un petit les nouveautés d'ORACLE 11 et revenir à notre quotidien : A savoir, les problèmes de performance.
Lorsque vous (ou un de vos clients) a des problèmes de performance une chose que beaucoup oublient de vérifier est le pourcentage de lignes chainées. Et pourtant ceci, peut avoir un impact non négligeable sur les performances.
Qu'est ce qu'une ligne chainée ?
Lors de la création d'une table, vous définissez une valeur pour le paramètre PCTFREE. La, je suis un peu optimiste. En admettant que vous ne soyez pas DBA, ou qu'Oracle n'est pas votre quotidien, vous créez une table avec 10 comme valeur pour PCTFREE. Il s'agit de la valeur par défaut. L'unité de mesure d'un tablespace étant le block, cela signifie que lorsque vous inserez des lignes dans une table, oracle gardera 10% d'espace libre par block pour les futures mises à jour (update).
Si lors d'une mise à jour, il n'y a plus d'espace dans le block contenant la ligne, Oracle mettre l'information dans un autre block qui sera chainée via le ROWID (numéro de sécu de la ligne).
Le souci, c'est que lorsque l'on va vouloir récupérer des informations de la table portant sur une ligne chainée, Oracle devra lire deux blocks au lieu d'un, et c'est la que les performances peuvent se dégrader. Car si un trop grand nombre de lignes sont chainées, on va multiplier les lectures.
Alors maintenant que l'on sait ce qu'est une ligne chainée; comment fait-on pour les identifier ?
Ce n'est pas très compliqué, il suffit d'analyzer la table voulue avec la commande suivante:
ANALYZE TABLE ma_table LIST CHAINED ROWS INTO Chained_Rows;
Et la ! forte probalité d'avoir une belle ORA-01495, table de ligne de chaine indiquée introuvable.
Comme souvent Oracle offre des outils, mais l'installation par défaut les laisse de coté.
Il faut créer la table Chaine_Rows
Pour cela vous pouvez utiliser le script utlchain.sql qui se trouve dans $ORACLE_HOME\RDBMS\admin
Il s'agit simplement d'un CREATE TABLE. Comme je suis gentil, je vous mets le script.
create table CHAINED_ROWS (
owner_name varchar2(30),
table_name varchar2(30),
cluster_name varchar2(30),
partition_name varchar2(30),
subpartition_name varchar2(30),
head_rowid rowid,
analyze_timestamp date
);
Elle s'appelle CHAINED_ROWS, rien ne vous empeche de l'appeler autrement. Disons que c'est plus sage.
Soit vous créer la table dans le schema pour lequel vous voulez analyzer des tables ou alors vous la créer sur un schema à part (voir en SYSTEM), en prenant soin de créer un synonym public.
Donc une fois la table crée, on peut relancer l'analyze.
Juste pour la forme un petit exemple tout simple.
CREATE TABLE T_2 (col1 number, col2 number);
BEGIN
FOR i IN 1..100000 LOOP
INSERT INTO T_2 VALUES (i,1);
END LOOP;
COMMIT;
END;
/
et puis un jour, le fonctionnel changeant (si si , ca arrive), on décide d'ajouter une colonne col3 de type NVARCHAR2(50)
ALTER TABLE T_2 ADD (col3 nvarchar2(50));
et comme si ca ne suffisait pas on décide de l'initialiser avec la valeur "VIDE" (j'en connais qui font ca)
UPDATE T_2 SET COL3='VIDE';
COMMIT;
Et bien de facon inconsciente, vous venez de participer à la dégradation des performances de votre base.
Démonstration:
ANALYZE TABLE T_2 LIST CHAINED ROWS INTO CHAINED_ROWS;
SELECT COUNT(*) FROM CHAINED_ROWS;
Résultat :plus de 69000 lignes chainées dans mon cas (taille de block=8K). 70% de lignes chainées alors qu'Oracle recommande d'agir à partir de 5% de lignes chainées.
Essayez de projeter cela sur un schema avec de nombreuses tables contenant de nombreuses colonnes, et vous comprendrez mieux pourquoi votre base rame !
ATTENTION : Ne pas confondre les "lignes chainées" avec la valeur le la colonne CHAIN_CNT de la table USER_TABLES.
Et après, maintenant que l'on sait ou se trouve le mal, il sera plus simple de l'éradiquer !
Allez je vous laisse réfléchir un petit peu sur le sujet, et on en reparle demain ou lundi. NE soyez pas timides, faites des propositions !!
LAO