Объедините запросы SELECT и ASK в одном запросе.

Контекст: 14 миллионов троек, верстак Blazegraph. В настоящее время я пытаюсь разработать запросы, которые сочетают в себе SELECT и ASK. Точнее, я хочу выбрать результаты на своем графике, где предположение верно.

Для моего примера представьте, что у меня есть много книг, у которых есть один автор и один редактор. Я хочу выбрать книгу автора, книга которой связана через свойство случайной длины пути с client#1.

В моем случае с моими данными требуется много времени, чтобы реализовать запрос прямо так:

SELECT ?id_book
WHERE {?id_book prefix:hasAuthor :author#1.
        ?id_book prefix:linkedToEditor*/prefix:hasClient :client#1}
ORDER by ?id_book

Чтобы сократить время вычислений (x 1:1000), я использую скрипт для последовательной реализации этих запросов. Скрипт выбирает книги, автором которых является автор №1:

SELECT ?id_book
WHERE {?id_book prefix:hasAuthor :author#1}
ORDER by ?id_book

И я запрашиваю каждый результат от 1 до n (id_book#1, id_book#2, ..., id_book#n), если он связан с клиентом № 1:

ASK {id_book#i prefix:linkedToEditor*/prefix:hasClient :client#1}

Запрос SELECT, за которым следует запрос ASK, намного быстрее, чем первый запрос SELECT для тех же результатов. Я не хочу исследовать все возможности ?id_book prefix:linkedToEditor*/prefix:hasClient :client#1; Я просто хочу сохранить результаты там, где существует ссылка. Я пробовал с FILTER EXISTS или двумя запросами SELECT, но время запроса одинаково велико:

SELECT ?id_book
WHERE {?id_book prefix:hasAuthor :author#1.}
FILTER EXIST {?id_book prefix:linkedToEditor*/prefix:hasClient :client#1}
ORDER by ?id_book

or

SELECT ?id_book
WHERE {?id_book prefix:linkedToEditor*/prefix:hasClient :client#1.
    {SELECT ?id_book
        WHERE {?id_book prefix:hasAuthor :author#1.}
    }
}

Как я могу оптимизировать свои запросы в один запрос?


person Cyril    schedule 17.08.2015    source источник
comment
Как указано в ответе ниже, ваш опыт довольно удивителен. Я мог бы предложить вам рассмотреть и, возможно, протестировать несколько различных хранилищ RDF и/или процессоров SPARQL. Есть из чего выбрать...   -  person TallTed    schedule 20.08.2015


Ответы (1)


Немного удивительно, что есть такая разница во времени ваших запросов; механизм SPARQL, вероятно, должен быть в состоянии оптимизировать запрос, чтобы сначала выполнить простую часть, а затем выполнить более сложный путь свойства запроса. Порядок также может привести к некоторому увеличению времени, и это действительно не важно, если вас интересуют только логические результаты.

В любом случае, поскольку вложенные запросы выполняются в первую очередь, вы можете как бы заставить «сначала сделать это, затем сделать это», вложив запросы следующим образом:

select ?id_book {
  #-- first, get the books by author one
  { select ?id_book { ?id_book prefix:hasAuthor :author#1 } }

  #-- then, then check that the book is related to client one
  ?id_book prefix:linkedToEditor*/prefix:hasClient :client#1
}
order by ?id_book
person Joshua Taylor    schedule 17.08.2015
comment
Этот запрос занимает много времени в моем случае. Я думаю, что механизм SPARQL проверяет каждую возможность во втором запросе, а затем сравнивает с первым запросом, чтобы получить результаты. Похоже, это случай с движком SPARQL Blazegraph. - person Cyril; 17.08.2015
comment
Подзапросы @Cyril должны оцениваться в первую очередь. Это должно найти несколько значений ?id_book, а затем проверить каждое из них. Если кажется, что ваш движок делает что-то другое, что произойдет, если вы поменяете позиции этих запросов? То есть положить внешний внутрь? Кроме того, есть ли какие-либо изменения, если вы не заказываете результаты? - person Joshua Taylor; 17.08.2015
comment
Я лучше понимаю поведение моего запроса. С предложенным вами запросом я правильно получаю ?id_book with the author#1, но второй запрос определяет все пути, где ?id_book проверен linkedToEditor*/hasClient; это занимает слишком много времени. И может использовать DISTINCT, но DISTINCT проверяет все пути и ограничивает результаты, где ?id_book DISTINCT: это занимает то же время. - person Cyril; 19.08.2015
comment
Лучше всего было бы ограничить второй запрос одним результатом для каждого ?id_book, найденного в первом запросе. В моем случае второй запрос имеет много решений (слишком много промежуточных редакторов), и это занимает слишком много времени. - person Cyril; 19.08.2015
comment
@Cyril, в свете этого помогает ли изменение самого внешнего выбора на select distinct ?id_book ...? - person Joshua Taylor; 19.08.2015
comment
Для справки, запрос внутри FILTER EXISTS имеет более 10 тысяч решений. Один только этот запрос занимает более 600 000 мс, чтобы получить результаты на моем ПК (mac pro 8go RAM и 4 ядра). Запрос DISTINCT просто выбирает из всех результатов результаты с различными ?id_book. Исчисление не ограничивается одним на ?id_book. Было бы идеально, если бы запрос в FILTER EXISTS мог быть ограничен ОДНИМ результатом. Я посылаю свои данные и свои процедуры персоналу Blazegraph. Они реактивны, и продукт очень хорош. Я думаю, у них будет ответ. - person Cyril; 20.08.2015
comment
@Cyril Если единственным значением, которое вы выбираете, является ?id_book, то выполнение SELECT DISTINCT ?id_book ... позволит движку SPARQL остановиться после проверки только одного из этих 10 тысяч решений для каждого кандидата в значение ?id_book, поскольку этого было бы достаточно, чтобы включить значение, и изучение большего количества из этих 10 тысяч решений не может ничего добавить к результатам запроса. - person Joshua Taylor; 20.08.2015
comment
@Cyril Запрос DISTINCT просто выбирает среди всех результатов результаты с отличным ?id_book. Обратите внимание, что я предложил изменить самый внешний запрос, чтобы выбрать отдельный. То есть, делая select distinct ?id_book { { select ?id_book ...} ?id_book path value }. Затем движок может определить, что требуется только одно совпадение для ?id_book path value, поскольку дополнительные пути ничего не добавляют. Но теперь, когда вы упомянули об этом, выполнение Different в inner запросе будет означать, что вы не повторяете там никаких значений ?id_book, поэтому может помочь использование Different в обоих местах. (Внутренний отчет может помочь больше?) - person Joshua Taylor; 20.08.2015
comment
На данный момент с моей конфигурацией, с DISTINCT или без него, даже когда я переключаю внутренний/внешний порядок запросов => результат тот же с точки зрения времени и исчисления на стороне сервера. Жду комментарий персонала. - person Cyril; 20.08.2015