Jena Оптимизация запросов ARQ/TDB

У меня есть довольно небольшой график, содержащий примерно 500 тыс. троек. Я также сгенерировал файл stats.opt и запустил свой код на довольно быстром компьютере (четырехъядерный процессор, 16 ГБ ОЗУ, твердотельный накопитель). Но для запроса, который я создаю с помощью интерфейса OP, требуется вечность. перебрать набор результатов. Набор результатов содержит около 15000 строк, а итерация занимает 4 секунды, что неприемлемо для конечных пользователей. Выполнение запроса занимает всего 90 мс (думаю, реальная работа выполняется итерацией курсора?). Почему это так медленно и что я могу сделать, чтобы ускорить итерацию набора результатов?

Вот запрос:

SELECT  ?apartment ?price ?hasBalcony ?lat ?long ?label ?hasImage ?park ?supermarket ?rooms ?area ?street
WHERE
  { ?apartment dssd:hasBalcony ?hasBalcony .
    ?apartment wgs84:lat ?lat .
    ?apartment wgs84:long ?long .
    ?apartment rdfs:label ?label .
    ?apartment dssd:hasImage ?hasImage .
    ?apartment dssd:hasNearby ?hasNearbyPark .
    ?hasNearbyPark dssd:hasNearbyPark ?park .
    ?apartment dssd:hasNearby ?hasNearbySupermarket .
    ?hasNearbySupermarket dssd:hasNearbySupermarket ?supermarket .
    ?apartment dssd:price ?price .
    ?apartment dssd:rooms ?rooms .
    ?apartment dssd:area ?area .
    ?apartment vcard:hasAddress ?address .
    ?address vcard:streetAddress ?street
    FILTER ( ?hasBalcony = true )
    FILTER ( ?price <= 1000.0e0 )
    FILTER ( ?price >= 650.0e0 )
    FILTER ( ?rooms <= 4.0e0 )
    FILTER ( ?rooms >= 3.0e0 )
    FILTER ( ?area <= 100.0e0 )
    FILTER ( ?area >= 60.0e0 )
  }    

(Есть ли лучший способ запросить эти бноды: ?hasNearbyPark, ?hasNearbySupermarket)

И код для выполнения запроса:

dataset.begin(ReadWrite.READ);
Model model = dataset.getNamedModel("http://example.com");
QueryExecution queryExecution = QueryExecutionFactory.create(buildQuery(), model);
ResultSet resultSet = queryExecution.execSelect();
while ( resultSet.hasNext() ) {
    QuerySolution solution = resultSet.next(); ...

person Daniel Gerber    schedule 29.08.2013    source источник
comment
Вы можете использовать ?apartment dssd:hasNearby [ dssd:hasNearbyPark ?park ] и ?apartment dssd:hasNearby [ dssd:hasNearbySupermarket ?supermarket ] для парка и супермаркета, а также для ?address, который, похоже, вы не используете, за исключением получения ?street. С помощью ; вы также можете сэкономить кучу времени. Например, вместо ?apartment wgs84:lat ?lat . ?apartment wgs84:long ?long ., use ?apartment wgs84:lat ?lat ; wgs84:длинный ?длинный ; ...`.   -  person Joshua Taylor    schedule 29.08.2013
comment
Ну, я строю запрос программно с помощью OP, поэтому я не имею на это никакого влияния. Это изменит время выполнения?   -  person Daniel Gerber    schedule 29.08.2013
comment
Вместо FILTER ( ?hasBalcony = true ) вам, вероятно, следует просто запросить ?apartment dssd:hasBalcony true .. Есть ли разница в производительности, если вы начнете комбинировать выражения фильтра, например, FILTER ( ?price <= 1000.0e0 && ?price >= 650.0e0 ). Кроме того, для комнат, если это целочисленное значение, возможно, вы можете использовать {?apt rooms 3} UNION {?apt rooms 4}.   -  person Joshua Taylor    schedule 29.08.2013
comment
Синтаксис пустого узла эквивалентен. При написании вручную синтаксис пустого узла может быть более эстетичным, но он не более и не менее эффективен. То же самое касается сокращения с помощью ;. Тем не менее, немного о 3 и 4 комнатах с union вместо фильтра и hasBalcony true вместо filter( hasBalcony = true ) может ускорить процесс, так как они будут больше ограничивать совпадения, и позже будет меньше фильтров. Точно так же объединение выражений фильтра может быть лучше, но я не знаю, происходит ли это уже автоматически. Во всяком случае, это то, что нужно попробовать.   -  person Joshua Taylor    schedule 29.08.2013
comment
Я только что попытался выполнить запрос следующим образом:   -  person Daniel Gerber    schedule 29.08.2013
comment
Я только что опробовал ваши предложения, но время выполнения/итерации запроса не изменилось. :/все равно спасибо (извините, больше не могу удалять комментарии)   -  person Daniel Gerber    schedule 29.08.2013


Ответы (1)


В механизме запросов ARQ

Во-первых, вы, кажется, неправильно понимаете, как работает механизм ARQ:

ResultSet resultSet = queryExecution.execSelect();

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

Фактическая работа над ответом на ваш вопрос не происходит, пока вы не начнете звонить hasNext() и next():

while ( resultSet.hasNext() ) {
   QuerySolution solution = resultSet.next(); ...

Таким образом, время, которое вы указываете, неверно, для оценки запроса требуется 4 секунды, потому что именно столько времени требуется для повторения всех результатов.

По вашему актуальному вопросу

Вы не показали, что делает ваш метод buildQuery(), но вы говорите, что строите запрос как структуру Op программно, а не как строку? Если это так, то механизм запросов может на самом деле не применять оптимизацию, хотя я не думаю, что это будет проблемой. Вы можете попробовать добавить op = Algebra.optimize(op);, прежде чем вернуть построенный Op, но я не уверен, что это будет иметь большое значение.

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

Точно так же я не уверен, будет ли соблюден ваш stats.opt файл, потому что вы запрашиваете конкретную модель, а не набор данных TDB, поэтому механизм запросов может быть общей целью, а не механизм TDB. Я не эксперт в TDB, поэтому я не могу сказать, так это или нет.

Нижняя линия

Как правило, в вашем вопросе недостаточно информации, чтобы диагностировать, есть ли реальная проблема в вашей настройке или ваш запрос просто дорогой. Было бы полезно сообщить об этом как о минимальном тестовом примере (минимальный полный код плюс примеры данных) в список [email protected] для дальнейшего анализа.

В качестве общего комментария к вашему запросу многие фильтры диапазона требуют больших затрат, что, вероятно, происходит в большинстве случаев.

person RobV    schedule 29.08.2013
comment
Спасибо Роб за ваш ответ. На движке запросов arq я так понял. Что касается моего фактического вопроса, я попробовал Algebra.optimize(op) без какого-либо эффекта, удаление stats.opt также не дало никакого эффекта. Удаление значений bnode ?квартира dssd:hasNearby ?hasNearbyStop . ?hasNearbyStop dssd:hasNearbyStop ?stop . ?квартира dssd:поблизости ?поблизостисупермаркет . ?hasNearbySupermarket dssd:hasNearbySupermarket ?супермаркет . экономит мне почти 4 секунды, так что это самая дорогая часть. Но я все еще не могу поверить, что этот запрос занимает 4 секунды в моем чрезвычайно маленьком наборе данных (который я не могу опубликовать). - person Daniel Gerber; 30.08.2013
comment
так как я работаю с Йеной, например. dbpedia (с более сложными запросами) уже давно. - person Daniel Gerber; 30.08.2013
comment
@DanielGerber Помните, что ваше представление о том, что такое сложный запрос, и ARQ не обязательно совпадают! Часто в SPARQL размер набора данных в значительной степени не имеет отношения к производительности, важен размер промежуточных результатов. Было бы интересно, если бы вы хотя бы опубликовали свой файл stats.opt, так как это даст нам некоторое представление о характеристиках вашего набора данных, не раскрывая ваши данные. - person RobV; 30.08.2013
comment
Чтобы уточнить, обычно существует корреляция между размером набора данных и размером промежуточных результатов, которые будут получены, и, следовательно, тем, сколько времени требуется для ответа на запрос. Однако относительно просто написать запрос, который работает ужасно, независимо от того, насколько мал набор данных. И наоборот, написать запрос, который всегда будет очень быстрым, независимо от размера набора данных. - person RobV; 30.08.2013
comment
Привет @RobV, не могли бы вы помочь мне уточнить: модель находится в ОЗУ или запрос выполняется через жесткий диск (если я выполняю его, как указано выше)? если hdd, можно ли его как-то загрузить в ОЗУ полностью? Вот моя статистика. Было бы полезнее исключить bnodes из запроса и использовать API модели для получения данных? Спасибо, Роб, Даниэль - person Daniel Gerber; 02.09.2013
comment
Хммм, похоже, что ваши промежуточные результаты должны быть относительно небольшими, так что проблема действительно, вероятно, в сложности всех фильтров. Вы пытались сравнить производительность между выполнением запроса без каких-либо предложений FILTER и с вашими предложениями FILTER, которые должны сказать вам, является ли фильтрация приемником производительности. - person RobV; 04.09.2013
comment
Как я уже писал ранее, фильтры не самая дорогая часть. Удаление узлов (супермаркет, парк) приводит к тому, что этот запрос выполняется за 100 мс. - person Daniel Gerber; 05.09.2013