SPARQL Ускорить федеративный запрос
У меня есть собственный набор данных, и я хочу выполнить федеративный запрос в SPARQL. Вот запрос:
PREFIX : <http://myURIsNamespace#>
PREFIX wd: <http://www.wikidata.org/entity/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX p: <http://www.wikidata.org/prop/>
PREFIX ps: <http://www.wikidata.org/prop/statement/>
PREFIX pq: <http://www.wikidata.org/prop/qualifier/>
PREFIX wdt: <http://www.wikidata.org/prop/direct/>
select * where {
?bioentity :hasMutatedVersionOf ?gene .
?gene :partOf wd:Q430258 .
SERVICE <https://query.wikidata.org/sparql> {
?gene p:P644 ?statement;
wdt:P31 wd:Q7187 ;
wdt:P703 wd:Q15978631 ;
wdt:P1057 wd:Q430258 .
?statement ps:P644 ?start .
?statement pq:P659 wd:Q20966585 .
?gene p:P645 ?statement2.
?statement2 ps:P645 ?end .
?statement2 pq:P659 wd:Q20966585 .
FILTER (xsd:integer(?start)>21000000 && xsd:integer(?start)<30000000)
}
}
Я запускаю запрос через интерфейс SPARQL graphDB, но он действительно очень медленный. Чтобы вернуть 8 записей, требуется больше минуты. Если я разделю запрос на две части, они будут смехотворно быстрыми.
Запрос # 1
select * where {
?bioentity :hasMutatedVersionOf ?gene .
?gene :partOf wd:Q430258 .
}
56 записей за 0,1 с
Запрос # 2
select * where {
SERVICE <https://query.wikidata.org/sparql> {
?gene p:P644 ?statement;
wdt:P31 wd:Q7187 ;
wdt:P703 wd:Q15978631 ;
wdt:P1057 wd:Q430258 .
?statement ps:P644 ?start .
?statement pq:P659 wd:Q20966585 .
?gene p:P645 ?statement2.
?statement2 ps:P645 ?end .
?statement2 pq:P659 wd:Q20966585 .
FILTER (xsd:integer(?start)>21000000 && xsd:integer(?start)<30000000)
}
}
158 записей за 0,5 с
Почему федерация такая медленная? Есть ли способ оптимизировать производительность?
1 ответ
Короткий ответ
Просто разместите свой
SERVICE
часть первая, т.е. раньше?bioentity :hasMutatedVersionOf ?gene .
Прочитайте хорошую статью по этой теме (например, глава 5 этой книги)
Соответствующая цитата из вышеупомянутой статьи:
3.3.2 Оптимизация и выполнение запросов
Порядок выполнения операторов запросов существенно влияет на общую стоимость оценки запросов. Помимо важного времени выполнения запроса в сценарии объединения есть и другие аспекты, которые имеют отношение к оптимизации запроса:
Минимизация стоимости связи. Количество контактируемых источников данных напрямую влияет на производительность выполнения запроса из-за накладных расходов на связь. Однако уменьшение количества задействованных источников данных идет вразрез с полнотой результатов.
Оптимизация локализации исполнения. Стандартные интерфейсы запросов связанных источников данных, как правило, способны отвечать только на запросы по предоставленным данным. Следовательно, объединения с другими результатами данных, как правило, необходимо выполнять в источнике запросов. Если вообще возможно, лучшая стратегия переместит части операций слияния результатов в источники данных, особенно если они могут выполняться параллельно.
Потоковые результаты. Получение полного результата при оценке запроса для большого набора данных может занять некоторое время даже при хорошо оптимизированной стратегии выполнения. Таким образом, можно возвращать результаты, как только они становятся доступными, что можно оптимизировать, пытаясь сначала вернуть релевантные результаты.
Длинный ответ
Пример данных
PREFIX : <http://myURIsNamespace#>
PREFIX wd: <http://www.wikidata.org/entity/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX p: <http://www.wikidata.org/prop/>
PREFIX ps: <http://www.wikidata.org/prop/statement/>
PREFIX pq: <http://www.wikidata.org/prop/qualifier/>
PREFIX wdt: <http://www.wikidata.org/prop/direct/>
INSERT { ?gene rdf:type owl:Thing }
WHERE {
SERVICE <https://query.wikidata.org/sparql> {
?gene p:P644 ?statement;
wdt:P31 wd:Q7187 ;
wdt:P703 wd:Q15978631 ;
wdt:P1057 wd:Q430258 .
?statement ps:P644 ?start .
?statement pq:P659 wd:Q20966585 .
?gene p:P645 ?statement2.
?statement2 ps:P645 ?end .
?statement2 pq:P659 wd:Q20966585 .
FILTER (xsd:integer(?start)>26000000 && xsd:integer(?start)<30000000)
}
}
Общее количество троек составляет 79. Обратите внимание, что 26000000
используется вместо 21000000
,
Запрос 1
PREFIX : <http://myURIsNamespace#>
PREFIX wd: <http://www.wikidata.org/entity/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX p: <http://www.wikidata.org/prop/>
PREFIX ps: <http://www.wikidata.org/prop/statement/>
PREFIX pq: <http://www.wikidata.org/prop/qualifier/>
PREFIX wdt: <http://www.wikidata.org/prop/direct/>
SELECT * WHERE {
?gene rdf:type owl:Thing .
SERVICE <https://query.wikidata.org/sparql> {
?gene p:P644 ?statement;
wdt:P31 wd:Q7187 ;
wdt:P703 wd:Q15978631 ;
wdt:P1057 wd:Q430258 .
?statement ps:P644 ?start .
?statement pq:P659 wd:Q20966585 .
?gene p:P645 ?statement2.
?statement2 ps:P645 ?end .
?statement2 pq:P659 wd:Q20966585 .
FILTER (xsd:integer(?start)>20000000 && xsd:integer(?start)<30000000)
}
}
Запрос 2
PREFIX : <http://myURIsNamespace#>
PREFIX wd: <http://www.wikidata.org/entity/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX p: <http://www.wikidata.org/prop/>
PREFIX ps: <http://www.wikidata.org/prop/statement/>
PREFIX pq: <http://www.wikidata.org/prop/qualifier/>
PREFIX wdt: <http://www.wikidata.org/prop/direct/>
SELECT * WHERE {
SERVICE <https://query.wikidata.org/sparql> {
?gene p:P644 ?statement;
wdt:P31 wd:Q7187 ;
wdt:P703 wd:Q15978631 ;
wdt:P1057 wd:Q430258 .
?statement ps:P644 ?start .
?statement pq:P659 wd:Q20966585 .
?gene p:P645 ?statement2.
?statement2 ps:P645 ?end .
?statement2 pq:P659 wd:Q20966585 .
FILTER (xsd:integer(?start)>20000000 && xsd:integer(?start)<30000000)
}
?gene rdf:type owl:Thing
}
Спектакль
+------------+---------+---------+
| | Query 1 | Query 2 |
+------------+---------+---------+
| GraphDB | 30 sec | 1 sec |
| Blazegraph | 1 sec | 1 sec |
+------------+---------+---------+
Поведение GraphDB
Выполняя Запрос 1, GraphDB выполняет 79 различных GET
просит Wikidata¹:
Эти запросы являются запросами такого рода:
SELECT ?start ?statement ?end ?statement2 WHERE {
<http://www.wikidata.org/entity/Q18031286> p:P644 ?statement;
wdt:P31 wd:Q7187 ;
wdt:P703 wd:Q15978631 ;
wdt:P1057 wd:Q430258 .
?statement ps:P644 ?start .
?statement pq:P659 wd:Q20966585 .
<http://www.wikidata.org/entity/Q18031286> p:P645 ?statement2.
?statement2 ps:P645 ?end .
?statement2 pq:P659 wd:Q20966585 .
FILTER (xsd:integer(?start)>20000000 && xsd:integer(?start)<30000000)
Интересно, что на другой машине GraphDB выполняет GET
запросы другого вида:
GET /sparql?queryLn="Sparql"&query=<original_query_service_part>&$gene=<http://www.wikidata.org/entity/Q18031286>
В этом запросе используется протокол Sesame, эти привязки в URL не являются частью протокола SPARQL 1.1.
Возможно, точный вид запроса зависит от стоимости внутреннего reuse.vars.in.subselects
параметр, значение которого по умолчанию предположительно отличается в Windows и Linux.
Поведение блейзографа
Выполняя Query 1, Blazegraph выполняет одиночный POST
запрос к Wikidata²:
SELECT ?gene ?statement ?start ?statement2 ?end
WHERE {
?gene p:P644 ?statement;
wdt:P31 wd:Q7187 ;
wdt:P703 wd:Q15978631 ;
wdt:P1057 wd:Q430258 .
?statement ps:P644 ?start .
?statement pq:P659 wd:Q20966585 .
?gene p:P645 ?statement2.
?statement2 ps:P645 ?end .
?statement2 pq:P659 wd:Q20966585 .
FILTER (xsd:integer(?start)>20000000 && xsd:integer(?start)<30000000)
}
VALUES ( ?gene) {
( wd:Q14908148 ) ( wd:Q15320063 ) ( wd:Q17861651 ) ( wd:Q17917753 ) ( wd:Q17928333 )
( wd:Q18024923 ) ( wd:Q18026347 ) ( wd:Q18030710 ) ( wd:Q18031220 ) ( wd:Q18031457 )
( wd:Q18031551 ) ( wd:Q18031832 ) ( wd:Q18032918 ) ( wd:Q18033094 ) ( wd:Q18033798 )
( wd:Q18034311 ) ( wd:Q18035006 ) ( wd:Q18035085 ) ( wd:Q18035609 ) ( wd:Q18036516 )
( wd:Q18036676 ) ( wd:Q18037580 ) ( wd:Q18038385 ) ( wd:Q18038459 ) ( wd:Q18038737 )
( wd:Q18038763 ) ( wd:Q18039997 ) ( wd:Q18040291 ) ( wd:Q18041261 ) ( wd:Q18041415 )
( wd:Q18041558 ) ( wd:Q18045881 ) ( wd:Q18047232 ) ( wd:Q18047373 ) ( wd:Q18047918 )
( wd:Q18047966 ) ( wd:Q18048744 ) ( wd:Q18049145 ) ( wd:Q18049164 ) ( wd:Q18053139 )
( wd:Q18056540 ) ( wd:Q18057411 ) ( wd:Q18060804 ) ( wd:Q18060856 ) ( wd:Q18060876 )
( wd:Q18060905 ) ( wd:Q18060958 ) ( wd:Q20773708 ) ( wd:Q15312971 ) ( wd:Q17860819 )
( wd:Q17917713 ) ( wd:Q18026310 ) ( wd:Q18027015 ) ( wd:Q18031286 ) ( wd:Q18032599 )
( wd:Q18032797 ) ( wd:Q18035169 ) ( wd:Q18035627 ) ( wd:Q18039938 ) ( wd:Q18041207 )
( wd:Q18041512 ) ( wd:Q18041930 ) ( wd:Q18045491 ) ( wd:Q18045762 ) ( wd:Q18046301 )
( wd:Q18046472 ) ( wd:Q18046487 ) ( wd:Q18047149 ) ( wd:Q18047491 ) ( wd:Q18047719 )
( wd:Q18048527 ) ( wd:Q18049774 ) ( wd:Q18051886 ) ( wd:Q18053875 ) ( wd:Q18056212 )
( wd:Q18056538 ) ( wd:Q18065866 ) ( wd:Q20766978 ) ( wd:Q20781543 )
}
Заключение
При федеративных запросах сложно создать эффективный план выполнения, поскольку селективность удаленных шаблонов неизвестна.
В вашем конкретном случае должно быть не очень важно, объединять результаты локально или удаленно, потому что и локальные, и удаленные наборы результатов невелики. Однако в GraphDB удаленное объединение результатов менее эффективно, поскольку GraphDB не снижает расходы на связь.
¹ Для создания скриншотов, <http://query.wikidata.org/sparql>
вместо <https://query.wikidata.org/sparql>
использовался.
² В Blazegraph можно написать hint:Query hint:optimizer "None"
обеспечить последовательную оценку.