Beruflich Dokumente
Kultur Dokumente
UNIVERSITE
PARIS-SUD
INFO
!!
!
M1
TER
STAGE
Remerciement!
Je tiens remercier monsieur Kim Nguyen, mon directeur de stage. Il ma accord sa
confiance ds le premier jour. Il ma encourag quand jai rencontr des problmes. Il ma
guid dans mes dmarches tout au long de mon stage. Il est lorigine de nombre dides
et de conseils, dont ce rapport est le reflet. Jai apprci de pouvoir travailler ses cts
durant ces 4 mois.
Rsum !
Le langage XPath est un langage de requte pour les documents XML. Lvaluation
efficace de requte XPath est un problme critique en base de donnes. Le but de mon
stage est limplmentation en OCaml dun algorithme efficace propos par Gotlob, Koch,
Pichler [Efficient algorithm for processing XPath queries]. Jai aussi effectu des
comparaison avec un algorithme alternatif bas sur les automates darbres dvelopp par
Kim Nguyen.!
Mots-cls: XPath; Ocaml
Sommaire!
Remerciement!................................................................................................................................2!
Rsum !..........................................................................................................................................3!
Sommaire!........................................................................................................................................4!
1 Introduction !..............................................................................................................................5!
1.1 XPath et XML!...................................................................................................................................5!
1.2 Problme de lvaluation efficace!.................................................................................................6!
1.3 Introduction du projet Tatoo!.........................................................................................................6!
1.4 Travail de TER!.................................................................................................................................6!
4 Exprience !...............................................................................................................................20!
4.1 Correction!.......................................................................................................................................20!
4.2 Lefficacit!.......................................................................................................................................21!
5 Conclusion!...............................................................................................................................24!
6 Bibliographie !...........................................................................................................................25
!
1 Introduction !
!
ALGORITHME EFFICACE POUR LE TRAITEMENT DES REQUTES XPATH!
HUIBO SHI UNIVERSIT PARIS-SUD INFORMATIQUE
Difficults: !
I. Comprhension du formalisme de larticle!
II. Larticle manque beaucoup de dtails sur la manire dimplmenter
certaines oprations!
III. Standard XML et XPath trs complexes.!
!
2 Prsentation de XPath !
pour reprsenter l'arbre. firstchild renvoie le premier fils d'un nud (s'il y a des fils,
cest--dire, si le nud n'est pas une feuille), et autrement nil. Si n1,. . . , nk sont les fils
d'un nud dans cet ordre, nextsibling (ni) = ni +1 et nextsibling(nk) = nil. Nous
dfinissons les fonctions firstchild-1 et nextsibling-1 comme les inverses des deux
premires fonctions, o nil est renvoy si aucun inverse existe pour un nud donn.!
Chaque noeud a un identifiant unique. Nous allons reprsenter le document XML de
lintroduction comme un arbre, voir ci-dessous :!
regions
1
asia
america
country
lang
11
europe
12
country
country
10
name capital
13
lang
14
15
name capital
2.2 XPath!
XPath utilise des expressions de chemin pour slectionner des ensembles de nuds
dans un document XML. Les noeuds sont choisis en valuant la requte pas pas: !
Reprenons la requte !
/descendant::country[child::capital and ancestor::asia]/child::name!
Path Expression
Description
descendant
country
[]
child
ancestor
[child::capital and Filtre le rsultat prcdant et choisit ceux qui ont un fils avec
ancestor::asia]
tiquette capital et ceux qui ont un anctre avec tiquette asia
Donc le rsultat de chaque tape est :!
/descendant::country :
! !
<name>China</name>!
! !
<capital>Beijing</capital>!
! !
</country>!
! !
<country lang="Franais">!
! !
<name>France</name>!
! !
<capital>Paris</capital>!
! !
</country>!
! !
<country lang="Anglais">!
! !
<name>United States</name>!
! !
<capital>Tokyo</capital>!
</country>!
!!
! !
<name>China</name>!
! !
<capital>Beijing</capital>!
! !
</country>!
<name>China</name>!
Naive_tree:!
type node = {
tag : QName.t;
preorder : int;
mutable kind : Tree.NodeKind.t;
mutable data : string;
mutable first_child : node;
mutable next_sibling : node;
mutable parent: node;
}
type t = {
root : node;
size : int;
by_preorder : node array;
}
Self
Child
Descendant of bool
FollowingSibling
Parent
Ancestor of bool
PrecedingSibling
Preceding
Following
descendant
T(b)
parent
child
T(a)
T(c)
Start
not
dom
ancestor
following
T(d)
e
d
10
Start : <#document><a><b><c/><d/></b><e><f/></e></a></#document>!
child(Start) : <a><b><c/><d/></b><e><f/></e></a>!
Tag(a) : <a><b><c/><d/></b><e><f/></e></a>!
Inter(child(Start), Tag(a)) : <a><b><c/><d/></b><e><f/></e></a>!
descendant(child(Start) Tag(a)) : <b><c/><d/></b>!
!
<c/>!
<d/>!
<e><f/></e>!
<f/>!
Tag(b) : <b><c/><d/></b>!
descendant(child(Start) Tag(a)) Tag(b) : <b><c/><d/></b> -!
Tag(d) : <d/>!
ancestor(Tag(d)) : <b><c/><d/></b> !
!
<a><b><c/><d/></b><e><f/></e></a>!
<#document><a><b><c/><d/></b><e><f/></e></a></#document>!
Tag(c) : <c/>!
Tag(c) ancestor(Tag(d)) : !
parent(Tag(c) ancestor(Tag(d))) : -!
Tag(*) : <a><b><c/><d/></b><e><f/></e></a>!
!
<b><c/><d/></b>!
<c/>!
<d/>!
<e><f/></e>!
<f/>!
following(Tag(*)) : <d/>!
!
<e><f/></e>!
<f/>!
Dom : <#document><a><b><c/><d/></b><e><f/></e></a></#document>!
!
<a><b><c/><d/></b><e><f/></e></a>!
<b><c/><d/></b>!
<c/>!
<d/>!
<e><f/></e>!
<f/>!
Dom - following(Tag(*)) : !
!
<c/>!
11
<b><c/><d/></b>!
<a><b><c/><d/></b><e><f/></e></a>!
<#document><a><b><c/><d/></b><e><f/></e></a></#document>-!
:!
!
<c/>!
<b><c/><d/></b>!
<a><b><c/><d/></b><e><f/></e></a>!
<#document><a><b><c/><d/></b><e><f/></e></a></#document>-!
:!
!
<b><c/><d/></b>!
Evaluer le QueryTree de taille |Q| en faisant au plus |D| oprations par noeud
du QueryTree.!
3.2 Algorithme de traduction de XPath vers QueryTree!
La traduction est donne dans larticle par un ensemble dquations rcursives:!
S ::t[e] (N0)
:=
(N0) T (t) 1e
S /::t[e] (N0)
:=
({root}) T (t) 1e
S /::t[e] (N0)
:=
(S(N0)) T (t) 1e
S ::t[e]
:=
S ::t[e]/
:=
S /
:=
dom
(S)
root
1 e1 and e2
:=
1 e1 1 e2
1 e1 or e2
:=
1 e1 1 e2
1 not(e)
:=
dom - 1
:=
!
!
12
Les champs id et hash du type queryTree sont utilis pour une optimisation que lon
prsente dans la section 3.4.1. !
tant donn une requte Q, elle peut tre rcrite en une expression algbrique E sur
les oprations , , , '-', et Tag(*) en utilisant la fonction S en temps O (|Q|).!
3.3 Evaluation du QueryTree en temps O(|D|*|Q|)!
Le code principal dvaluation du QueryTree est donn ci-dessous:!
Paramtres: larbre xml [tree], un QueryTree [qt], un noeud dpart [s]!
Retour: lensemble de noeuds correspondent au qt!
Fonction: eval_QueryTree
13
14
Larticle donne la fonction ci-dessous pour valuer les axes mis sous cette forme :!
fonction eval(R1 Rn)*(S) begin!
! S := S;!
! while (il y a un lment x dans S) do!
! !
! return S;!
! end; !
fonction eval (S) := evalE() (S).!
fonction eval self (S) := S.!
fonction eval e1.e2 (S) := eval e2 (eval e1(S))!
fonction evalR (S) := { R(x) | x S}.!
fonction eval12 (S) := eval1 (S) eval2 (S).!
o S dom est un ensemble de noeuds dun document XML, e1 et e2 sont des
expressions rgulires, R, R1, , Rn sont des relations primitives, 1 et 2 sont des axes, et
est un axe autre que self.!
Selon les rgles prcdentes, maintenant on va raliser la fonction . On dfini h
(type de Hashtbl) et q (type de Queue) pour stocker les donnes pendant le processus de
la fonction . Dans ce cas , h est quivalent de S, q permet dvaluer les Ri dans lordre
corresponds dans h. On choisi la structure de Queue car il est FIFO. A la fin, on transmet h
type de List tri afin de maintenir linterface unifie. Le code dtaill dans le tableau cidessous :!
15
16
T(a)
child
parent
parent
Start
ancestor
T(c)
ancestor
T(a)
T(b)
T(b)
En fait dans des requtes ralistes il y a souvent des portions de QueryTree qui se
rptent.!
Lide est de donner un numro chaque lment de larbre de QueryTree. Si
deux lments ont la mme signification, ils ont la mme numro. Voir la figure cidessous, cest un arbre de QueryTree avec identificateur. La deuxime apparition de T(a) a
numro 2 aussi, pareil pour T(b) ancestor. On cre donc une reprsentation de larbre
sous forme de DAG avec partage maximal.!
T(a)
child
1
12
11
parent 8
parent 10
Start
T(c)
6
ancestor
5
T(a)
ancestor
T(b)
T(b)
17
dans une table de hachage. Avant dvaluer un noeud du QueryTree, nous le cherchons
dans le table de hachage, sil existe, nous retournons directement le rsultat. Sinon nous
stockons le rsultat dans le table. Dautre part, afin dutiliser une table de hachage plus
approprie, Nous allons dfinir notre propre fonction de hachage la place de Hashtable
standard. Les codes partiels sont ci-dessous:!
let rec hash q =
if q.hash != -1 then q.hash
else match q.desc with
Dom -> 1
| Start -> 3
| Tag(s,_) -> 5 + 17*QNameSet.hash s
| Axis(a,q) -> 7 + 17 * Hashtbl.hash a + 23* hash q
| Binop(op,q1,q2) -> 11 + 17* Hashtbl.hash op + 23* hash q1 + 27*
hash q2
!
3.4.2 Utilisation des bitvectors pour enlever les tris intermdiaires!
Souvenons nous que nous avons utilis la fonction standard List.sort pour garder
les noeuds dans un ordre du document dans la fonction eval_axis, a ajoute une
complexit de O(log|D|), donc maintenant notre algorithme a la complexit O (|D|*|Q|
*log(|D|)), ce qui est mieux que lalgorithme naf mais pas optimal. Nous voulons la
complexit O (|D|*|Q|) et viter les doublons. Nous devons prserver lordre pendant
lvaluation dun axe. Pour raliser a, nous allons crire des fonctions ddies pour
chaque axe la place de la fonction gnrique eval_star et utiliser un bitvector pour
stocker les noeuds intermdiaires . Le code extrait est:
let get_descendant tree v =
let rec aux n acc =
if n == Naive_tree.nil then acc
else let n1 = Naive_tree.first_child tree n in
let j = Naive_tree.preorder tree n in
Bitvector.set acc j true;
incr node_compteur;
let acc1 = aux n1 acc in
let n2 = Naive_tree.next_sibling tree n in
aux n2 acc1
in
let v0 = Bitvector.create (Naive_tree.size tree) in
for i = 0 to (Bitvector.length v)-1 do
if Bitvector.get v i then
let n = Naive_tree.by_preorder tree i in
let n1 = Naive_tree.first_child tree n in
let _ = aux n1 v0 in ()
done;
v0
ALGORITHME EFFICACE POUR LE TRAITEMENT DES REQUTES XPATH!
HUIBO SHI UNIVERSIT PARIS-SUD INFORMATIQUE
18
Lordre de noeud dans un arbre correspond une position dans le bitvector. Nous
mettons un lment de bitvector 1 si et seulement si le noeud correspondant est dans le
rsultat valu. Grace au bitvector, les rsultats valus par laxe sont toujours ordonns,
nous avons vit de renverser chaque fois le rsultat et vit de fusionner deux listes
tries que nous avons vu dans lexemples prcdentes. De plus un bitvector une taille de
O (|D|). Nous allons comparer le rsultat defficacit en diffrents moyens dans la
prochaine section. !
19
4 Exprience !
Dans cette section, nous allons dabord tester la correction du programme. Ensuite,
nous allons valuer son efficacit. Mon programme est crit entirement en OCaml (628
lignes) et est maintenu avec le systme de version Git.!
4.1 Correction!
Nous avons test notre programme sur un jeu de test du W3C[1]. La figure cidessous est une capture dcran dexcution de mon programme. Si le rsultat est OK,
mon programme renvoie les noeuds attendus, sinon le script affiche Problem.!
Comme on le voit, tous les rsultats sont OK, cest--dire que mon programme
renvoi des rsultats corrects.
20
4.2 Lefficacit!
Dans le tableau suivant, nous allons voir les diffrences entre les rsultats de
lvaluation non optimis et de lvaluation optimise. Jai test par un fichier XML avec
1151 nombres de noeuds. Jai compar des nombres de noeuds traverses et les temps
dexcution. videmment, lvaluation non optimise prend beaucoup plus de temps que
lvaluation optimise. On remarque que les 2 optimisations (Hash consing & bitvector)
sajoutent. Comme chaque fonction List.sort ajoute une complexit de O (log (|D|)),
souvenons nous que nous avons remplac la fonction List.sort par des fonctions
ddies(voir 3.4.2). Dautre part, nous avons minimis larbre de QueryTree, et stock les
rsultats dvaluation dans notre propre table de hachage, donc quand nous rencontrons
un noeud du QueryTree valu, nous renvoyons directement le rsultat. Cest--dire si
larbre de QueryTree avait la rplication, nous valuerions moins de noeuds, sinon deux
moyens de lvaluation valuent de mme noeuds. Du coups, mon programme est
efficace.!
Query
valuation
non optimise
optimis par
hash consing
noeu
ds
temps!
(ms)
noeu
ds
temps!
(ms)
temps!
(ms)
A1 /site/closed_auctions/closed_auction/
annotation/description/text/keyword
271
16,3600
271
0,3381
4839,1 0,2282
7170,2
A2 //closed_auction//keyword
0,5250
2042,9 0,1891
5672,6
A3 /site/closed_auctions/closed_auction//
keyword
0,3080
3395,7 0,1469
7122,1
A4 /site/closed_auctions/
closed_auction[annotation/description/
text/keyword]/date
0,4649
3312,0 0,2508
6139,2
A5 /site/closed_auctions/
closed_auction[descendant::keyword]/
date
0,2539
4235,3 0,1721
6247,4
A6 /site/people/person[profile/gender and
profile/age]/name
0,3679
4735,8 0,2251
7740,8
A7 /site/people/person[phone or
homepage]/name
0,3512
4147,9 0,1950
7469,3
A8 /site/people/person[address and
(phone or homepage) and (creditcard or
profile)]/name
0,4640
4854,7 0,2680
8405,0
gain
de
temps!
(%)
optimi gain de
s par temps!
bitvect (%)
or
21
Query
valuation
non optimise
optimis par
hash consing
noeu
ds
noeu
ds
temps!
(ms)
temps!
(ms)
B1 /site/regions/*/item[parent::namerica or
parent::samerica]/name
0,3741
4370,5 0,2000
8173,2
B2 //keyword/ancestor::listitem/text/
keyword
0,4940
2838,2 0,2222
6309,9
B3 /site/open_auctions/open_auction/
bidder[following-sibling::bidder]
0,2210
4568,9 0,2060
4902,1
B4 /site/open_auctions/open_auction/
bidder[preceding-sibling::bidder]
0,2258
4939,2 0,2060
5413,6
B5 /site/regions/*/item[following::item]/
name
0,4759
3168,8 0,2851
5288,5
B6 /site/regions/*/item[preceding::item]/
name
0,4768
3396,1 0,2620
6180,3
B7 //person[profile/@income]/name
1,0698
1275,6 0,1740
7840,5
B8 /site/open_auctions/
open_auction[bidder and not(bidder/
preceding-sibling::bidder)]/interval
0,2151
8197,1 0,1860
9479,3
B9 /site/open_auctions/
open_auction[(not(bidder/
following::bidder) or not(bidder/
preceding::bidder)) or (bidder/
following::bidder and bidder/
preceding::bidder)]/interval
0,6270
B10 /site/open_auctions/
open_auction[(not(bidder/
following::bidder) or not(bidder/
preceding::bidder)) and (bidder/
following::bidder and bidder/
preceding::bidder)]/interval
0,4830
B11 //open_auction/bidder/../bidder/../
bidder/../interval
0,6151
2967,9 0,2570
7103,2
B12 //item/@id/../@id/../@id/../@id/../
name
0,5519
3989,4 0,2489
8846,2
B13 //keyword/ancestor::parlist/
descendant::keyword/ancestor::parlist/
descendant::keyword/ancestor::parlist/
descendant::keyword
0,5469
3319,6 0,2880
6304,0
temps!
(ms)
gain
de
temps!
(%)
optimi gain de
s par temps!
bitvect (%)
or
22
temps
dexcution (ms)
12,5
25
37,5
50
taille de QueryTree
!
temps dexcution (ms)
B13
67,5
45
22,5
0
12,5
25
37,5
50
taille de QueryTree
!
requete sur la taille du fichier de 2535588 noeuds
temps dexcution (ms)
6000
4500
3000
1500
0
B13
12,5
25
37,5
taille de QueryTree
50
23
5 Conclusion!
Pendant mon stage, jai tudi larticle [Efficient Algorithms for Processing XPath
Queries] [2], appris lalgorithme sur larticle et russi implmenter cet algorithme en
temps O(|D|*|Q|) en OCaml.!
Grace ce stage, jai tout dabord approfondi la connaissance de programmation
fonctionnelle, jai appris beaucoup de techniques de programmation, par exemple
lutilisation de fonction auxiliaire, la rcursion terminale, etc. Jai aussi approfondi la
connaissance sur les algorithmes que jai indiqu dans ce rapport. Pour raliser ces
algorithmes, jai lu beaucoup de fois larticle, jai fait des dessins par pas aider
comprendre. Ensuite, ce que minfluence beaucoup, cest que comment on construit un
gros projet de petit petit, surtout lanalyse structural de programme. Si lalgorithme
serait lme de programme, la structure est le squelette de programme. De plus, grce
Kim Nguyen, jai reconnait le processus doptimisation. Aprs la premire optimisation, il
me donne lautre lide doptimisation, et nous vrifions si a marche mieux ou pas, et la
suite Dans nos efforts, le programme marche plus en plus efficacement. Enfin, jai appris
lutilisation de quelques outils comme git, cela rend mon travail plus facile et efficace.!
Par la suite, je vais continuer optimiser mon programme, en particulier essayer de
diminuer la consommation en mmoire.!
!
!
24
6 Bibliographie !
[1] World Wide Web Consortium. XPath Recommendation.
http://www.w3c.org/TR/xpath/.
[2] Georg Gottlob, Christoph Koch, Reinhard Pichler.Efficient Algorithms for Processing
XPath Queries 2002
25