![]() |
|||||||||||||||||||||||||||||||||||||||||||||||
|
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
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 ;-)
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 TEXTUne 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 :
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.sqlUne 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
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
|
||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||