You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@jena.apache.org by Holger Knublauch <ho...@topquadrant.com> on 2021/09/07 02:44:12 UTC
Shared prefixes for all named graphs in TDB dataset (JENA-2006)
Hi Andy,
with our current migration to Jena 4.1 we noticed this change
https://issues.apache.org/jira/browse/JENA-2006
is affecting the way that we use TDB (in the "shared TDB aka XDB") mode.
Previously, all named graphs were storing their own prefixes, yet now
there seems to be only one prefix mapping for all named graphs, which
breaks the assumptions that we made on the Graph API until now.
We need to find a way to restore the old behavior. I drilled into the
code for a few hours but feel stuck due to my limited understanding of
how these pieces work together. So far I have introduced this class
below to override the createPrefixMapping method:
public class GraphXDB extends GraphTxnTDB {
public GraphXDB(DatasetGraphTransaction dataset, Node graphName) {
super(dataset, graphName);
}
@Override
protected PrefixMapping createPrefixMapping() {
DatasetPrefixesTDB pm = getDatasetGraphTDB().getStoragePrefixes();
GraphPrefixesProjection projection = new
GraphPrefixesProjection(getGraphName().toString(), pm);
return Prefixes.adapt(projection);
}
}
and this looks OK in read mode but fails on writes with errors such as:
ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] Not active: 20
ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] **** Not active: 20
ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] Not active: 20
ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] **** Not active: 20
ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] Not active: 20
ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] **** Not active: 20
Stack:
Thread [qtp975404820-101] (Suspended (breakpoint at line 304 in
BlockMgrJournal))
owns: Transaction (id=366)
BlockMgrJournal.checkActive() line: 304
BlockMgrJournal.commitPrepare(Transaction) line: 91
Transaction.lambda$prepare$0(TransactionLifecycle) line: 289
74738525.accept(Object) line: not available
ArrayList<E>.forEach(Consumer<? super E>) line: 1541
Transaction.forAllComponents(Consumer<TransactionLifecycle>) line: 283
Transaction.prepare() line: 289
Transaction.writerPrepareCommit() line: 165
Transaction.commit() line: 120
DatasetGraphTxn.commit() line: 61
DatasetGraphTransaction.commit() line: 216
DatasetGraphTxnTracking(DatasetGraphWrapper).commit() line: 276
DatasetGraphTxnTracking.commit() line: 41
TxnX.exec(T, TxnType, Runnable) line: 164
TxnX.executeWrite(T, Runnable) line: 204
PrefixMappingTxn.removeNsPrefix(String) line: 41
ModelCom.removeNsPrefix(String) line: 972
Would you have any hints on how to proceed and whether this is on the
right track? In the worst case, I guess we could switch to a completely
different storage mechanism for those per-graph prefixes and bypass TDB.
Thank you
Holger
Re: Shared prefixes for all named graphs in TDB dataset (JENA-2006)
Posted by Andy Seaborne <an...@apache.org>.
On 07/09/2021 12:33, Holger Knublauch wrote:
> Slightly related to this, I noticed that
> PrefixMappingAdapter.uriToPrefix is very inefficient, doing a reverse
> O(n) look-up.
It is not used for writing - the RIOT writers use a PrefixMap that is
tuned for writing usage patterns. Reverse multi-lookup with delete
revealing is both tricky and simply hides work elsewhere.
The adapter has a "works with anything implementation".
Andy
Re: Shared prefixes for all named graphs in TDB dataset (JENA-2006)
Posted by Andy Seaborne <an...@apache.org>.
Adding a graph is a copy, of triples and of the prefixes.
The exception is datasets-map-link
On 13/09/2021 03:47, Holger Knublauch wrote:
> To be consistent, wouldn't this mean that as soon as a Graph is added to
> a dataset, then it should adopt the dataset namespaces too? I am
> thinking about operations such as when a GraphMem is added to a
> DatasetGraph using addGraph. But this appears problematic, as Graphs
> could logically be part of multiple datasets. From the documentation it
> seems that someone could even add a TDB Graph to another Dataset. So why
> should TDB behave different from other datasets?
TDB behaves like other datasets: TDB1, TDB2, TIM (Transaction In
Memory), and the basic dataset implementation.
Adding a graph is a copy, of the triples and of the prefixes.
A dataset is isolated - if a graph is added, then there is a graph in
the dataset and later altering the source graph does not affect the
dataset contents.
This is the difference between DatasetFactory.create() and
DatasetFactory.createGeneral.
Dataset-map-link is the exception.
It does not provide the isolation contract.
Its primary usage is to give a dataset view over graphs from any
storage, or some derived graph. Jena rules being the prototypical example.
It is best used as read-only, or at least not with both graph and
dataset updates mixed together. If a graph gets created in
DatasetGraphMapLink it defaults to in-memory so can be lost which people
run into from time to time.
DatasetFactory.create() could change to be TIM. It should not make a
difference except MRSW becomes MR+SW.
Fuseki uses TIM when storing in memory. It takes an assembler to change
that.
Andy
>
> Holger
>
>
> On 2021-09-10 6:37 am, Andy Seaborne wrote:
>>
>>
>> On 07/09/2021 12:33, Holger Knublauch wrote:
>>> Having said this, I honestly don't think the limitations of one
>>> serialization should be enough to motivate such a drastic change to
>>> how prefixes are managed in TDB.
>>
>> It is not one serialization - it includes JSON-LD, where it looks like
>> new work will include packages of graphs as a dataset. It also makes
>> default union graph work properly and consistently. A dataset is a
>> logical collection of data - shared prefixes makes sense and is
>> natural for datasets read/write.
>>
>> TDB 1 and 2 are both have per-graph prefixes. Hardly drastic.
>>
>> TQ has its own proprietary graph combination and security layer which
>> is not based or related to RDF datasets and it does not use Jena data
>> access security. Using a single dataset to store many graphs of that
>> graph combination system is local to TQ.
>>
>>> For example it means that if someone changes the prefixes in one
>>> graph of the dataset, then she also changes the prefixes for all
>>> others, even for graphs that are not supposed to be writable for her.
>>> And then what would happen if two graphs are loaded and added from
>>> turtle files where each declares "ex" prefix? All this sounds very
>>> fragile and makes the use of such shared-prefixmapping datasets
>>> rather limiting - the old design was working just fine.
>>
>> The triples are kept apart. The second prefix does not change the
>> earlier data.
>>
>> Andy
Re: Shared prefixes for all named graphs in TDB dataset (JENA-2006)
Posted by Holger Knublauch <ho...@topquadrant.com>.
To be consistent, wouldn't this mean that as soon as a Graph is added to
a dataset, then it should adopt the dataset namespaces too? I am
thinking about operations such as when a GraphMem is added to a
DatasetGraph using addGraph. But this appears problematic, as Graphs
could logically be part of multiple datasets. From the documentation it
seems that someone could even add a TDB Graph to another Dataset. So why
should TDB behave different from other datasets?
Holger
On 2021-09-10 6:37 am, Andy Seaborne wrote:
>
>
> On 07/09/2021 12:33, Holger Knublauch wrote:
>> Having said this, I honestly don't think the limitations of one
>> serialization should be enough to motivate such a drastic change to
>> how prefixes are managed in TDB.
>
> It is not one serialization - it includes JSON-LD, where it looks like
> new work will include packages of graphs as a dataset. It also makes
> default union graph work properly and consistently. A dataset is a
> logical collection of data - shared prefixes makes sense and is
> natural for datasets read/write.
>
> TDB 1 and 2 are both have per-graph prefixes. Hardly drastic.
>
> TQ has its own proprietary graph combination and security layer which
> is not based or related to RDF datasets and it does not use Jena data
> access security. Using a single dataset to store many graphs of that
> graph combination system is local to TQ.
>
>> For example it means that if someone changes the prefixes in one
>> graph of the dataset, then she also changes the prefixes for all
>> others, even for graphs that are not supposed to be writable for her.
>> And then what would happen if two graphs are loaded and added from
>> turtle files where each declares "ex" prefix? All this sounds very
>> fragile and makes the use of such shared-prefixmapping datasets
>> rather limiting - the old design was working just fine.
>
> The triples are kept apart. The second prefix does not change the
> earlier data.
>
> Andy
Re: Shared prefixes for all named graphs in TDB dataset (JENA-2006)
Posted by Andy Seaborne <an...@apache.org>.
On 07/09/2021 12:33, Holger Knublauch wrote:
> Having said this, I honestly don't think the limitations of one
> serialization should be enough to motivate such a drastic change to how
> prefixes are managed in TDB.
It is not one serialization - it includes JSON-LD, where it looks like
new work will include packages of graphs as a dataset. It also makes
default union graph work properly and consistently. A dataset is a
logical collection of data - shared prefixes makes sense and is natural
for datasets read/write.
TDB 1 and 2 are both have per-graph prefixes. Hardly drastic.
TQ has its own proprietary graph combination and security layer which is
not based or related to RDF datasets and it does not use Jena data
access security. Using a single dataset to store many graphs of that
graph combination system is local to TQ.
> For example it means that if someone
> changes the prefixes in one graph of the dataset, then she also changes
> the prefixes for all others, even for graphs that are not supposed to be
> writable for her. And then what would happen if two graphs are loaded
> and added from turtle files where each declares "ex" prefix? All this
> sounds very fragile and makes the use of such shared-prefixmapping
> datasets rather limiting - the old design was working just fine.
The triples are kept apart. The second prefix does not change the
earlier data.
Andy
Re: Shared prefixes for all named graphs in TDB dataset (JENA-2006)
Posted by Holger Knublauch <ho...@topquadrant.com>.
Hi Andy,
many thanks.
On 2021-09-07 9:11 pm, Andy Seaborne wrote:
> Hi Holger,
>
> I let TQ know this was happening when the JIRA was in progress.
Quite possibly. Too many things happen in parallel, sorry if I missed
that one and didn't pay enough attention.
>
> The errors you see mean internal transaction state has passed across
> transaction boundaries. DatasetGraphTransaction is the object class
> that carries across transactions in TDB1. DatasetGraphTDB has a
> lifetime of one transaction (and it is also the storage).
>
> createPrefixMapping creates a cached prefix map but the code has
> "getDatasetGraphTDB" which is the transaction specific object.
>
> Try overriding getPrefixMapping() with that code, not
> createPrefixMapping() as a quick solution to test the rest of your
> architecture.
Yes, after a quick test, this seems to work better. I need to do more
testing tomorrow and check performance impact of creating this repeatedly.
>
> TDB1 uses PrefixMapTDB1/PrefixMapProxy to become switchable (a feature
> that is native to TDB2).
>
> Beware about TriG based backups. They didn't separate prefixes per
> graph before and still don't (with a different behaviour). There
> isn't a standard format for a setup that you describe.
Yes, we noticed the same issue. The work-around for us might be to add
the prefix declarations as (temp) triples into each graph, e.g. using
the sh:prefix vocabulary. But we are also adding alternative ways of
doing backups, esp through Git integration where people use individual
Turtle files. That's better anyway, as our Turtle writer preserves order
of triples.
Having said this, I honestly don't think the limitations of one
serialization should be enough to motivate such a drastic change to how
prefixes are managed in TDB. For example it means that if someone
changes the prefixes in one graph of the dataset, then she also changes
the prefixes for all others, even for graphs that are not supposed to be
writable for her. And then what would happen if two graphs are loaded
and added from turtle files where each declares "ex" prefix? All this
sounds very fragile and makes the use of such shared-prefixmapping
datasets rather limiting - the old design was working just fine.
Anyway, as long as we can work around this...
Slightly related to this, I noticed that
PrefixMappingAdapter.uriToPrefix is very inefficient, doing a reverse
O(n) look-up.
>
> Andy
>
> Would it be possible to have browsable stack traces next time?
> Something to drop into the Eclipse stack viewer.
Will try, yes.
Thanks again,
Holger
>
> On 07/09/2021 03:44, Holger Knublauch wrote:
>> Hi Andy,
>>
>> with our current migration to Jena 4.1 we noticed this change
>>
>> https://issues.apache.org/jira/browse/JENA-2006
>>
>> is affecting the way that we use TDB (in the "shared TDB aka XDB") mode.
>>
>> Previously, all named graphs were storing their own prefixes, yet now
>> there seems to be only one prefix mapping for all named graphs, which
>> breaks the assumptions that we made on the Graph API until now.
>>
>> We need to find a way to restore the old behavior. I drilled into the
>> code for a few hours but feel stuck due to my limited understanding
>> of how these pieces work together. So far I have introduced this
>> class below to override the createPrefixMapping method:
>>
>> public class GraphXDB extends GraphTxnTDB {
>>
>> public GraphXDB(DatasetGraphTransaction dataset, Node graphName) {
>> super(dataset, graphName);
>> }
>>
>> @Override
>> protected PrefixMapping createPrefixMapping() {
>> DatasetPrefixesTDB pm =
>> getDatasetGraphTDB().getStoragePrefixes();
>> GraphPrefixesProjection projection = new
>> GraphPrefixesProjection(getGraphName().toString(), pm);
>> return Prefixes.adapt(projection);
>> }
>> }
>>
>> and this looks OK in read mode but fails on writes with errors such as:
>>
>> ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] Not active: 20
>> ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] **** Not active: 20
>> ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] Not active: 20
>> ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] **** Not active: 20
>> ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] Not active: 20
>> ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] **** Not active: 20
>>
>> Stack:
>>
>> Thread [qtp975404820-101] (Suspended (breakpoint at line 304 in
>> BlockMgrJournal))
>> owns: Transaction (id=366)
>> BlockMgrJournal.checkActive() line: 304
>> BlockMgrJournal.commitPrepare(Transaction) line: 91
>> Transaction.lambda$prepare$0(TransactionLifecycle) line: 289
>> 74738525.accept(Object) line: not available
>> ArrayList<E>.forEach(Consumer<? super E>) line: 1541
>> Transaction.forAllComponents(Consumer<TransactionLifecycle>) line: 283
>> Transaction.prepare() line: 289
>> Transaction.writerPrepareCommit() line: 165
>> Transaction.commit() line: 120
>> DatasetGraphTxn.commit() line: 61
>> DatasetGraphTransaction.commit() line: 216
>> DatasetGraphTxnTracking(DatasetGraphWrapper).commit() line: 276
>> DatasetGraphTxnTracking.commit() line: 41
>> TxnX.exec(T, TxnType, Runnable) line: 164
>> TxnX.executeWrite(T, Runnable) line: 204
>> PrefixMappingTxn.removeNsPrefix(String) line: 41
>> ModelCom.removeNsPrefix(String) line: 972
>>
>> Would you have any hints on how to proceed and whether this is on the
>> right track? In the worst case, I guess we could switch to a
>> completely different storage mechanism for those per-graph prefixes
>> and bypass TDB.
>>
>> Thank you
>> Holger
>>
>>
Re: Shared prefixes for all named graphs in TDB dataset (JENA-2006)
Posted by Andy Seaborne <an...@apache.org>.
Hi Holger,
I let TQ know this was happening when the JIRA was in progress.
The errors you see mean internal transaction state has passed across
transaction boundaries. DatasetGraphTransaction is the object class that
carries across transactions in TDB1. DatasetGraphTDB has a lifetime of
one transaction (and it is also the storage).
createPrefixMapping creates a cached prefix map but the code has
"getDatasetGraphTDB" which is the transaction specific object.
Try overriding getPrefixMapping() with that code, not
createPrefixMapping() as a quick solution to test the rest of your
architecture.
TDB1 uses PrefixMapTDB1/PrefixMapProxy to become switchable (a feature
that is native to TDB2).
Beware about TriG based backups. They didn't separate prefixes per graph
before and still don't (with a different behaviour). There isn't a
standard format for a setup that you describe.
Andy
Would it be possible to have browsable stack traces next time? Something
to drop into the Eclipse stack viewer.
On 07/09/2021 03:44, Holger Knublauch wrote:
> Hi Andy,
>
> with our current migration to Jena 4.1 we noticed this change
>
> https://issues.apache.org/jira/browse/JENA-2006
>
> is affecting the way that we use TDB (in the "shared TDB aka XDB") mode.
>
> Previously, all named graphs were storing their own prefixes, yet now
> there seems to be only one prefix mapping for all named graphs, which
> breaks the assumptions that we made on the Graph API until now.
>
> We need to find a way to restore the old behavior. I drilled into the
> code for a few hours but feel stuck due to my limited understanding of
> how these pieces work together. So far I have introduced this class
> below to override the createPrefixMapping method:
>
> public class GraphXDB extends GraphTxnTDB {
>
> public GraphXDB(DatasetGraphTransaction dataset, Node graphName) {
> super(dataset, graphName);
> }
>
> @Override
> protected PrefixMapping createPrefixMapping() {
> DatasetPrefixesTDB pm = getDatasetGraphTDB().getStoragePrefixes();
> GraphPrefixesProjection projection = new
> GraphPrefixesProjection(getGraphName().toString(), pm);
> return Prefixes.adapt(projection);
> }
> }
>
> and this looks OK in read mode but fails on writes with errors such as:
>
> ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] Not active: 20
> ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] **** Not active: 20
> ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] Not active: 20
> ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] **** Not active: 20
> ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] Not active: 20
> ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] **** Not active: 20
>
> Stack:
>
> Thread [qtp975404820-101] (Suspended (breakpoint at line 304 in
> BlockMgrJournal))
> owns: Transaction (id=366)
> BlockMgrJournal.checkActive() line: 304
> BlockMgrJournal.commitPrepare(Transaction) line: 91
> Transaction.lambda$prepare$0(TransactionLifecycle) line: 289
> 74738525.accept(Object) line: not available
> ArrayList<E>.forEach(Consumer<? super E>) line: 1541
> Transaction.forAllComponents(Consumer<TransactionLifecycle>) line: 283
> Transaction.prepare() line: 289
> Transaction.writerPrepareCommit() line: 165
> Transaction.commit() line: 120
> DatasetGraphTxn.commit() line: 61
> DatasetGraphTransaction.commit() line: 216
> DatasetGraphTxnTracking(DatasetGraphWrapper).commit() line: 276
> DatasetGraphTxnTracking.commit() line: 41
> TxnX.exec(T, TxnType, Runnable) line: 164
> TxnX.executeWrite(T, Runnable) line: 204
> PrefixMappingTxn.removeNsPrefix(String) line: 41
> ModelCom.removeNsPrefix(String) line: 972
>
> Would you have any hints on how to proceed and whether this is on the
> right track? In the worst case, I guess we could switch to a completely
> different storage mechanism for those per-graph prefixes and bypass TDB.
>
> Thank you
> Holger
>
>
Re: Shared prefixes for all named graphs in TDB dataset (JENA-2006)
Posted by Holger Knublauch <ho...@topquadrant.com>.
Small correction to stack trace from previous email, in case that matters:
Thread [qtp975404820-93] (Suspended (breakpoint at line 305 in
BlockMgrJournal))
owns: NodeTableNative (id=586)
owns: DatasetPrefixesTDB (id=587)
BlockMgrJournal.checkActive() line: 305
BlockMgrJournal._promote(Block) line: 220
BlockMgrJournal.promote(Block) line: 215
BPTreeRecordsMgr(PageBlockMgr<T>).promote(Page) line: 109
BPTreeRecords.promote() line: 118
BPTreeRecords.internalInsert(Record) line: 129
BPTreeNode.internalInsert(Record) line: 462
BPTreeNode.insert(BPTreeNode, Record) line: 206
BPlusTree.addAndReturnOld(Record) line: 323
BPlusTree.add(Record) line: 315
NodeTableNative.accessIndex(Node, boolean) line: 154
NodeTableNative._idForNode(Node, boolean) line: 120
NodeTableNative.getAllocateNodeId(Node) line: 76
NodeTableInline(NodeTableWrapper).getAllocateNodeId(Node) line: 39
NodeTableInline.getAllocateNodeId(Node) line: 50
NodeTupleTableConcrete.addRow(Node...) line: 85
DatasetPrefixesTDB.insertPrefix(String, String, String) line: 52
GraphPrefixesProjection.add(String, String) line: 63
PrefixMappingAdapter.add(String, String) line: 50
PrefixMappingAdapter(PrefixMappingBase).setNsPrefix(String, String)
line: 124
PrefixMappingTxn.lambda$0(String, String) line: 35
2012881121.run() line: not available
TxnX.exec(T, TxnType, Runnable) line: 156
TxnX.executeWrite(T, Runnable) line: 204
PrefixMappingTxn.setNsPrefix(String, String) line: 35
ModelCom.setNsPrefix(String, String) line: 965
On 2021-09-07 12:44 pm, Holger Knublauch wrote:
> Hi Andy,
>
> with our current migration to Jena 4.1 we noticed this change
>
> https://issues.apache.org/jira/browse/JENA-2006
>
> is affecting the way that we use TDB (in the "shared TDB aka XDB") mode.
>
> Previously, all named graphs were storing their own prefixes, yet now
> there seems to be only one prefix mapping for all named graphs, which
> breaks the assumptions that we made on the Graph API until now.
>
> We need to find a way to restore the old behavior. I drilled into the
> code for a few hours but feel stuck due to my limited understanding of
> how these pieces work together. So far I have introduced this class
> below to override the createPrefixMapping method:
>
> public class GraphXDB extends GraphTxnTDB {
>
> public GraphXDB(DatasetGraphTransaction dataset, Node graphName) {
> super(dataset, graphName);
> }
>
> @Override
> protected PrefixMapping createPrefixMapping() {
> DatasetPrefixesTDB pm =
> getDatasetGraphTDB().getStoragePrefixes();
> GraphPrefixesProjection projection = new
> GraphPrefixesProjection(getGraphName().toString(), pm);
> return Prefixes.adapt(projection);
> }
> }
>
> and this looks OK in read mode but fails on writes with errors such as:
>
> ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] Not active: 20
> ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] **** Not active: 20
> ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] Not active: 20
> ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] **** Not active: 20
> ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] Not active: 20
> ERROR o.a.j.t.t.BlockMgrJournal [qtp975404820-67] **** Not active: 20
>
> Stack:
>
> Thread [qtp975404820-101] (Suspended (breakpoint at line 304 in
> BlockMgrJournal))
> owns: Transaction (id=366)
> BlockMgrJournal.checkActive() line: 304
> BlockMgrJournal.commitPrepare(Transaction) line: 91
> Transaction.lambda$prepare$0(TransactionLifecycle) line: 289
> 74738525.accept(Object) line: not available
> ArrayList<E>.forEach(Consumer<? super E>) line: 1541
> Transaction.forAllComponents(Consumer<TransactionLifecycle>) line: 283
> Transaction.prepare() line: 289
> Transaction.writerPrepareCommit() line: 165
> Transaction.commit() line: 120
> DatasetGraphTxn.commit() line: 61
> DatasetGraphTransaction.commit() line: 216
> DatasetGraphTxnTracking(DatasetGraphWrapper).commit() line: 276
> DatasetGraphTxnTracking.commit() line: 41
> TxnX.exec(T, TxnType, Runnable) line: 164
> TxnX.executeWrite(T, Runnable) line: 204
> PrefixMappingTxn.removeNsPrefix(String) line: 41
> ModelCom.removeNsPrefix(String) line: 972
>
> Would you have any hints on how to proceed and whether this is on the
> right track? In the worst case, I guess we could switch to a
> completely different storage mechanism for those per-graph prefixes
> and bypass TDB.
>
> Thank you
> Holger
>
>