#query-optimization #sparql #semantic-web #virtuoso
#оптимизация запросов #sparql #семантическая сеть #виртуоз
Вопрос:
Насколько я понимаю, Virtuoso преобразует запросы SPARQL, которые я запускаю в его интерфейсе (будь то из веб-приложения, консольной isql
команды или из HTTP API), в SQL, а затем Virtuoso запрашивает свои внутренние базы данных SQL.
Прямо сейчас я пытаюсь выполнить простой, но отнимающий много времени запрос на довольно больших графиках (примерно от 1 М до 10 м троек): подсчитываю количество радужных оболочек и пустых узлов на моих графиках. В случае пустых узлов я запускаю два следующих запроса:
DEFINE sql:log-enable 2
WITH <http://localhost/tcl/>
SELECT COUNT(DISTINCT *)
WHERE {?s ?p ?o FILTER isBlank(?o)}
DEFINE sql:log-enable 2
WITH <http://localhost/tcl/>
SELECT COUNT(DISTINCT *)
WHERE {?s ?p ?o FILTER isBlank(?s)}
В то время как первое выполняется довольно быстро (5-6 секунд, результат — 352 550 пустых узлов), второе выполняется сравнительно очень медленно (~ 1 минута, результат — 885 255 пустых узлов). Такое поведение также происходит с другими графиками.
Чтобы продвинуться в этом дальше, я попытался проанализировать компиляцию SQL. И действительно, они совершенно разные.
Первый запрос (подсчет пустых объектов) разлагается как таковой:
SELECT COUNT ( DISTINCT
box_hash (
__id2in ( "s_1_1_t0"."S"),
__id2in ( "s_1_1_t0"."P"),
__ro2sq ( "s_1_1_t0"."O"))) AS "callret-0"
FROM DB.DBA.RDF_QUAD AS "s_1_1_t0"
WHERE
"s_1_1_t0"."G" = __i2idn ( __bft( 'http://localhost/tcl/' , 1))
AND
is_bnode_iri_id ( "s_1_1_t0"."O")
OPTION (QUIETCAST)
В то время как второй (количество пустых объектов) преобразуется в:
SELECT COUNT ( DISTINCT
box_hash (
__id2in ( "s_2_1_t0"."S"),
__id2in ( "s_2_1_t0"."P"),
__ro2sq ( "s_2_1_t0"."O"))) AS "callret-0"
FROM DB.DBA.RDF_QUAD AS "s_2_1_t0"
WHERE
"s_2_1_t0"."G" = __i2idn ( __bft( 'http://localhost/tcl/' , 1))
AND
( "s_2_1_t0"."S" >= min_bnode_iri_id ())
OPTION (QUIETCAST)
Как вы можете видеть, предпоследняя строка отличается. Итак, любопытствуя об этой разнице, я попытался составить запрос, используя «быструю» структуру, но для ускорения «медленных» результатов: Я заменил ( "s_2_1_t0"."S" >= min_bnode_iri_id ())
на is_bnode_iri_id ( "s_1_1_t0"."S")
.
И это сработало! Я получил то же самое точное число, за исключением того, что намного быстрее (9-10 секунд).
Итак, теперь я хочу спросить: как я могу изменить способ преобразования запроса SPARQL в SQL? Или есть способ напрямую запрашивать базы данных SQL из внешнего приложения?
Эти запросы SPARQL обычно выполняются в коде Python, поэтому я не могу делать это вручную каждый раз.
Комментарии:
1. вы уверены, что ваши запросы выполняют то, что вы хотите?
SELECT COUNT(DISTINCT *) WHERE {?s ?p ?o FILTER isBlank(?o)}
возвращает количество троек с пустыми узлами, но не так, как вы сказали «352 550 пустых узлов»2. Я не знаю, как вы хотите это изменить или возможно ли отключить или повлиять на используемый план запроса. Используется оптимизатор запросов, и похоже, что используется другой план запроса индекс.
3. я знаю, что вы действительно можете подключиться к базе данных SQL, например, через Python: docs.openlinksw.com/virtuoso/execpythonscript
4. Возможно, моя формулировка была немного двусмысленной. Сумма результирующих значений обоих запросов дает мне количество троек с пустыми узлами в позиции субъекта количество троек с пустыми узлами в позиции объекта. Это равно общему количеству пустых узлов на графике, если я не ошибаюсь (в моей ситуации я заранее знаю, что в позиции предиката нет пустых узлов).
5. Технически это верно, но эти вычисления в основном предназначены для подсчета распространенности пустых узлов на графике, поэтому мои вычисления (которые скорее представляют собой » количество позиций, занятых пустыми узлами «, а не » количество пустых узлов » на самом деле) кажутся более уместными в моей ситуации. Но ваше замечание верно, и это ошибка