<?xml version="1.0" encoding="UTF-8" ?>
<!--RDF based XML document generated By OpenLink Virtuoso-->
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
 <rss:channel xmlns:rss="http://purl.org/rss/1.0/" rdf:about="http://www.openlinksw.com:443/weblog/oerling/">
  <rss:title>Orri Erling&#39;s Weblog</rss:title>
  <rss:link>http://www.openlinksw.com:443/weblog/oerling/</rss:link>
  <rss:description />
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">oerling@openlinksw.com</dc:creator>
  <dc:date xmlns:dc="http://purl.org/dc/elements/1.1/">2026-10-05T23:54:26Z</dc:date>
  <rss:items>
   <rdf:Seq>
      <rdf:li rdf:resource="http://www.openlinksw.com:443/weblog/oerling/?date=2016-01-11#1866" />
   </rdf:Seq>
  </rss:items>
 </rss:channel>
 <rss:item xmlns:rss="http://purl.org/rss/1.0/" rdf:about="http://www.openlinksw.com:443/weblog/oerling/?date=2016-01-11#1866">
  <rss:title>New Semantic Publishing Benchmark Record</rss:title>
  <dc:date xmlns:dc="http://purl.org/dc/elements/1.1/">2016-01-11T15:22:09Z</dc:date>
  <dc:description xmlns:dc="http://purl.org/dc/elements/1.1/">There is a new SPB (Semantic Publishing Benchmark) 256 Mtriple record with Virtuoso. As before, the result has been measured with the feature/analytics branch of the v7fasttrack open source distribution, and it will soon be available as a preconfigured Amazon EC2 image. The updated benchmarks AMI with this version of the software will be out there within the next week, to be announced on this blog. On the Cost of RDF Query Optimization RDF query optimization is harder than the relational equivalent; first, because there are more joins, hence an NP complete explosion of plan search space, and second, because cardinality estimation is harder and usually less reliable. The work on characteristic sets, pioneered by Thomas Neumann in RDF3X, uses regularities in structure for treating properties usually occurring in the same subject as columns of a table. The same idea is applied for tuning physical representation in the joint Virtuoso / MonetDB work published at WWW 2015. The Virtuoso results discussed here, however, are all based on a single RDF quad table with Virtuoso&#39;s default index configuration. Introducing query plan caching raises the Virtuoso score from 80 qps to 144 qps at the 256 Mtriple scale. The SPB queries are not extremely complex; lookups with many more triple patterns exist in actual workloads, e.g., Open PHACTS. In such applications, query optimization indeed dominates execution times. In SPB, data volumes touched by queries grow near linearly with data scale. At the 256 Mtriple scale, nearly half of CPU cycles are spent deciding a query plan. Below are the CPU cycles for execution and compilation per query type, sorted by descending sum of the times, scaled to milliseconds per execution. These are taken from a one minute sample of running at full throughput. Test system is the same used before in the TPC-H series: dual Xeon E5-2630 Sandy Bridge, 2 x 6 cores x 2 threads, 2.3GHz, 192 GB RAM. We measure the compile and execute times, with and without using hash join. When considering hash join, the throughput is 80 qps. When not considering hash join, the throughput is 110 qps. With query plan caching, the throughput is 145 qps whether or not hash join is considered. Using hash join is not significant for the workload but considering its use in query optimization leads to significant extra work. With hash join Compile Execute Total Query 3156Â ms 1181Â ms 4337Â ms Total 1327Â ms 28Â ms 1355Â ms query 01 444Â ms 460Â ms 904Â ms query 08 466Â ms 54Â ms 520Â ms query 06 123Â ms 268Â ms 391Â ms query 05 257Â ms 5Â ms 262Â ms query 11 191Â ms 59Â ms 250Â ms query 10 9Â ms 179Â ms 188Â ms query 04 114Â ms 26Â ms 140Â ms query 07 46Â ms 62Â ms 108Â ms query 09 71Â ms 25Â ms 96Â ms query 12 61Â ms 13Â ms 74Â ms query 03 47Â ms 2Â ms 49Â ms query 02 Â  Â  Â  Â  Without hash join Compile Execute Total Query 1816Â ms 1019Â ms 2835Â ms Total 197Â ms 466Â ms 663Â ms query 08 609Â ms 32Â ms 641Â ms query 01 188Â ms 293Â ms 481Â ms query 05 275Â ms 61Â ms 336Â ms query 09 163Â ms 10Â ms 173Â ms query 03 128Â ms 38Â ms 166Â ms query 10 102Â ms 5Â ms 107Â ms query 11 63Â ms 27Â ms 90Â ms query 12 24Â ms 57Â ms 81Â ms query 06 47Â ms 1Â ms 48Â ms query 02 15Â ms 24Â ms 39Â ms query 07 5Â ms 5Â ms 10Â ms query 04 Considering hash join always slows down compilation, and sometimes improves and sometimes worsens execution. Some improvement in cost-model and plan-space traversal-order is possible, but altogether removing compilation via caching is better still. The results are as expected, since a lookup workload such as SPB has little use for hash join by nature. The rationale for considering hash join in the first place is that analytical workloads rely heavily on this. A good TPC-H score is simply unfeasible without this as previously discussed on this blog. If RDF is to be a serious contender beyond serving lookups, then hash join is indispensable. The decision for using this however depends on accurate cardinality estimates on either side of the join. Previous work (e.g., papers from FORTH around MonetDB) advocates doing away with a cost model altogether, since one is hard and unreliable with RDF anyway. The idea is not without its attraction but will lead to missing out of analytics or to relying on query hints for hash join. The present Virtuoso thinking is that going to rule based optimization is not the preferred solution, but rather using characteristic sets for reducing triples into wider tables, which also cuts down on plan search space and increases reliability of cost estimation. When looking at execution alone, we see that actual database operations are low in the profile, with memory management taking the top 19%. This is due to CONSTRUCT queries allocating small blocks for returning graphs, which is entirely avoidable.</dc:description>
  <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>There is a new <a href="http://ldbcouncil.org/developer/spb" id="link-id0x7fd87214c348">SPB (Semantic Publishing Benchmark)</a> 256 Mtriple record with <a href="http://dbpedia.org/resource/Virtuoso_Universal_Server" id="link-id0x7fd870d26a48">Virtuoso</a>.</p>

<p>As before, the result has been measured with the <a href="https://github.com/v7fasttrack/virtuoso-opensource/tree/feature/analytics" id="link-id0x7fd870d26be8">feature/analytics</a> branch of the <a href="https://github.com/v7fasttrack/virtuoso-opensource/" id="link-id0x7fd870d26d58">v7fasttrack</a> open source distribution, and it will soon be available as a preconfigured Amazon EC2 image.  The updated <a href="http://www.openlinksw.com/weblogs/oerling/?id=1849" id="link-id0x7fd87217aec8">benchmarks AMI</a> with this version of the software will be out there within the next week, to be announced on this blog.</p>

<h2>On the Cost of RDF Query Optimization</h2>

<p>RDF query optimization is harder than the relational equivalent; first, because there are more joins, hence an NP complete explosion of plan search space, and second, because cardinality estimation is harder and usually less reliable.  The work on characteristic sets, pioneered by <a href="https://www.linkedin.com/pub/thomas-neumann/2/35/189" id="link-id0x7fd870c3e918">Thomas Neumann</a> in <a href="https://domino.mpi-inf.mpg.de/intranet/ag5/ag5publ.nsf/0/AD3DBAFA6FB90DD2C1257593002FF3DF/$file/rdf3x.pdf" id="link-id0x7fd870c3eae8">RDF3X</a>, uses regularities in structure for treating properties usually occurring in the same subject as columns of a table.  The same idea is applied for tuning physical representation in <a href="http://homepages.cwi.nl/~duc/papers/emergentschema_www15.pdf" id="link-id0x7fd8721c1ea8">the joint Virtuoso / MonetDB work published at WWW 2015</a>.</p>

<p>The Virtuoso results discussed here, however, are all based on a single RDF quad table with Virtuoso&#39;s default index configuration.</p>

<p>Introducing query plan caching raises the Virtuoso score from 80 qps to 144 qps at the 256 Mtriple scale.  The SPB queries are not extremely complex; lookups with many more triple patterns exist in actual workloads, e.g., <a href="http://dbpedia.org/resource/OpenPHACTS" id="link-id0x7fd8721313e8">Open PHACTS</a>.  In such applications, query optimization indeed dominates execution times.  In SPB, data volumes touched by queries grow near linearly with data scale.  At the 256 Mtriple scale, nearly half of CPU cycles are spent deciding a query plan.  Below are the CPU cycles for execution and compilation per query type, sorted by descending sum of the times, scaled to milliseconds per execution. These are taken from a one minute sample of running at full throughput.</p>

<p>Test system is the same used before in the <a href="http://www.openlinksw.com/weblog/oerling/?id=1739" id="link-id0x7fd872131738">TPC-H series</a>: dual Xeon E5-2630 Sandy Bridge, 2 x 6 cores x 2 threads, 2.3GHz, 192 GB RAM.</p>

<p>We measure the compile and execute times, with and without using hash join.  When considering hash join, the throughput is 80 qps.  When not considering hash join, the throughput is 110 qps.  With query plan caching, the throughput is 145 qps whether or not hash join is considered.  Using hash join is not significant for the workload but considering its use in query optimization leads to significant extra work.</p>

<table style="padding:10px;border-spacing:10px;margin-left:auto;margin-right:auto;">
<tr style="text-align:center;">
<td>

<h3>With hash join</h3>

<table style="padding:10px;border-spacing:10px;margin-left:auto;margin-right:auto;">
<tr style="text-align:center;">
    <th>Compile</th>
    <th>Execute</th>
    <th>Total</th>
    <th>Query</th>
  </tr>
  <tr>
    <td style="text-align:right;"> <code><i> 3156Â ms </i></code> </td>
    <td style="text-align:right;"> <code><i> 1181Â ms </i></code> </td>
    <td style="text-align:right;"> <code><i> 4337Â ms </i></code> </td>
    <td style="text-align:right;"> <code><i> Total </i></code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 1327Â ms </code> </td>
    <td style="text-align:right;"> <code> 28Â ms </code> </td>
    <td style="text-align:right;"> <code> 1355Â ms </code> </td>
    <td style="text-align:right;"> <code> query 01 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 444Â ms </code> </td>
    <td style="text-align:right;"> <code>  460Â ms </code> </td>
    <td style="text-align:right;"> <code> 904Â ms </code> </td>
    <td style="text-align:right;"> <code> query 08 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 466Â ms </code> </td>
    <td style="text-align:right;"> <code>  54Â ms </code> </td>
    <td style="text-align:right;"> <code> 520Â ms </code> </td>
    <td style="text-align:right;"> <code> query 06 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 123Â ms </code> </td>
    <td style="text-align:right;"> <code>  268Â ms </code> </td>
    <td style="text-align:right;"> <code> 391Â ms </code> </td>
    <td style="text-align:right;"> <code> query 05 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 257Â ms </code> </td>
    <td style="text-align:right;"> <code>  5Â ms </code> </td>
    <td style="text-align:right;"> <code> 262Â ms </code> </td>
    <td style="text-align:right;"> <code> query 11 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 191Â ms </code> </td>
    <td style="text-align:right;"> <code>  59Â ms </code> </td>
    <td style="text-align:right;"> <code> 250Â ms </code> </td>
    <td style="text-align:right;"> <code> query 10 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 9Â ms </code> </td>
    <td style="text-align:right;"> <code>    179Â ms </code> </td>
    <td style="text-align:right;"> <code> 188Â ms </code> </td>
    <td style="text-align:right;"> <code> query 04 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 114Â ms </code> </td>
    <td style="text-align:right;"> <code>  26Â ms </code> </td>
    <td style="text-align:right;"> <code> 140Â ms </code> </td>
    <td style="text-align:right;"> <code> query 07 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 46Â ms </code> </td>
    <td style="text-align:right;"> <code>   62Â ms </code> </td>
    <td style="text-align:right;"> <code> 108Â ms </code> </td>
    <td style="text-align:right;"> <code> query 09 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 71Â ms </code> </td>
    <td style="text-align:right;"> <code>   25Â ms </code> </td>
    <td style="text-align:right;"> <code> 96Â ms </code> </td>
    <td style="text-align:right;"> <code> query 12 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 61Â ms </code> </td>
    <td style="text-align:right;"> <code>   13Â ms </code> </td>
    <td style="text-align:right;"> <code> 74Â ms </code> </td>
    <td style="text-align:right;"> <code> query 03 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 47Â ms </code> </td>
    <td style="text-align:right;"> <code>   2Â ms </code> </td>
    <td style="text-align:right;"> <code> 49Â ms </code> </td>
    <td style="text-align:right;"> <code> query 02 </code></td>
  </tr>
</table>

</td>
<td style="text-align:center;">
Â  Â  Â  Â  
</td>
<td style="text-align:center;">

<h3>Without hash join</h3>

<table style="padding:10px;border-spacing:10px;margin-left:auto;margin-right:auto;">
<tr style="text-align:center;">
    <th>Compile</th>
    <th>Execute</th>
    <th>Total</th>
    <th>Query</th>
  </tr>
  <tr>
    <td style="text-align:right;"> <code><i> 1816Â ms </i></code> </td>
    <td style="text-align:right;"> <code><i> 1019Â ms </i></code> </td>
    <td style="text-align:right;"> <code><i> 2835Â ms </i></code> </td>
    <td style="text-align:right;"> <code><i> Total </i></code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 197Â ms </code> </td>
    <td style="text-align:right;"> <code>  466Â ms </code> </td>
    <td style="text-align:right;"> <code> 663Â ms </code> </td>
    <td style="text-align:right;"> <code> query 08 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 609Â ms </code> </td>
    <td style="text-align:right;"> <code>  32Â ms </code> </td>
    <td style="text-align:right;"> <code> 641Â ms </code> </td>
    <td style="text-align:right;"> <code> query 01 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 188Â ms </code> </td>
    <td style="text-align:right;"> <code>  293Â ms </code> </td>
    <td style="text-align:right;"> <code> 481Â ms </code> </td>
    <td style="text-align:right;"> <code> query 05 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 275Â ms </code> </td>
    <td style="text-align:right;"> <code>  61Â ms </code> </td>
    <td style="text-align:right;"> <code> 336Â ms </code> </td>
    <td style="text-align:right;"> <code> query 09 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 163Â ms </code> </td>
    <td style="text-align:right;"> <code>  10Â ms </code> </td>
    <td style="text-align:right;"> <code> 173Â ms </code> </td>
    <td style="text-align:right;"> <code> query 03 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 128Â ms </code> </td>
    <td style="text-align:right;"> <code>  38Â ms </code> </td>
    <td style="text-align:right;"> <code> 166Â ms </code> </td>
    <td style="text-align:right;"> <code> query 10 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 102Â ms </code> </td>
    <td style="text-align:right;"> <code>  5Â ms </code> </td>
    <td style="text-align:right;"> <code> 107Â ms </code> </td>
    <td style="text-align:right;"> <code> query 11 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 63Â ms </code> </td>
    <td style="text-align:right;"> <code>   27Â ms </code> </td>
    <td style="text-align:right;"> <code> 90Â ms </code> </td>
    <td style="text-align:right;"> <code> query 12 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 24Â ms </code> </td>
    <td style="text-align:right;"> <code>   57Â ms </code> </td>
    <td style="text-align:right;"> <code> 81Â ms </code> </td>
    <td style="text-align:right;"> <code> query 06 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 47Â ms </code> </td>
    <td style="text-align:right;"> <code>   1Â ms </code> </td>
    <td style="text-align:right;"> <code> 48Â ms </code> </td>
    <td style="text-align:right;"> <code> query 02 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 15Â ms </code> </td>
    <td style="text-align:right;"> <code>   24Â ms </code> </td>
    <td style="text-align:right;"> <code> 39Â ms </code> </td>
    <td style="text-align:right;"> <code> query 07 </code></td>
  </tr>
  <tr>
    <td style="text-align:right;"> <code> 5Â ms </code> </td>
    <td style="text-align:right;"> <code>    5Â ms </code> </td>
    <td style="text-align:right;"> <code> 10Â ms </code> </td>
    <td style="text-align:right;"> <code> query 04 </code></td>
  </tr>
</table>
</td>
</tr>
</table>

<p>Considering hash join always slows down compilation, and sometimes improves and sometimes worsens execution. Some improvement in cost-model and plan-space traversal-order is possible, but altogether removing compilation via caching is better still.  The results are as expected, since a lookup workload such as SPB has little use for hash join by nature.</p>

<p>The rationale for considering hash join in the first place is that analytical workloads rely heavily on this.  A good <a href="http://www.tpc.org/tpch/" id="link-id0x7fd8721ce268">TPC-H</a> score is simply unfeasible without this as <a href="http://www.openlinksw.com/weblog/oerling/?id=1739" id="link-id0x7fd8720f3f48">previously discussed on this blog</a>.  If RDF is to be a serious contender beyond serving lookups, then hash join is indispensable.  The decision for using this however depends on accurate cardinality estimates on either side of the join.</p>

<p>Previous work (e.g., papers from <a href="http://www.forth.gr/" id="link-id0x7fd8720f8548">FORTH</a> around <a href="http://dbpedia.org/resource/MonetDB" id="link-id0x7fd8721bfe38">MonetDB</a>) advocates doing away with a cost model altogether, since one is hard and unreliable with RDF anyway.  The idea is not without its attraction but will lead to missing out of analytics or to relying on query hints for hash join.</p>

<p>The present Virtuoso thinking is that going to rule based optimization is not the preferred solution, but rather using characteristic sets for reducing triples into wider tables, which also cuts down on plan search space and increases reliability of cost estimation.</p>

<p>When looking at execution alone, we see that actual database operations are low in the profile, with memory management taking the top 19%. This is due to <code>CONSTRUCT</code> queries allocating small blocks for returning graphs, which is entirely avoidable.</p>
]]></content:encoded>
 </rss:item>
</rdf:RDF>