我正在使用一个相当大的数据集(大约500Mio-Triples)存储在图形数据库免费并在我的本地开发人员机器上运行。
我想用RDF4J对数据集执行一些操作,并且必须或多或少地选择整个数据集。要进行测试,我只需选择所需的元组。代码在第一个一百万元组中运行良好,之后由于graphDB继续分配更多的RAM,速度变得非常慢。
是否有可能对非常大的数据集执行选择查询并批量获取它们?
基本上,我只想通过一些选定的三元组进行“迭代”,所以不需要使用graphDB中的那么多RAM。我可以看到,在查询完成之前,我已经准备好在RDF4J中获取数据,因为它只在大约140万个读取元组时崩溃(HeapSpaceError)。不幸的是,graphDB无法释放allready读取元组的内存。我错过什么了吗?
非常感谢你的帮助。
ps.I allready将graphDB的可用堆空间设置为20GB。
RDF4J(Java)代码如下所示:
package ch.test;
import org.eclipse.rdf4j.query.*;
import org.eclipse.rdf4j.repository.RepositoryConnection;
import org.eclipse.rdf4j.repository.http.HTTPRepository;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
public class RDF2RDF {
public static void main(String[] args) {
System.out.println("Running RDF2RDF");
HTTPRepository sourceRepo = new HTTPRepository("http://localhost:7200/repositories/datatraining");
try {
String path = new File("").getAbsolutePath();
String sparqlCommand= Files.readString(Paths.get(path + "/src/main/resources/sparql/select.sparql"), StandardCharsets.ISO_8859_1);
int chunkSize = 10000;
int positionInChunk = 0;
long loadedTuples = 0;
RepositoryConnection sourceConnection = sourceRepo.getConnection();
TupleQuery query = sourceConnection.prepareTupleQuery(sparqlCommand);
try (TupleQueryResult result = query.evaluate()) {
for (BindingSet solution:result) {
loadedTuples++;
positionInChunk++;
if (positionInChunk >= chunkSize) {
System.out.println("Got " + loadedTuples + " Tuples");
positionInChunk = 0;
}
}
}
} catch (IOException err) {
err.printStackTrace();
}
}
}
select.sparql:
PREFIX XXX_meta_schema: <http://schema.XXX.ch/meta/>
PREFIX XXX_post_schema: <http://schema.XXX.ch/post/>
PREFIX XXX_post_tech_schema: <http://schema.XXX.ch/post/tech/>
PREFIX XXX_geo_schema: <http://schema.XXX.ch/geo/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX XXX_raw_schema: <http://schema.XXX.ch/raw/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT * WHERE {
BIND(<http://data.XXX.ch/raw/Table/XXX.csv> as ?table).
?row XXX_raw_schema:isDefinedBy ?table.
?cellStreetAdress XXX_raw_schema:isDefinedBy ?row;
XXX_raw_schema:ofColumn <http://data.XXX.ch/raw/Column/Objektadresse>;
rdf:value ?valueStreetAdress.
?cellOrt mobi_raw_schema:isDefinedBy ?row;
XXX_raw_schema:ofColumn <http://XXX.mobi.ch/raw/Column/Ort>;
rdf:value ?valueOrt.
?cellPlz mobi_raw_schema:isDefinedBy ?row;
XXX_raw_schema:ofColumn <http://XXX.mobi.ch/raw/Column/PLZ>;
rdf:value ?valuePLZ.
BIND (URI(concat("http://data.XXX.ch/post/tech/Adress/", MD5(STR(?cellStreetAdress)))) as ?iri_tech_Adress).
}
我的解决方案:使用一个首先获取所有“行”的子选择状态。
PREFIX mobi_post_schema: <http://schema.mobi.ch/post/>
PREFIX mobi_post_tech_schema: <http://schema.mobi.ch/post/tech/>
PREFIX mobi_geo_schema: <http://schema.mobi.ch/geo/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX mobi_raw_schema: <http://schema.mobi.ch/raw/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT * WHERE {
{
SELECT ?row WHERE
{
BIND(<http://data.mobi.ch/raw/Table/Gebaeudeobjekte_August2020_ARA_Post.csv> as ?table).
?row mobi_raw_schema:isDefinedBy ?table.
}
}
?cellStreetAdress mobi_raw_schema:isDefinedBy ?row;
mobi_raw_schema:ofColumn <http://data.mobi.ch/raw/Column/Objektadresse>;
rdf:value ?valueStreetAdress.
?cellOrt mobi_raw_schema:isDefinedBy ?row;
mobi_raw_schema:ofColumn <http://data.mobi.ch/raw/Column/Ort>;
rdf:value ?valueOrt.
?cellPlz mobi_raw_schema:isDefinedBy ?row;
mobi_raw_schema:ofColumn <http://data.mobi.ch/raw/Column/PLZ>;
rdf:value ?valuePLZ.
BIND (URI(concat("http://data.mobi.ch/post/tech/Adress/", MD5(STR(?cellStreetAdress)))) as ?iri_tech_Adress).
}
我不知道为什么给出的查询在内存方面会如此昂贵,因为GraphDB是免费执行的,但通常很多都取决于数据集的形状和大小。当然,首先执行基本上检索整个数据库的查询并不一定是明智之举。
话虽如此,有几件事你可以试试。使用限制
和偏移
作为分页机制是一种方法。
您可以尝试的另一个选项是将查询一分为二:一个查询检索您感兴趣的所有资源标识符,然后迭代这些标识符,并为每个查询执行单独的查询,以获取该特定资源的详细信息(属性和关系)。
在您的示例中,您可以在上拆分?row
,因此首先执行查询以获取给定表的所有行:
SELECT ?row WHERE {
VALUES ?table { <http://data.XXX.ch/raw/Table/XXX.csv> }
?row XXX_raw_schema:isDefinedBy ?table.
}
然后迭代该结果,为注入每个返回的值?将
行到检索详细信息的查询中:
SELECT * WHERE {
VALUES ?row { <http://data.XXX.ch/raw/Table/XXX.csv#row1> }
?cellStreetAdress XXX_raw_schema:isDefinedBy ?row;
XXX_raw_schema:ofColumn <http://data.XXX.ch/raw/Column/Objektadresse>;
rdf:value ?valueStreetAdress.
?cellOrt mobi_raw_schema:isDefinedBy ?row;
XXX_raw_schema:ofColumn <http://XXX.mobi.ch/raw/Column/Ort>;
rdf:value ?valueOrt.
?cellPlz mobi_raw_schema:isDefinedBy ?row;
XXX_raw_schema:ofColumn <http://XXX.mobi.ch/raw/Column/PLZ>;
rdf:value ?valuePLZ.
BIND (URI(concat("http://data.XXX.ch/post/tech/Adress/", MD5(STR(?cellStreetAdress)))) as ?iri_tech_Adress).
}
在Java代码中,类似以下内容:
java prettyprint-override">
String sparqlCommand1 = // the query for all rows of the table
// query for details of each row. Value of row will be injected via the API
String sparqlCommand2 = "SELECT * WHERE { \n"
+ " ?cellStreetAdress XXX_raw_schema:isDefinedBy ?row;\n"
+ " XXX_raw_schema:ofColumn <http://data.XXX.ch/raw/Column/Objektadresse>;\n"
+ " rdf:value ?valueStreetAdress.\n"
+ " ?cellOrt mobi_raw_schema:isDefinedBy ?row;\n"
+ " XXX_raw_schema:ofColumn <http://XXX.mobi.ch/raw/Column/Ort>;\n"
+ " rdf:value ?valueOrt.\n"
+ " ?cellPlz mobi_raw_schema:isDefinedBy ?row;\n"
+ " XXX_raw_schema:ofColumn <http://XXX.mobi.ch/raw/Column/PLZ>;\n"
+ " rdf:value ?valuePLZ.\n"
+ " BIND (URI(concat(\"http://data.XXX.ch/post/tech/Adress/\", MD5(STR(?cellStreetAdress)))) as ?iri_tech_Adress).\n"
+ "}";
try(RepositoryConnection sourceConnection = sourceRepo.getConnection()) {
TupleQuery rowQuery = sourceConnection.prepareTupleQuery(sparqlCommand1);
TupleQuery detailsQuery = sourceConnection.prepareTupleQuery(sparqlCommand2);
try (TupleQueryResult result = rowQuery.evaluate()) {
for (BindingSet solution: result) {
// inject the current row identifier
detailsQuery.setBinding("row", solution.getValue("row"));
// execute the details query for the row and do something with
// the result
detailsQuery.evaluate().forEach(System.out::println);
}
}
}
当然,您正在以这种方式进行更多的查询(n1,其中N是行数),但每个单独的查询结果都只是一个小数据块,可能更易于GraphDB Free(以及您自己的应用程序)管理。
我正在尝试使用rdf4j文档构造SPARQL查询:https://rdf4j.org/documentation/tutorials/sparqlbuilder/ 我是java的新手(和stackoverflow,如果写得不好,很抱歉),但我想我已经包含了正确的开始步骤。我用以下方式实例化了一个选择查询、前缀和变量: URL已被右前缀替换 我试图编写的查询是:选择?在哪里{:team_1:draf
现在我正在用Apache Kafka做一些测试。在Kafka生产者的配置中,参数batch.size和linger.ms控制批处理策略。是否可以在生产的同时动态地制作这些参数?例如。如果数据摄取率上升很快,我们可能希望增加batch.size以每批积累更多的消息。我没有找到任何动态批处理与Kafka生产者的例子。有没有可能实施?
嗨,我是新春批。 我有如下Spring批次的情况: 我需要运行所有促销的批处理[促销列表] > 在这里,我想再次从batch中读取上面的动态查询,因为它返回的结果至少为5万条记录。 以下是我所期待的过程,这在Spring批次中是否可行? 阅读促销【读者逐一阅读促销】 创建查询并将其放在上下文中 传递给下一个读者 读取器逐个读取事务 处理交易并计算积分 我这里的问题是不能写嵌套块[一个用于读取提升,
我正在开发一个Spring Batch应用程序。我将这个应用程序作为ajar文件部署在一个生产Linux服务器上,并作为一个普通的jar应用程序运行。我的Spring Batch应用程序已经启动并运行,实际上我的updateInfoBatch-0.0.1-snapshot.jar似乎是作为进程启动并运行的: 我的应用程序包含两个使用CRON表达式在特定时间调度的作业定义: 现在,我询问是否有某种方
问题内容: 我目前正在从数据存储区中请求20个条目,使用游标将其返回给用户,以防用户要求更多条目,请将游标用作新起点,并询问下一个20个条目。 该代码看起来像 万一重要的是这里的完整代码:https : //github.com/koffeinsource/kaffeeshare/blob/master/data/appengine.go#L23 使用带有的循环看起来像是反模式,但是使用/ 时我看
例如: 用例1: 我想将上面的查询传递给一个实用工具类,该类将只使用不同的SELECT生成相同的查询,例如: 目前,我在应用程序代码中的查询构造时使用助手类来完成这一任务。我想把责任转移到一个库,这样它就可以透明地强制应用程序。 谢了。