Изменить преобразование SQL запроса SPARQL в Virtuoso

#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. Технически это верно, но эти вычисления в основном предназначены для подсчета распространенности пустых узлов на графике, поэтому мои вычисления (которые скорее представляют собой » количество позиций, занятых пустыми узлами «, а не » количество пустых узлов » на самом деле) кажутся более уместными в моей ситуации. Но ваше замечание верно, и это ошибка