Как я могу оптимизировать запрос SPARQL, который возвращает необязательные свойства?
Как я могу оптимизировать запрос SPARQL, как показано ниже?
Цель этого запроса:
- Укажите ресурс (страна ресурса, где
countryCode = "US"
) - Вернуть необязательные свойства, определенные на ресурсе.
К сожалению, OPTIONAL
блоки оцениваются перед родительским блоком, что заставляет механизм запросов загружать все данные для всех стран.
То, что я хочу, это что-то вроде LEFT OUTER JOIN
поведение, но механизм запросов не обрабатывает это таким образом.
Что я могу сделать, чтобы улучшить производительность запросов?
SELECT *
WHERE
{
?type (rdfs:subClassOf)* gj:Country .
?this_0 rdf:type ?type ;
gn:countryCode "US"
# each of these blocks is executed as a standalone query in the engine
OPTIONAL
{ ?this_0 gn:countryCode ?countryCode_1}
OPTIONAL
{ ?this_0 gn:name ?name_2}
OPTIONAL
{ ?this_0 gj:cscId ?cscId_3}
}
Я использую конечную точку SPARQL REST в MarkLogic 8.4.
Обновить:
Я пытался запросить с optimize=2
вариант, но это не дало мне существенного улучшения производительности:
/v1/graphs/sparql?optimize=2
Связанный: Как мне указать опции в конечной точке SPARQL REST для MarkLogic?
Обновление 2:
Даже если я сделаю одно из необязательных свойств обязательным, запрос все еще работает медленно:
WHERE
{
?type (rdfs:subClassOf)* gj:Country .
?this_0 rdf:type ?type ;
gn:countryCode "US"; gj:cscId ?cscId_3 ;
}
Нужно ли делать что-то особенное, чтобы проиндексировать это свойство gj:cscId?
Обновление 3:
Вот информация о профиле из консоли запросов.
Обновление 4:
Вот диагностическая информация трассировки:
2017-04-27 13:30:17.238 Info: [Event:id=SPARQL Value Frequencies] sessionKey=13846462700334370907 namedGraphs=0 values=
2017-04-27 13:30:17.238 Info: <triple-value-statistics count="154569757" unique-subjects="25445373" unique-predicates="104" unique-objects="67520361" xmlns="cts:triple-value-statistics">
2017-04-27 13:30:17.238 Info: <triple-value-entries>
2017-04-27 13:30:17.238 Info: <triple-value-entry count="181">
2017-04-27 13:30:17.238 Info: <triple-value>http://kb.everest.cscglobal.com/geonames-jurisdiction/1.0/schema#Country</triple-value>
2017-04-27 13:30:17.238 Info: <subject-statistics count="2" unique-predicates="2" unique-objects="2"/>
2017-04-27 13:30:17.238 Info: <predicate-statistics count="0" unique-subjects="0" unique-objects="0"/>
2017-04-27 13:30:17.238 Info: <object-statistics count="179" unique-subjects="179" unique-predicates="4"/>
2017-04-27 13:30:17.238 Info: </triple-value-entry>
2017-04-27 13:30:17.238 Info: <triple-value-entry count="15">
2017-04-27 13:30:17.238 Info: <triple-value>http://www.w3.org/2000/01/rdf-schema#subClassOf</triple-value>
2017-04-27 13:30:17.238 Info: <subject-statistics count="0" unique-predicates="0" unique-objects="0"/>
2017-04-27 13:30:17.238 Info: <predicate-statistics count="15" unique-subjects="15" unique-objects="5"/>
2017-04-27 13:30:17.238 Info: <object-statistics count="0" unique-subjects="0" unique-predicates="0"/>
2017-04-27 13:30:17.238 Info: </triple-value-entry>
2017-04-27 13:30:17.238 Info: <triple-value-entry count="8739716">
2017-04-27 13:30:17.238 Info: <triple-value>http://www.w3.org/1999/02/22-rdf-syntax-ns#type</triple-value>
2017-04-27 13:30:17.238 Info: <subject-statistics count="0" unique-predicates="0" unique-objects="0"/>
2017-04-27 13:30:17.238 Info: <predicate-statistics count="8359510" unique-subjects="8341619" unique-objects="14"/>
2017-04-27 13:30:17.238 Info: <object-statistics count="0" unique-subjects="0" unique-predicates="0"/>
2017-04-27 13:30:17.238 Info: </triple-value-entry>
2017-04-27 13:30:17.238 Info: <triple-value-entry count="8697064">
2017-04-27 13:30:17.238 Info: <triple-value>http://www.geonames.org/ontology#countryCode</triple-value>
2017-04-27 13:30:17.238 Info: <subject-statistics count="2" unique-predicates="2" unique-objects="2"/>
2017-04-27 13:30:17.238 Info: <predicate-statistics count="8323137" unique-subjects="8323137" unique-objects="517"/>
2017-04-27 13:30:17.238 Info: <object-statistics count="1" unique-subjects="1" unique-predicates="1"/>
2017-04-27 13:30:17.238 Info: </triple-value-entry>
2017-04-27 13:30:17.238 Info: <triple-value-entry count="2119305">
2017-04-27 13:30:17.238 Info: <triple-value datatype="http://www.w3.org/2001/XMLSchema#string">US</triple-value>
2017-04-27 13:30:17.238 Info: <subject-statistics count="0" unique-predicates="0" unique-objects="0"/>
2017-04-27 13:30:17.238 Info: <predicate-statistics count="0" unique-subjects="0" unique-objects="0"/>
2017-04-27 13:30:17.238 Info: <object-statistics count="2061783" unique-subjects="2061783" unique-predicates="3"/>
2017-04-27 13:30:17.238 Info: </triple-value-entry>
2017-04-27 13:30:17.238 Info: <triple-value-entry count="13946907">
2017-04-27 13:30:17.238 Info: <triple-value>http://kb.everest.cscglobal.com/geonames-jurisdiction/1.0/schema#cscId</triple-value>
2017-04-27 13:30:17.238 Info: <subject-statistics count="3" unique-predicates="3" unique-objects="3"/>
2017-04-27 13:30:17.238 Info: <predicate-statistics count="11739004" unique-subjects="11739004" unique-objects="11739004"/>
2017-04-27 13:30:17.238 Info: <object-statistics count="0" unique-subjects="0" unique-predicates="0"/>
2017-04-27 13:30:17.238 Info: </triple-value-entry>
2017-04-27 13:30:17.238 Info: </triple-value-entries>
2017-04-27 13:30:17.238 Info: </triple-value-statistics>
2017-04-27 13:30:17.239 Info: [Event:id=SPARQL AST] sessionKey=13846462700334370907
2017-04-27 13:30:17.239 Info: initialPlan=SPARQLModule[
2017-04-27 13:30:17.239 Info: Prolog[]
2017-04-27 13:30:17.239 Info: SPARQLSelect[SPARQLProject[order()
2017-04-27 13:30:17.239 Info: GraphNode[Var type 0]
2017-04-27 13:30:17.239 Info: GraphNode[Var this_0 1]
2017-04-27 13:30:17.239 Info: GraphNode[Var cscId_3 2]
2017-04-27 13:30:17.239 Info: SPARQLLeftNestedLoopJoin[order() hash(1==1) scatter(1 = 1)
2017-04-27 13:30:17.239 Info: SPARQLNestedLoopJoin[order() hash(1==1) scatter(1 = 1)
2017-04-27 13:30:17.239 Info: SPARQLScatterJoin[order(0,1) hash(0==0) scatter(0 = 0)
2017-04-27 13:30:17.239 Info: SPARQLZeroOrOne[
2017-04-27 13:30:17.239 Info: GraphNode[Var type 0]
2017-04-27 13:30:17.239 Info: GraphNode[IRI <http://kb.everest.cscglobal.com/geonames-jurisdiction/1.0/schema#Country>]
2017-04-27 13:30:17.239 Info: SPARQLScatterOneOrMore[
2017-04-27 13:30:17.239 Info: GraphNode[Var type 0]
2017-04-27 13:30:17.239 Info: GraphNode[Var ANON16629111911678922088 0]
2017-04-27 13:30:17.239 Info: GraphNode[Var ANON7634081659815295853 1]
2017-04-27 13:30:17.239 Info: GraphNode[IRI <http://kb.everest.cscglobal.com/geonames-jurisdiction/1.0/schema#Country>]
2017-04-27 13:30:17.239 Info: TriplePattern[order(0,1) PSO
2017-04-27 13:30:17.239 Info: GraphNode[Var ANON16629111911678922088 0]
2017-04-27 13:30:17.239 Info: GraphNode[IRI <http://www.w3.org/2000/01/rdf-schema#subClassOf>]
2017-04-27 13:30:17.239 Info: GraphNode[Var ANON7634081659815295853 1]]]]
2017-04-27 13:30:17.239 Info: TriplePattern[order(0,1) OPS
2017-04-27 13:30:17.239 Info: GraphNode[Var this_0 1]
2017-04-27 13:30:17.239 Info: GraphNode[IRI <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>]
2017-04-27 13:30:17.239 Info: GraphNode[Var type 0]]]
2017-04-27 13:30:17.239 Info: TriplePattern[order(1) SOP
2017-04-27 13:30:17.239 Info: GraphNode[Var this_0 1]
2017-04-27 13:30:17.239 Info: GraphNode[IRI <http://www.geonames.org/ontology#countryCode>]
2017-04-27 13:30:17.239 Info: GraphNode[Literal "US"]]]
2017-04-27 13:30:17.239 Info: TriplePattern[order(1,2) PSO
2017-04-27 13:30:17.239 Info: GraphNode[Var this_0 1]
2017-04-27 13:30:17.239 Info: GraphNode[IRI <http://kb.everest.cscglobal.com/geonames-jurisdiction/1.0/schema#cscId>]
2017-04-27 13:30:17.239 Info: GraphNode[Var cscId_3 2]]]]]]
2017-04-27 13:30:17.239 Info: [Event:id=SPARQL Cost Analysis] sessionKey=13846462700334370907 optimize=1 r=3 t=1.28811 os=360 is=15 mutations=30 seed=7088858925989728751
2017-04-27 13:30:17.239 Info: initialCost=(m:5.99223e+11,r:0,io:(52.9404/167736/1.17487e+09),cpu(1):(0/1.77017e+08/1.18652e+12),mem:8185,c:1.03266e+07,crd:[14,2.06178e+06,1.03266e+07])
2017-04-27 13:30:17.320 Info: [Event:id=SPARQL Cost Analysis] sessionKey=13846462700334370907 diff=-5.98971e+11 diff%=-99.958 r=0
2017-04-27 13:30:17.320 Info: cost=(m:2.51757e+08,r:0,io:(52.9404/322.031/4.68406e+07),cpu(4):(0/159/3.51041e+07),mem:415.68,c:6.46969e+06,crd:[14,2.06178e+06,6.46969e+06])
2017-04-27 13:30:17.320 Info: [Event:id=SPARQL Cost Analysis] sessionKey=13846462700334370907 diff=-5.98971e+11 diff%=-99.958 r=1
2017-04-27 13:30:17.320 Info: cost=(m:2.51757e+08,r:0,io:(52.9404/322.031/4.68406e+07),cpu(4):(0/159/3.51041e+07),mem:415.68,c:6.46969e+06,crd:[14,2.06178e+06,6.46969e+06])
2017-04-27 13:30:17.326 Info: [Event:id=SPARQL Cost Analysis] sessionKey=13846462700334370907 diff=-5.98971e+11 diff%=-99.958 r=2
2017-04-27 13:30:17.326 Info: cost=(m:2.51757e+08,r:0,io:(52.9404/322.031/4.68406e+07),cpu(4):(0/159/3.51041e+07),mem:415.68,c:6.46969e+06,crd:[14,2.06178e+06,6.46969e+06])
2017-04-27 13:30:17.326 Info: [Event:id=SPARQL Cost Analysis] sessionKey=13846462700334370907
2017-04-27 13:30:17.326 Info: bestCost=(m:2.51757e+08,r:0,io:(52.9404/322.031/4.68406e+07),cpu(4):(0/159/3.51041e+07),mem:415.68,c:6.46969e+06,crd:[14,2.06178e+06,6.46969e+06])
2017-04-27 13:30:17.326 Info: [Event:id=SPARQL AST] sessionKey=13846462700334370907
2017-04-27 13:30:17.326 Info: plan=SPARQLModule[
2017-04-27 13:30:17.326 Info: Prolog[]
2017-04-27 13:30:17.326 Info: SPARQLSelect[SPARQLProject[order(1,0)
2017-04-27 13:30:17.326 Info: GraphNode[Var type 0]
2017-04-27 13:30:17.326 Info: GraphNode[Var this_0 1]
2017-04-27 13:30:17.326 Info: GraphNode[Var cscId_3 2]
2017-04-27 13:30:17.326 Info: SPARQLRightMergeJoin[order(1,0) hash(1==1) scatter()
2017-04-27 13:30:17.326 Info: TriplePattern[order(1,2) PSO
2017-04-27 13:30:17.326 Info: GraphNode[Var this_0 1]
2017-04-27 13:30:17.326 Info: GraphNode[IRI <http://kb.everest.cscglobal.com/geonames-jurisdiction/1.0/schema#cscId>]
2017-04-27 13:30:17.326 Info: GraphNode[Var cscId_3 2]]
2017-04-27 13:30:17.326 Info: SPARQLHashJoin[order(1,0) hash(0==0) scatter()
2017-04-27 13:30:17.326 Info: SPARQLZeroOrOne[
2017-04-27 13:30:17.326 Info: GraphNode[Var type 0]
2017-04-27 13:30:17.326 Info: GraphNode[IRI <http://kb.everest.cscglobal.com/geonames-jurisdiction/1.0/schema#Country>]
2017-04-27 13:30:17.326 Info: SPARQLBloomOneOrMore[
2017-04-27 13:30:17.326 Info: GraphNode[IRI <http://kb.everest.cscglobal.com/geonames-jurisdiction/1.0/schema#Country>]
2017-04-27 13:30:17.326 Info: GraphNode[Var ANON7634081659815295853 1]
2017-04-27 13:30:17.326 Info: GraphNode[Var ANON16629111911678922088 0]
2017-04-27 13:30:17.326 Info: GraphNode[Var type 0]
2017-04-27 13:30:17.326 Info: TriplePattern[order(0,1) PSO
2017-04-27 13:30:17.326 Info: GraphNode[Var ANON16629111911678922088 0]
2017-04-27 13:30:17.326 Info: GraphNode[IRI <http://www.w3.org/2000/01/rdf-schema#subClassOf>]
2017-04-27 13:30:17.326 Info: GraphNode[Var ANON7634081659815295853 1]]]]
2017-04-27 13:30:17.326 Info: SPARQLMergeJoin[order(1,0) hash(1==1) scatter()
2017-04-27 13:30:17.326 Info: TriplePattern[order(1) OPS
2017-04-27 13:30:17.326 Info: GraphNode[Var this_0 1]
2017-04-27 13:30:17.326 Info: GraphNode[IRI <http://www.geonames.org/ontology#countryCode>]
2017-04-27 13:30:17.326 Info: GraphNode[Literal "US"]]
2017-04-27 13:30:17.326 Info: TriplePattern[order(1,0) PSO
2017-04-27 13:30:17.326 Info: GraphNode[Var this_0 1]
2017-04-27 13:30:17.326 Info: GraphNode[IRI <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>]
2017-04-27 13:30:17.326 Info: GraphNode[Var type 0]]]]]]]]
Обновление 5:
В некоторых случаях я обнаружил, что могу устранить ?type
выражение пути свойства из запроса. В одном таком случае производительность улучшилась на два порядка:
WHERE
{
?this_0 rdf:type gj:Country ;
gn:countryCode "US"
# each of these blocks is executed as a standalone query in the engine
OPTIONAL
{ ?this_0 gn:countryCode ?countryCode_1}
OPTIONAL
{ ?this_0 gn:name ?name_2}
OPTIONAL
{ ?this_0 gj:cscId ?cscId_3}
}
Поскольку это решение изменяет вывод запроса, оно не решает все наши варианты использования.
Кажется, что проблема не в самих OPTIONAL, а в том, что выражение пути пути свойства сбивает с толку планировщика запросов, поэтому свойства в блоках OPTIONAL ищутся независимо (что не является производительным).
2 ответа
Оптимизатор запросов использует статистику для определения наилучшего порядка операций. Часто встречается ограничительный тройной паттерн, который можно использовать для ограничения дальнейших операций с использованием скаттер-соединения.
В вашем случае статистика не дает такого очевидного ограничительного тройного паттерна. Посмотрев в вывод статистики тройного значения, вы можете увидеть, что строка "US" встречается 2061783 раз как объект - так что это не слишком ограничительно.
IRI gj:Country является ограничительным (179 раз в положении объекта), но, к сожалению, вам нужно использовать его справа от оператора переходного замыкания. Очень сложно предсказать, сколько результатов вернет оператор транзитивного замыкания, так как это во многом зависит от фактических данных.
Вы обнаружите, что использование пути к свойствам, подобного приведенному ниже, позволит MarkLogic избежать использования оператора "ноль или один", что может привести к небольшому повышению производительности:
?this_0 a/rdfs:subClassOf* gj:Country .
Если вы знаете, что (например) существует только одна gj:Country с кодом страны "US", вы можете добавить ограничение для этой части запроса, чтобы дать оптимизатору подсказки о том, как обрабатывать запрос, т.е.:
select * {
{
select * {
?this_0 a/rdfs:subClassOf* gj:Country .
?this_0 gn:countryCode 'US' .
} limit 1
}
OPTIONAL { ?this_0 gj:cscId ?cscId_3 }
}
У Marklogic 8, похоже, есть проблема с производительностью путей использования свойств *
, Попробуйте заменить
?type (rdfs:subClassOf)* gj:Country .
с
{
BIND(gj:Country AS ?type)
} UNION {
?type (rdfs:subClassOf)+ gj:Country .
}