!
!
!
!
!
!
!
!

White paper/Intermedia (Oracle Text) (13/05/2003)

La Bibliothèque

Ceci est un projet personnel en cours !

Préambule

Depuis des années je suis mordu par l'information. Dans son sens large: la stocker, la retrouver. Ceci est dû peut être à une jeunesse passé dans un pays ou les machines à écrire étaient prohibées. Quand j'ai connu Oracle, je ne m'imaginais pas qu'un jour il va m'aider à résoudre rapidement une partie de mon problème: gérer l'information d'une manière crédible et rapide.
Intégrer l'information
L'information circule. Ma bibliothèque contient des documents qui concernent Oracle. Divers et variés (les pages WEB, les documents locaux). Les pages WEB  peuvent être à leur place (sur le WEB) ou ramenées en local. Chaque type de document est indexé avec une technique particulière Oracle présente dans le package interMedia.
Ramener l'information
Les pages proposées sont puisées du WEB avec une routine écrite en perl attachée au serveur HTTP Apache (mod_perl). La routine écrite en Perl ramène uniquement la page. Une procédure indépendante indexe les documents qui ne sont pas (encore) indexés, une autre reindexe toute la base.
Indexer l'information
Il existe dans la nature (et sur le marché) divers moteur de recherche et indexation. Celui que j'utilise, basé intégralement sur le moteur d'Oracle, indexe notamment des documents Oracle (ma bibliotheque technique). 4000 documents sont indexés en moins d'une minute (oui, une minute !), si des chargements massifs ne sont pas en cours (C'est la lenteur d'un pentium 3 à 600 Mhz qui m'a poussé à utiliser une machine bi processeur et plus de mémoire). Oracle sait reindexer uniquement les documents modifiés (action qui provoque au fur et à mesure une fragmantation importante des index).
Récupérer l'information
Aujourd'hui 13 Mai 2003, l'interface de saisie de mots de recherche n'est pas terrible (dans le fond, je suis passionné par Oracle, pas par la programmation HTML).
Quelques détails techniques 
  • Serveur PC - Pentium III bi processeur 800Mhz, 1 GigaOctet RAM, Windows 2000 server, 120 Giga Octets HD (IDE et SCSI)
  • Le serveur Web - Apache (NT)
  • Perl - ActiveState (NT)
  • Interface Perl/Apache - mod_perl
  • Oracle – 9.0.3.0 win2000
  • Insertion des documents - 5000 documents présents sur le réseau local par heure (en moyenne)
  • Indexation des documents - 4500 en deux minutes
Performances
Les mesures des performances de la bibliothèque rentrent dans le cadre des mesures dites normales sur une base Oracle. Bien que décrites dans un certain ordre, je les formaliserai au fur et à mesure, dans un ordre incertain :-)
Le score de la recherche
Le score de la recherche est calculé ... 
Les erreurs
Bien suivre la table dr$index_error, pour éviter les situations de type:
SQL> select count(*) from dr$index_error;
COUNT(*)
----------
17695973 
Cette table peut vite dégringoler, la fliquer régulièrement !
Les types de documents indexés
Aujourd'hui, j'indexe des documents dits de type texte (html, txt, xml, sql, etc) et des documents dits de type binaire (pdf, doc, xls)
Les types de stockage de documents employés
J'emploie pour les indexes diverses méthodes. Chacune nécessite un type de soin Oracle différent ;-)
  • Le stockage des documents (de type texte) dans des colonnes de type CLOB. C'est de loin l'indexation la plus rapide, mais qui nécessite une volumétrie conséquente.
  • Le stockage des documents (de type binaire) dans des colonnes de type BLOB. Pour des raisons de performances, j'ai renoncé à ce type de stockage.
  • Le stockage des documents sur Internet ;-). Ce n'est pas mon stockage ! Oracle indexe les adresses URL fournies dans une table.
  • Le stockage des documents sur le file system local. Attention, il ne s'agit pas des BFILES. Oracle indexe les documents en fonction de leur disposition 'géographique', le répertoire fourni. La table qui contient les documents à indexer s'appelle bib_datastore. L'index associé au texte indexé s'appelle datastores_text. 
Le chargement des documents texte dans la base (biblio v1)
En ce qui concerne les CLOBS qui peuplent une des tables (BIBLIOTHEQUE), ils sont alimentés par une procédure PL/SQL stockée. Elle lit le fichier en binaire et remplit la bonne colonne ! Cette table contient approximativement 300.000 documents, dans huit partitions de 1.5 GigaOctets la pièce ! Oracle indexe ces documents qui sont tous de type texte en  moins d'une heure, en parallèle ! (Quatre process).
Le chargement des documents binaires dans la base (biblio v2)
Plus tard j'ai intégré dans la base des documents de type PDF, PPT, etc. Les blobs sont moins vite analysés et indexés que les CLOBs.
Le referenncement des documents dans la base (biblio v3)
La version actuelle de la bibliothèque stocke dans la base la liste des documents à indexer. Ces documents se trouvent à l'extérieur de la base (fichiers OS). Uniquement l'index de ces documents est intégré dans la base, lors de la lecture d'un document, celui-ci est lu au niveau OS et envoyé avec Perl et Apache vers le client WEB. L'index pour les 450.000 documents de la base de connaissances TAFORA occupe six (6) GigaOctets.
Présentation de Oracle TEXT
Une des nouveautés de la 8i, que nous considérons très utile, est Intermedia Text, suite améliorée de l’Option ConText. Il s’agit d’une pléiade de procédures et de fonctions qui permettent le stockage et le traitement des documents. Nous allons présenter un projet d’indexation des documents, ORACLE fournit une centaine de filtres pour la plupart de types documents. Le projet stocke, transforme et rend un document Word en format html.
Pour que cette option puisse fonctionner correctement, une préparation de la base est nécessaire. Ce mini guide reprend les actions nécessaires. Cette option peut être complètement installée avec l’assistant de création de la base de données, mais notre installation a été manuelle.

Les paramètres de init.ora

La taille de shared_pool_size devrait être de plus de 120 Mega Octets. Nous avons pu la réduire ultérieurement.
La taille du bloc (db_block_size) devrait être égale ou supérieure à 8K.
Le paramètre compatible devrait être positionné à minimum 8.1.0.0.0: compatible = 8.1.0.0.0

L’environnement

L’utilisateur fétiche de InterMedia est CTXSYS. Dans une installation avec l’assistant, son tablespace est DRSYS.

La création

Pour débuter, choisissez la création des scripts lors de l’installation. Faire attention aux scripts drsys.sql et context.sql
Pour installer le toutim manuellement, lancer @/ctx/admin/dr0csys.sql en tant que SYS sous sqlplus. L’utilisateur CTXSYS sera créé.
Se connecter avec CTXSYS, lancer @/ctx/admin/dr0inst.sql \bin\oractxx8.dll. Le paramètre spécifié indique la source du fichier oractxx8.dll.
Vous pouvez vérifier la bonne installation des packages et surtout de la bibliothèque avec :
select library_name,file_spec,dynamic,status from user_libraries;

L’installation des langues

Vous pouvez choisir d’installer les préférences concernant la langue utilisée. Lors de l’indexation des documents, vous pourrez utiliser des paramètres de ce type. Les possibilités d’indexation, dépendantes de la langue choisie, sont :
  • Lexer définit la langue d’indexation.
  • Wordlist représente la base de requêtes floues (fuzzy).
  • Stoplist correspond à une liste de mots à ne pas indexer.
  • Datastore détermine le stockage des documents.
  • Filter précise les standards de filtrage des documents en texte.
  • Storage définit le stockage des tables d’indexation.
  • Section group caractérise des sections dans les documents.
L’installation avec l’assistant met en place les préférences US, vous pouvez installer manuellement les préférences françaises en executant
@/ctx/admin/defaults/drdeff.sql
Une cinquantaine de scripts présents dans ctx/admin/defaults permettent de choisir une langue ou une autre. Leurs noms est drdefX.sql, ou X correspond à une option d’une langue.


Configuration de NET8

Listener.ora
La configuration suivante est fonctionnelle :
LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS_LIST =
        (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
      )
      (ADDRESS_LIST =
        (ADDRESS = (PROTOCOL = TCP)(HOST = sclavos)(PORT = 1521))
      )
    )
    (DESCRIPTION =
      (PROTOCOL_STACK =
        (PRESENTATION = GIOP)
        (SESSION = RAW)
      )
      (ADDRESS = (PROTOCOL = TCP)(HOST = sclavos)(PORT = 2481))
    )
  )
SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = PLSExtProc)
      (ORACLE_HOME = L:\ORACLE\Ora81)
      (PROGRAM = extproc)
    )
    (SID_DESC =
      (SID_NAME = IDBA)
      (ORACLE_HOME = L:\ORACLE\Ora81)
      (GLOBAL_DBNAME = IDBA)
    )
    (SID_DESC =
      (GLOBAL_DBNAME = IMED)
      (ORACLE_HOME = L:\ORACLE\Ora81)
      (SID_NAME = IMED)
    )
  )
L’appel aux DLLs se fera via une connexion IPC. Un nouvel SID (PLSExtProc) est accompagné d’un programme externe (EXTPROC).
PLSExtProc correspondra au SID dans CONNECT_DATA de extproc_connection_data dans TNSNAMES.ORA du serveur.
Tnsnames.ora
Sur le serveur
  1. Ajouter une entrée pour EXTPROC0 dans TNSNAMES.ORA du serveur. Utilisez la connexion à l’ancienne base avec SID au lieu de SERVICE_NAME.
EXTPROC_CONNECTION_DATA =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
    )
    (CONNECT_DATA =
      (SID = PLSExtProc)
    )
  )
Le nom de PLSExtProc peut contenir n'importe quelle valeur. En revanche, extproc_connection_data doit rester ainsi.

Sur les clients
Il n’y a pas de configuration spéciale pour les clients. Les requêtes passeront via la connexion normale sur le serveur.
Sqlnet.ora.
Vérifiez le domaine, par défaut, dans sqlnet.ora sur le serveur. Dans notre cas, il a la forme suivante :
NAMES.DEFAULT_DOMAIN = WORKGROUP
SQLNET.AUTHENTICATION_SERVICES= (NTS)
NAMES.DIRECTORY_PATH= (TNSNAMES, ONAMES, HOSTNAME)
extproc.connection_data.workgroup

Tester le reseau

Vérification du listener :
lsnrctl status
Vous devriez avoir un service PLSExtProc.
Tester le listener avec tnsping (sur le serveur) :
tnsping extproc_connection_data
Tester la connexion cliente :
Un test simple pour vérifier la connexion de n’importe quel client est d’indexer un texte ou tout simplement de démarrer la trace de l’index :
exec ctx_output.start_log('test_index.log')
Cette commande est censée produire un fichier log dans ORACLE_HOME/ctx/log. Tout autre message d’erreur signifie une installation incomplète.

Tester l’installation

Création d’une table:
connect ctxsys/ctxsys@idba
create table t1(c1 number primary key, text_c2 varchar2(200));
insert into t1 values (1,'Test Intermedia');
Insert into t1 values (2,'aboutit');
Commit;
Création d’un index :
create index idx on t1(test_text) indextype is ctxsys.context;
SQL> create index idx on t1(text_c2) indextype is ctxsys.context;
create index idx on t1(text_c2) indextype is ctxsys.context
*
ERROR at line 1:
ORA-29855: error occurred in the execution of ODCIINDEXCREATE routine
ORA-20000: interMedia Text error:
ORA-01658: unable to create INITIAL extent for segment in tablespace USER1
ORA-06512: at "CTXSYS.DRUE", line 126
ORA-06512: at "CTXSYS.TEXTINDEXMETHODS", line 54
ORA-06512: at line 1
Veillons aux volumes ! Après l’agrandissement du fichier, et la recréation de l’index, cherchons le texte :
Select c1, text_c2 from t1
where contains (test_text,'aboutit') > 0;
Vous devriez obtenir la deuxième ligne.
SQL> Select c1, text_c2 from t1
  2  where contains (text_c2,'aboutit') > 0;
        C1 TEXT_C2
---------- ----------------------------------------------------------------------
         2 aboutit

Insertion et indexation de plusieurs documents en format WORD

Les étapes présentées dans les paragraphes suivants ont comme but la restitution d’un document en format HTML à partir d'un format WORD. ORACLE nous fournit des filtres capables de cette prouesse !
Création d’un tablespace récepteur de notre bibliothèque. Le tablespace devrait être assez volumineux pour contenir nos documents (mais il est ridiculement petit dans notre exemple).
drop tablespace ctxsys.biblio_lobs including contents;
create tablespace biblio_lobs 
    datafile 'L:\DB\IDBA\DATA\P3\fbiblio_lobs.DAT' size 400M reuse;
Création de la table qui contiendra nos documents. Remarquons l’existence des champs lob. Idéalement, vu la volumétrie des objets, les segments de lob devraient être stockés ailleurs, dans un autre tablespace.
drop table ctxsys.bibliotheque;
connect ctxsys/poloff@idba
create table bibliotheque (
   document_id number not null, 
   document_machine  varchar2(25) not null,
   document_orig_dir varchar2(200),
   document_comment  varchar2(200),
   document_origin   varchar2(200),
   document_name     varchar2(80) not null
   ) tablespace biblio_lobs;
Création d’une clé primaire, sans laquelle l’indexation est impossible :
alter table bibliotheque add (constraint pk_bib primary key (document_id));
Ajout des lobs dans la table, un blob pour les documents binaires, un clob pour les html.
alter table bibliotheque add (
  document   blob default empty_blob(),
  document_html  clob default empty_clob()
  )
  lob (document) store as document_seg
    (tablespace biblio_lobs 
     storage (initial 4k next 4k pctincrease 0)
     chunk 4k nocache logging enable storage in row)
  lob (document_html) store as document_html_seg
    (tablespace biblio_lobs 
     storage (initial 2k next 2k pctincrease 0)
     chunk 2k nocache nologging enable storage in row)
  ;
Remplissons la table avec quelques documents répertoriés dans le fichier de contrôle de sql*loader.
host sqlldr userid = ctxsys/poloff@idba control=wordload.ctl log = wordload.log
Le fichier de contrôle (wordload.ctl) est de la forme suivante :
load into table bibliotheque
fields terminated by ',' 
( document_id, document_machine, document_orig_dir, document_comment, 
  document_origin, document_name, external_filename filler, 
  document lobfile(external_filename)
terminated by eof
)
Le fichier de données, est de cette forme :
01,'MASTER',P:\fiches,'','',orga_admin.doc,P:\fiches\orga_admin.doc
02,'MASTER',P:\fiches,'','',fichetechadmin.doc,P:\fiches\fichetechadmin.doc
03,'MASTER',P:\fiches,'','',admin_lob.doc,P:\fiches\admin_lob.doc
04,'MASTER',P:\fiches,'','',repart_traitements.doc,P:\fiches\repart_traitements.doc
05,'MASTER',P:\fiches,'','',concep_si.doc,P:\fiches\concep_si.doc
06,'MASTER',P:\fiches,'','',repart_donnees.doc,P:\fiches\repart_donnees.doc
07,'MASTER',P:\fiches,'','',prmigration_1.doc,P:\fiches\prmigration_1.doc
08,'MASTER',P:\fiches,'','',infocentre.doc,P:\fiches\infocentre.doc
Vérifiions le bon déroulement de l’opération :
select segment_name, partition_name, tablespace_name from dba_segments 
   where segment_name like '%DOCUMENT%';
select count(*) from bibliotheque;
Indexons nos documents. Remarquez l’existence d’un index sur les noms des documents, mis en majuscules, qui nous permettra de vérifier les doublons par nom.
create index document_name_index on bibliotheque(upper(document_name));
create index biblio_index on bibliotheque(document) indextype is CTXSYS.CONTEXT;
Select document_id, document_orig_dir from bibliotheque
  where contains (document,'ORACLE') > 0;
SQL> Select document_id, document_name, document_orig_dir from bibliotheque
  2  where contains (document,'ORACLE') > 0;
DOCUMENT_ID DOCUMENT_NAME                  DOCUMENT_ORIG_DIR
----------- ------------------------------ ------------------------------
          2 fichetechadmin.doc             P:\_web\9904\od\doc\fiches
          3 admin_lob.doc                  P:\_web\9904\od\doc\fiches
          7 prmigration_1.doc              P:\_web\9904\od\doc\fiches
         12 praudit_ORACLE_applicatif.doc  P:\_web\9904\od\doc\fiches
         16 fiche ows.doc                  P:\_web\9904\od\doc\fiches
         33 conversion_f3_f45_f5.doc       P:\_web\9904\od\doc\fiches
         35 fichetechtuning.doc            P:\_web\9904\od\doc\fiches
         38 praudit_ORACLE_noyau.doc       P:\_web\9904\od\doc\fiches
         48 mso140.doc                     f:\utils
9 rows selected.
Stats
Compteur

Copyright © 1998-2002 Radu Caulea, TAFORA MAJ 06/11/2006 !
Commentaires et suggestions radu[CHEZ]tafora.fr