Federico
Federico

Reputation: 47

Use of indexes with Existdb

Coming back with my question on indexes usage in Exist-db..... I want to optimize response times of the following query:

for $cana in doc("Events_sample.xml")//canal
for $prog in doc("Programs_sample.xml")//program [number(temporada)>1960 ][tipo_programa="Series"] [$cana//id_programa = number(@id_programa)] 
        order by $prog/titulo        
        return <tr class="modo2">
            <td>{$cana/string(@id_canal)}</td> 
            <td>{$prog/titulo}</td> 
            <td>{$prog/titulo_episodio}</td>
            <td>{$prog/generos}</td>
            <td>{$prog/id_serie}</td>
            <td>{$prog/episodio}</td>
            <td>{$prog/temporada}</td>
        </tr>

Basically I have 2 xml files, one holding information of all the programs scheduled within a number of channels (>100), with the second one including detailed info of these programs. And I want to list all the programs of type 'Series' with the season number being the year of production. And this per all channels listed in the first file.

Evaluation of this query takes more than 2 minutes in my PC. I tested different alternatives of the query with similar results, one of them is the following, which shows data in a slightly different way and with no performance improvement:

    for $prog in doc("programs_sample.xml")//program [number(temporada)>1960 ][tipo_programa="Series"]
  return
     <tr class="modo2">
                <td>{doc("Events_sample.xml")//canal[$prog/number(@id_programa)=evento/id_programa]/string(@id_canal)}</td> 
                <td>{$prog/titulo}</td> 
                <td>{$prog/titulo_episodio}</td>
                <td>{$prog/generos}</td>
                <td>{$prog/id_serie}</td>
                <td>{$prog/episodio}</td>
                <td>{$prog/temporada}</td>
            </tr>

Since I'm not an expert with xquery, maybe I'm still missing some extra optimization....

Samples of the XML files follow:

Programs.xml

    <?xml version="1.0" encoding="UTF-8"?>
<program_file fechaCreacion="20180919184224">
    <version>1.0</version>
    <programs>
        <program id_programa="1">
          <tipo_programa>Master</tipo_programa>
          <titulo >tit1</titulo>
          <año>2018</año>
        </program>
        <program id_programa="2">
          <tipo_programa>Master</tipo_programa>
          <titulo >tit1</titulo>
          <año>2018</año>
        </program>
           <program id_programa="3">
          <tipo_programa>Master</tipo_programa>
          <titulo >tit2</titulo>
          <año>2018</año>
        </program>
        <program id_programa="5">
          <id_serie>1</id_serie>
          <tipo_programa>Series</tipo_programa>
          <episodio>8</episodio>
          <titulo_episodio>Episod xx</titulo_episodio>
          <temporada>2016</temporada>
          <generos>serie comedia</generos>
          <titulo >tit1</titulo>
          <año>2018</año>
        </program>
        <program id_programa="6">
          <id_serie>2</id_serie>
          <tipo_programa>Series</tipo_programa>
          <episodio>8</episodio>
          <titulo_episodio>Episod yy</titulo_episodio>
          <temporada>2017</temporada>
          <titulo >tit1</titulo>
          <generos>serie comedia</generos>
          <año>2018</año>
        </program>
        <program id_programa="7">
          <id_serie>3</id_serie>
          <tipo_programa>Series</tipo_programa>
          <episodio>8</episodio>
          <temporada>2004</temporada>
          <titulo >tit2</titulo>
          <titulo_episodio>Episod zz</titulo_episodio>
          <generos>serie comedia</generos>
          <año>2018</año>
        </program>      
    </programs>
</program_file>

Events.xml

    <?xml version="1.0" encoding="UTF-8"?>
<schedule_file fechaCreacion="20181209202625">
  <version>1.0</version>
  <tipo_fichero>01</tipo_fichero>
  <subtipo_fichero>00</subtipo_fichero>
  <id_proveedor>001</id_proveedor>
  <nombre_proveedor>Orange</nombre_proveedor>
  <canales>
    <canal id_canal="TDPT" inicio_canal="20181207223000" fin_canal="20181224034500" duracion_canal="1401300">
      <evento>
        <id_evento>38008297</id_evento>
        <id_programa>1</id_programa>
        <fecha_inicio>20181207</fecha_inicio>
        <hora_inicio>223000</hora_inicio>
        <duracion>3600</duracion>
        <vivo>N</vivo>
        <rating>TP</rating>
        <HD>S</HD>
        <CC>N</CC>
        <nuevo>N</nuevo>
        <tipo_audio lang="SPA" audio_description="0">Stereo</tipo_audio>
        <_3D>N</_3D>
        <voVos>0</voVos>
      </evento>
      <evento>
        <id_evento>38008307</id_evento>
        <id_programa>655979</id_programa>
        <fecha_inicio>20181207</fecha_inicio>
        <hora_inicio>233000</hora_inicio>
        <duracion>5400</duracion>
        <vivo>N</vivo>
        <rating>TP</rating>
        <HD>S</HD>
        <CC>N</CC>
        <nuevo>N</nuevo>
        <tipo_audio lang="SPA" audio_description="0">Stereo</tipo_audio>
        <_3D>N</_3D>
        <voVos>0</voVos>
      </evento>
      <evento>
        <id_evento>38008308</id_evento>
        <id_programa>2</id_programa>
        <fecha_inicio>20181208</fecha_inicio>
        <hora_inicio>010000</hora_inicio>
        <duracion>5400</duracion>
        <vivo>N</vivo>
        <rating>TP</rating>
        <HD>S</HD>
        <CC>N</CC>
        <nuevo>N</nuevo>
        <tipo_audio lang="SPA" audio_description="0">Stereo</tipo_audio>
        <_3D>N</_3D>
        <voVos>0</voVos>
      </evento>
      <evento>
        <id_evento>38008309</id_evento>
        <id_programa>529846</id_programa>
        <fecha_inicio>20181208</fecha_inicio>
        <hora_inicio>023000</hora_inicio>
        <duracion>600</duracion>
        <vivo>N</vivo>
        <rating>TP</rating>
        <HD>S</HD>
        <CC>N</CC>
        <nuevo>N</nuevo>
        <tipo_audio lang="SPA" audio_description="0">Stereo</tipo_audio>
        <_3D>N</_3D>
        <voVos>0</voVos>
      </evento>
    </canal>
    <canal id_canal="MYZN" inicio_canal="20181207223000" fin_canal="20181224020000" duracion_canal="1395000">
      <evento>
        <id_evento>37864028</id_evento>
        <id_programa>3</id_programa>
        <fecha_inicio>20181207</fecha_inicio>
        <hora_inicio>223000</hora_inicio>
        <duracion>1800</duracion>
        <vivo>N</vivo>
        <rating>TP</rating>
        <HD>N</HD>
        <CC>N</CC>
        <nuevo>N</nuevo>
        <tipo_audio lang="SPA" audio_description="0">Stereo</tipo_audio>
        <_3D>N</_3D>
        <voVos>0</voVos>
      </evento>
      <evento>
        <id_evento>37864029</id_evento>
        <id_programa>5</id_programa>
        <fecha_inicio>20181207</fecha_inicio>
        <hora_inicio>230000</hora_inicio>
        <duracion>3600</duracion>
        <vivo>N</vivo>
        <rating>TP</rating>
        <HD>N</HD>
        <CC>N</CC>
        <nuevo>N</nuevo>
        <tipo_audio lang="spa" audio_description="0">Stereo</tipo_audio>
        <_3D>N</_3D>
        <voVos>0</voVos>
      </evento>
      <evento>
        <id_evento>37864607</id_evento>
        <id_programa>398729</id_programa>
        <fecha_inicio>20181208</fecha_inicio>
        <hora_inicio>000000</hora_inicio>
        <duracion>7200</duracion>
        <vivo>N</vivo>
        <rating>TP</rating>
        <HD>N</HD>
        <CC>N</CC>
        <nuevo>N</nuevo>
        <tipo_audio lang="spa" audio_description="0">Stereo</tipo_audio>
        <_3D>N</_3D>
        <voVos>0</voVos>
      </evento>
      <evento>
        <id_evento>37872206</id_evento>
        <id_programa>413706</id_programa>
        <fecha_inicio>20181223</fecha_inicio>
        <hora_inicio>214000</hora_inicio>
        <duracion>4800</duracion>
        <vivo>N</vivo>
        <rating>TP</rating>
        <HD>N</HD>
        <CC>N</CC>
        <nuevo>N</nuevo>
        <tipo_audio lang="spa" audio_description="0">Stereo</tipo_audio>
        <_3D>N</_3D>
        <voVos>0</voVos>
      </evento>
      <evento>
        <id_evento>37872207</id_evento>
        <id_programa>6</id_programa>
        <fecha_inicio>20181223</fecha_inicio>
        <hora_inicio>230000</hora_inicio>
        <duracion>3600</duracion>
        <vivo>N</vivo>
        <rating>TP</rating>
        <HD>N</HD>
        <CC>N</CC>
        <nuevo>N</nuevo>
        <tipo_audio lang="spa" audio_description="0">Stereo</tipo_audio>
        <_3D>N</_3D>
        <voVos>0</voVos>
      </evento>
      <evento>
        <id_evento>37872259</id_evento>
        <id_programa>398729</id_programa>
        <fecha_inicio>20181224</fecha_inicio>
        <hora_inicio>000000</hora_inicio>
        <duracion>7200</duracion>
        <vivo>N</vivo>
        <rating>TP</rating>
        <HD>N</HD>
        <CC>N</CC>
        <nuevo>N</nuevo>
        <tipo_audio lang="spa" audio_description="0">Stereo</tipo_audio>
        <_3D>N</_3D>
        <voVos>0</voVos>
      </evento>
    </canal>
    <canal id_canal="STCH" inicio_canal="20181207200100" fin_canal="20181224020100" duracion_canal="1404000">
      <evento>
        <id_evento>37601630</id_evento>
        <id_programa>641658</id_programa>
        <fecha_inicio>20181207</fecha_inicio>
        <hora_inicio>200100</hora_inicio>
        <duracion>10800</duracion>
        <vivo>N</vivo>
        <rating>TP</rating>
        <HD>S</HD>
        <CC>N</CC>
        <nuevo>S</nuevo>
        <tipo_audio lang="SPA" audio_description="0">Stereo</tipo_audio>
        <_3D>N</_3D>
        <voVos>0</voVos>
      </evento>
      <evento>
        <id_evento>37601631</id_evento>
        <id_programa>7</id_programa>
        <fecha_inicio>20181207</fecha_inicio>
        <hora_inicio>230100</hora_inicio>
        <duracion>9720</duracion>
        <vivo>N</vivo>
        <rating>TP</rating>
        <HD>S</HD>
        <CC>N</CC>
        <nuevo>N</nuevo>
        <tipo_audio lang="SPA" audio_description="0">Stereo</tipo_audio>
        <_3D>N</_3D>
        <voVos>0</voVos>
      </evento>
      <evento>
        <id_evento>37601632</id_evento>
        <id_programa>330720</id_programa>
        <fecha_inicio>20181208</fecha_inicio>
        <hora_inicio>014300</hora_inicio>
        <duracion>5820</duracion>
        <vivo>N</vivo>
        <rating>TP</rating>
        <HD>S</HD>
        <CC>N</CC>
        <nuevo>N</nuevo>
        <tipo_audio lang="SPA" audio_description="0">Stereo</tipo_audio>
        <_3D>N</_3D>
        <voVos>0</voVos>
      </evento>
      <evento>
        <id_evento>37601633</id_evento>
        <id_programa>3</id_programa>
        <fecha_inicio>20181208</fecha_inicio>
        <hora_inicio>032000</hora_inicio>
        <duracion>5640</duracion>
        <vivo>N</vivo>
        <rating>TP</rating>
        <HD>S</HD>
        <CC>N</CC>
        <nuevo>S</nuevo>
        <tipo_audio lang="SPA" audio_description="0">Stereo</tipo_audio>
        <_3D>N</_3D>
        <voVos>0</voVos>
      </evento>
    </canal>
  </canales>
</schedule_file>

The collection.xconf file (saved to db/system/config/db/apps/MyApp) I'm using is:

<collection xmlns="http://exist-db.org/collection-config/1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<index>
  <fulltext default="none" attributes="false"/>
    <lucene>
        <analyzer class="org.apache.lucene.analysis.standard.StandardAnalyzer">
            <param name="stopwords" type="org.apache.lucene.analysis.util.CharArraySet"/>
        </analyzer>    
        <text qname="tipo_programa"/>
        <text qname="temporada"/>
    </lucene>
    <range>

        <create qname="id_programa" type="xs:string"/>
        <create qname="temporada" type="xs:integer"/>
        <create qname="tipo_programa" type="xs:string"/>
        <create qname="program" type="xs:string"/>
    </range>
</index>

Unfortunately this is not working, the query goes as slow as before. I have also checked that indexes are created with MONEX but there is no proper use of them, just a Basic usage for the Series index (screen shots attached).

enter image description here enter image description here

I don't know what I'm doing wrong..... any hints will be welcomed.

Upvotes: 1

Views: 400

Answers (2)

duncdrum
duncdrum

Reputation: 733

Since your first query is not well formed, i can't adapt it, but I could run your second query. Without any modifications, this query runs in less then a second on the sample data. We can see that there are three calls to the range index, one successful two failing.initial run

The reason for this is twofold:

  1. Your index configuration uses the wrong types, which you convert in your query with number(). This means you first create a string index and then force a conversion which cannot use the index, instead of simply indexing the field as number in the first place and saving yourself the roundtrip.
  2. You are missing some of the attributes that you are querying inside []. To make full use of the index, all the expressions used in your query should be indexed.

Given the following conf.xml:

    <collection xmlns="http://exist-db.org/collection-config/1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <index>
      <fulltext default="none" attributes="false"/>
     <!-- Lucene was superflous for your use case    -->
        <range>
     <!--  this was missing some values used in your query  -->
            <create qname="id_programa" type="xs:integer"/>
            <create qname="temporada" type="xs:integer"/>
             <create qname="tipo_programa" type="xs:string"/>
            <create qname="program" type="xs:string"/>
            <create qname="@id_canal" type="xs:string"/>
            <create qname="@id_programa" type="xs:integer"/>
        </range>
     </index>
     </collection>

and this modified query:

xquery version "3.1";

(: Follow the standard layout of exist's expath packages :)
 import module namespace config="http://so-53557816/config" at "config.xqm";

 declare variable $events := doc($config:data-root || '/Events.xml');
 declare variable $programs := doc($config:data-root || '/Programs.xml');

(: temporada is a number no need to convert :)
(: go to al programms after 1960 that are a series :)
 for $prog in $programs//program[temporada >1960 ][tipo_programa="Series"]

(: complex xpath expressions should be evaluated once inside a let statement for greater legibiliy :)
(: look up channel id for each $prog :)
 let $cana := $events//id_programa[. = $prog/@id_programa]/../../@id_canal

  return
     <tr class="modo2">
                <td>{$cana}</td> 
                <td>{$prog/titulo}</td> 
                <td>{$prog/titulo_episodio}</td>
                <td>{$prog/generos}</td>
                <td>{$prog/id_serie}</td>
                <td>{$prog/episodio}</td>
                <td>{$prog/temporada}</td>
            </tr>

results in all three lookups to make use of the range index (no need for lucene full text indexes here)full index usage

You can download a .xar sample app of your code here, where I've also adopted a more standard application layout. With the data files inside a /data/ collections, and your query code in /modules/join.xql.

The query returns:

<tr class="modo2">
    <td id_canal="MYZN"/>
     <td>
        <titulo>tit1</titulo>
    </td>
    <td>
        <titulo_episodio>Episod xx</titulo_episodio>
    </td>
    <td>
        <generos>serie comedia</generos>
    </td>
    <td>
        <id_serie>1</id_serie>
    </td>
    <td>
        <episodio>8</episodio>
    </td>
    <td>
        <temporada>2016</temporada>
    </td>
 </tr>
 <tr class="modo2">
    <td id_canal="MYZN"/>
    <td>
        <titulo>tit1</titulo>
    </td>
    <td>
        <titulo_episodio>Episod yy</titulo_episodio>
    </td>
    <td>
        <generos>serie comedia</generos>
    </td>
    <td>
        <id_serie>2</id_serie>
    </td>
    <td>
        <episodio>8</episodio>
    </td>
    <td>
        <temporada>2017</temporada>
    </td>
 </tr>
 <tr class="modo2">
    <td id_canal="STCH"/>
    <td>
        <titulo>tit2</titulo>
    </td>
    <td>
        <titulo_episodio>Episod zz</titulo_episodio>
    </td>
    <td>
        <generos>serie comedia</generos>
    </td>
    <td>
        <id_serie>3</id_serie>
    </td>
    <td>
        <episodio>8</episodio>
    </td>
    <td>
        <temporada>2004</temporada>
    </td>
 </tr>

Upvotes: 1

duncdrum
duncdrum

Reputation: 733

Without a proper MWE I can only offer you some general observations:

Your query is maximally inefficient, there is no need for the overly complex where statement. The second for loop is equally superfluous. Getting rid of both will greatly improve performance, even without indexes.

Once you cleaned-up your query and examples, we can take another look at configuring indexes in exist-db.

you can find more information about how to write efficient queries in the documentation

Upvotes: 0

Related Questions