How can I improve Marklogic 7 performance on the following: /*[fn:name()="something"]

110 views Asked by At

I have a basic query:

/*[fn:name()="something"]

(1) Marklogic 7 is taking multiple seconds, is there an index that I can add to make this query faster?

(2) Which in memory limits should be increased to improve performance?

(3) Are there other ways to improve the performance with a different query but get exactly the same result?

3

There are 3 answers

2
mblakele On BEST ANSWER

Try using fn:node-name instead. I believe that's optimized. You'll need to handle namespaces properly, and that's part of why it can be optimized while fn:name can't.

 /*[fn:node-name()=fn:QName("","something")] 
3
CtheGood On

The following two xPaths should be the exact same:

/theNameOfMyElement

and

/*[fn:name()="theNameOfMyElement"]

The latter is adding an unnecessary and costly qualifier. First off, the * has to search for everything, not just elements. Several other problems exist with that approach.

If my first query is still taking a long time, use cts:search, which is much faster as it searches against indexes. The queries above can be written like this:

cts:search(/theNameOfMyElement, ())

Where the second parameter (empty sequence) can be a qualifying cts:query.

If namespaces are giving you fits, you can just do:

/*:theNameOfMyElement

/*[fn:name()="something"] seems like very bad practice to me. Use /something instead.

EDIT

After seeing that the other answer got accepted, I've been trying to think of what scenario you must be trying to solve if his solution worked and mine didn't. I'm still very certain that there is a faster way by just using xPath the way it was designed to work.

After some thought, I've decided your "real" scenario must either involve a dynamic element name or you may be trying to see if the element name matches one of a sequence of names.

I have drawn up a sample with it's output provided below, that demonstrates how you could still use both without using the qualifier based on fn:node-name

let $xml as element(sample) := <sample>
    <wrapper>
      <product>
        <entry>
          <red>$1.00</red>
          <yellow>$3.00</yellow>
          <blue>$4.50</blue>
        </entry>
      </product>
    </wrapper>
  </sample>
let $type as xs:string := "product"
return $xml/wrapper/xdmp:unpath($type)/entry/(red|yellow)

(: Returns 
  <red>$1.00</red>
  <yellow>$3.00</yellow> 
:)
0
grtjn On

In addition to the other good suggestions, consider applying pagination. MarkLogic can identify interesting content from indexes fast, but pulling up actual content from disk is relatively slow. And sending over all results at once could mean trying to hold all results (potentially billions) in memory before sending a reply over the wire. Pagination allows pulling up results in batches, which keeps memory usage low, and potentially allows parallelization as well.

HTH!