Skip to content

Instantly share code, notes, and snippets.

@mro
Forked from abargnesi/loader.c
Last active October 26, 2015 11:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mro/8800fab9ef4f38a4ec4e to your computer and use it in GitHub Desktop.
Save mro/8800fab9ef4f38a4ec4e to your computer and use it in GitHub Desktop.
Load an RDF file into a SQLite database without journaling.
// see https://github.com/mro/librdf.sqlite/issues/10#issuecomment-151000843
//
// Perpare (on debian wheezy):
// $ git clone https://github.com/mro/librdf.sqlite.git
// $ cd librdf.sqlite/demo
// $ sudo apt-get install gcc librdf0-dev librdf-storage-sqlite raptor2-utils
// $ rapper --output turtle --input rdfxml http://tatort.rdf.mro.name/episodes.rdf > loader.ttl
// rapper: Parsing URI http://tatort.rdf.mro.name/episodes.rdf with parser rdfxml
// rapper: Serializing with serializer turtle
// rapper: Parsing returned 100430 triples
//
// Compile:
// $ gcc -std=c99 -I /usr/include/raptor2 -I /usr/include/rasqal -l rdf -lsqlite3 loader.c
//
// Run:
// $ echo "librdf.sqlite" ; time ./a.out "file://$(pwd)/loader.ttl" "http://purl.mro.name/rdf/sqlite/"
// real 0m9.726s
// user 0m4.564s
// sys 0m4.744s
// $ echo "stock" ; time ./a.out "file://$(pwd)/loader.ttl" "sqlite"
// real 15m2.400s
// user 14m19.086s
// sys 0m42.351s
//
// based on https://gist.github.com/abargnesi/8402baf1a019a2179e70
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <librdf.h>
#include <raptor2.h>
#include "../rdf_storage_sqlite_mro.h"
#include "../rdf_storage_sqlite_mro.c" // unorthodox but ok for now
/* function prototypes */
int main(int argc, char *argv[]);
int main(int argc, char *argv[]) {
librdf_uri* uri;
librdf_world* world;
librdf_storage* storage;
librdf_parser* parser;
librdf_stream *stream;
librdf_model* model;
char *extfind;
char *parser_name = NULL;
char *storage_name = NULL;
if (argc != 3) {
fprintf(stderr, "usage: %s <rdf content URI> <name>\n", argv[0]);
return(1);
}
// open world
world = librdf_new_world();
librdf_world_open(world);
librdf_init_storage_sqlite_mro(world); // register storage factory
// assign uri for content
uri = librdf_new_uri(world, (const unsigned char*) argv[1]);
// assign storage name
storage_name = argv[2];
if (!storage_name) {
fprintf(stderr, "storage name was not set\n");
return 1;
}
extfind = strstr(argv[1], ".ttl");
if (extfind != NULL) {
parser_name = "turtle";
} else {
extfind = strstr(argv[1], ".nt");
if (extfind != NULL) {
parser_name = "ntriples";
}
}
if (!parser_name) {
fprintf(stderr, "uri was not turtle or ntriples\n");
return 1;
}
fprintf(stdout, "%s\n", extfind);
// create storage
storage = librdf_new_storage(world, storage_name, "loader.sqlite", "new='yes',synchronous='off'");
if (!storage) {
fprintf(stderr, "could not create sqlite storage");
return(1);
}
// create model
model = librdf_new_model(world, storage, NULL);
// create parser
parser = librdf_new_parser(world, parser_name, NULL, NULL);
stream = librdf_parser_parse_as_stream(parser, uri, NULL);
// librdf_model_transaction_start(model);
librdf_model_add_statements(model, stream);
//librdf_parser_parse_into_model(parser, uri, NULL, model);
// librdf_model_transaction_commit(model);
// free up
librdf_free_parser(parser);
librdf_free_model(model);
librdf_free_uri(uri);
librdf_free_world(world);
return 0;
}
@abargnesi
Copy link

Thanks for the correction and how to quickly load http://purl.mro.name/rdf/sqlite/.

In my previous setup, I could not figure out how to compile/load your storage independently so I replaced the sqlite extension, renamed some init factory methods, and compiled librdf. My loader used the storage "sqlite" but it loaded your storage mechanism. Hacky, :(.

Now I followed your instructions above and compiled it into the loader executable. I can confirm the same results relative to the size of the triple_relations table.

Here you will see a table scan for the original triples query. When the s_uri_id NULL check is removed a table scan is not needed. In this case the query execution time goes from 25 ms to 3 ms.

[tony@starship librdf.sqlite]$ time LD_LIBRARY_PATH=/home/tony/projects/tools/redland/dist/lib/ ./loader "file://$(pwd)/loader.ttl" "http://purl.mro.name/rdf/sqlite/"
.ttl

real    0m8.078s
user    0m4.340s
sys 0m3.723s
[tony@starship librdf.sqlite]$ sqlite3 loader.sqlite 
SQLite version 3.9.1 2015-10-16 17:31:12
Enter ".help" for usage hints.
sqlite> .eqp on
sqlite> .timer on
sqlite> select id, s_uri_id, s_blank_id, p_uri_id, o_uri_id, o_blank_id, o_lit_id, o_datatype_id, c_uri_id, s_uri, s_blank, p_uri, o_uri, o_blank, o_text, o_language, o_datatype, c_uri  from triples where ((-8806721442705067278 IS NULL) OR (s_uri_id = -8806721442705067278)) AND ((NULL IS NULL) OR (s_blank_id = NULL)) AND ((NULL IS NULL) OR (p_uri_id = NULL)) AND ((NULL IS NULL) OR (o_uri_id = NULL)) AND ((NULL IS NULL) OR (o_blank_id = NULL)) AND ((NULL IS NULL) OR (o_lit_id = NULL)) AND ((NULL IS NULL) OR (c_uri_id = NULL));
--EQP-- 0,0,0,SCAN TABLE triple_relations
--EQP-- 0,1,1,SEARCH TABLE so_uris AS s_uris USING INTEGER PRIMARY KEY (rowid=?)
--EQP-- 0,2,2,SEARCH TABLE so_blanks AS s_blanks USING INTEGER PRIMARY KEY (rowid=?)
--EQP-- 0,3,3,SEARCH TABLE p_uris AS p_uris USING INTEGER PRIMARY KEY (rowid=?)
--EQP-- 0,4,4,SEARCH TABLE so_uris AS o_uris USING INTEGER PRIMARY KEY (rowid=?)
--EQP-- 0,5,5,SEARCH TABLE so_blanks AS o_blanks USING INTEGER PRIMARY KEY (rowid=?)
--EQP-- 0,6,6,SEARCH TABLE o_literals AS o_literals USING INTEGER PRIMARY KEY (rowid=?)
--EQP-- 0,7,7,SEARCH TABLE t_uris AS o_lit_uris USING INTEGER PRIMARY KEY (rowid=?)
--EQP-- 0,8,8,SEARCH TABLE c_uris AS c_uris USING INTEGER PRIMARY KEY (rowid=?)
-7837493109954258395|-8806721442705067278||-8836124518624230666||-3014258084570110441||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://data.linkedmdb.org/resource/movie/performance||r1445859834r19418r1341||||
-6521925685366287237|-8806721442705067278||4692066169238827428|||-9124593498760923704|||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://purl.org/dc/terms/rightsHolder|||DasErste.de ARD|||
-5685533122899198270|-8806721442705067278||-8836124518624230666||5460252374437114620||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://data.linkedmdb.org/resource/movie/performance||r1445859834r19418r1347||||
-4682491877376251400|-8806721442705067278||3443508343793846967|||3839403385141048354|||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://purl.org/dc/elements/1.1/publisher|||DasErste.de|||
-4601871235825437149|-8806721442705067278||-8836124518624230666||4211156641511532381||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://data.linkedmdb.org/resource/movie/performance||r1445859834r19418r1344||||
-4252611682799109763|-8806721442705067278||-6142081012002472773||1868128407261638261||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://data.linkedmdb.org/resource/movie/director||r1445859834r19418r1329||||
-995858664298034674|-8806721442705067278||-6208088443785294164||-7728777437658883136||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://data.linkedmdb.org/resource/movie/cinematographer||r1445859834r19418r1328||||
-669730749491314797|-8806721442705067278||4880245562195007077|||-173642567833879099|-581470437816614896||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://purl.org/dc/terms/date|||1976-01-18T20:15:00||http://www.w3.org/2001/XMLSchema#dateTime|
268114977419826589|-8806721442705067278||6309922206880611724|||-6190445639032481587|||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://purl.org/dc/terms/abstract|||In einer ländlichen Tankstelle wird der Besitzer das Opfer von Raubmördern. Der Heidelberger Weinhändler Jürgen Santner, zufällig Zeuge des Überfalls, gibt eine ziemlich dürftige Schilderung des Verbrechens zu Protokoll. Kommissar Lutz,...|de||
3772826497027401997|-8806721442705067278||6544627173521664659||2456378171214346576||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://data.linkedmdb.org/resource/movie/production_company||r1445859834r19418r1348||||
5553082831618227484|-8806721442705067278||-8836124518624230666||5396524174151540657||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://data.linkedmdb.org/resource/movie/performance||r1445859834r19418r1338||||
5769987248256428170|-8806721442705067278||-8836124518624230666||-8157761806553660736||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://data.linkedmdb.org/resource/movie/performance||r1445859834r19418r1335||||
5979546941103810140|-8806721442705067278||6669950022400643745||-5909669071839348802||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://data.linkedmdb.org/resource/movie/story_contributor||r1445859834r19418r1349||||
6510286954181583438|-8806721442705067278||-744601634438522114|||2270436307102992576|||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://purl.org/dc/terms/description|||In einer ländlichen Tankstelle wird der Besitzer das Opfer von Raubmördern. Der Heidelberger Weinhändler Jürgen Santner, zufällig Zeuge des Überfalls, gibt eine ziemlich dürftige Schilderung des Verbrechens zu Protokoll. Kommissar Lutz, dem der Fall übertragen wird, kann sich Santners Zurückhaltung nicht recht erklären. Seinen Verdacht, dass Santner von den Tätern erpresst wird, kann er nicht belegen. Während Lutz zunächst ergebnislos recherchiert, fasst Santner einen Plan. Er will sein Wissen gewinnbringend anlegen und macht sich ebenfalls auf die Suche nach den Tankstellenräubern. Er ahnt nicht, in welche Gefahr er sich damit begibt.

|de||
6847859526031533130|-8806721442705067278||-3360599114530608577|||-5893294698776338646|||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://purl.org/dc/terms/title|||Augenzeuge|de||
7399730096935757377|-8806721442705067278||-1824146319768708692|5819198473605095967|||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://purl.org/dc/terms/references|http://www.daserste.de/unterhaltung/krimi/tatort/fallback-image-110~_v-facebook1200_f78777.jpg|||||
7782095998802941846|-8806721442705067278||-3016059829419529009|||-9124593498760923704|||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://purl.org/dc/elements/1.1/rights|||DasErste.de ARD|||
8075035669754047617|-8806721442705067278||-8836124518624230666||-6305794634349907444||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://data.linkedmdb.org/resource/movie/performance||r1445859834r19418r1332||||
8781027361554649693|-8806721442705067278||-8800921675913015609|-7023620399157488429|||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://www.w3.org/1999/02/22-rdf-syntax-ns#type|http://purl.org/dc/dcmitype/Text|||||
Run Time: real 0.025 user 0.016667 sys 0.006667
sqlite> select id, s_uri_id, s_blank_id, p_uri_id, o_uri_id, o_blank_id, o_lit_id, o_datatype_id, c_uri_id, s_uri, s_blank, p_uri, o_uri, o_blank, o_text, o_language, o_datatype, c_uri  from triples where ((s_uri_id = -8806721442705067278)) AND ((NULL IS NULL) OR (s_blank_id = NULL)) AND ((NULL IS NULL) OR (p_uri_id = NULL)) AND ((NULL IS NULL) OR (o_uri_id = NULL)) AND ((NULL IS NULL) OR (o_blank_id = NULL)) AND ((NULL IS NULL) OR (o_lit_id = NULL)) AND ((NULL IS NULL) OR (c_uri_id = NULL));
--EQP-- 0,0,0,SEARCH TABLE triple_relations USING INDEX triple_relations_index_s_uri_id (s_uri_id=?)
--EQP-- 0,1,1,SEARCH TABLE so_uris AS s_uris USING INTEGER PRIMARY KEY (rowid=?)
--EQP-- 0,2,2,SEARCH TABLE so_blanks AS s_blanks USING INTEGER PRIMARY KEY (rowid=?)
--EQP-- 0,3,3,SEARCH TABLE p_uris AS p_uris USING INTEGER PRIMARY KEY (rowid=?)
--EQP-- 0,4,4,SEARCH TABLE so_uris AS o_uris USING INTEGER PRIMARY KEY (rowid=?)
--EQP-- 0,5,5,SEARCH TABLE so_blanks AS o_blanks USING INTEGER PRIMARY KEY (rowid=?)
--EQP-- 0,6,6,SEARCH TABLE o_literals AS o_literals USING INTEGER PRIMARY KEY (rowid=?)
--EQP-- 0,7,7,SEARCH TABLE t_uris AS o_lit_uris USING INTEGER PRIMARY KEY (rowid=?)
--EQP-- 0,8,8,SEARCH TABLE c_uris AS c_uris USING INTEGER PRIMARY KEY (rowid=?)
-7837493109954258395|-8806721442705067278||-8836124518624230666||-3014258084570110441||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://data.linkedmdb.org/resource/movie/performance||r1445859834r19418r1341||||
-6521925685366287237|-8806721442705067278||4692066169238827428|||-9124593498760923704|||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://purl.org/dc/terms/rightsHolder|||DasErste.de ARD|||
-5685533122899198270|-8806721442705067278||-8836124518624230666||5460252374437114620||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://data.linkedmdb.org/resource/movie/performance||r1445859834r19418r1347||||
-4682491877376251400|-8806721442705067278||3443508343793846967|||3839403385141048354|||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://purl.org/dc/elements/1.1/publisher|||DasErste.de|||
-4601871235825437149|-8806721442705067278||-8836124518624230666||4211156641511532381||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://data.linkedmdb.org/resource/movie/performance||r1445859834r19418r1344||||
-4252611682799109763|-8806721442705067278||-6142081012002472773||1868128407261638261||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://data.linkedmdb.org/resource/movie/director||r1445859834r19418r1329||||
-995858664298034674|-8806721442705067278||-6208088443785294164||-7728777437658883136||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://data.linkedmdb.org/resource/movie/cinematographer||r1445859834r19418r1328||||
-669730749491314797|-8806721442705067278||4880245562195007077|||-173642567833879099|-581470437816614896||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://purl.org/dc/terms/date|||1976-01-18T20:15:00||http://www.w3.org/2001/XMLSchema#dateTime|
268114977419826589|-8806721442705067278||6309922206880611724|||-6190445639032481587|||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://purl.org/dc/terms/abstract|||In einer ländlichen Tankstelle wird der Besitzer das Opfer von Raubmördern. Der Heidelberger Weinhändler Jürgen Santner, zufällig Zeuge des Überfalls, gibt eine ziemlich dürftige Schilderung des Verbrechens zu Protokoll. Kommissar Lutz,...|de||
3772826497027401997|-8806721442705067278||6544627173521664659||2456378171214346576||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://data.linkedmdb.org/resource/movie/production_company||r1445859834r19418r1348||||
5553082831618227484|-8806721442705067278||-8836124518624230666||5396524174151540657||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://data.linkedmdb.org/resource/movie/performance||r1445859834r19418r1338||||
5769987248256428170|-8806721442705067278||-8836124518624230666||-8157761806553660736||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://data.linkedmdb.org/resource/movie/performance||r1445859834r19418r1335||||
5979546941103810140|-8806721442705067278||6669950022400643745||-5909669071839348802||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://data.linkedmdb.org/resource/movie/story_contributor||r1445859834r19418r1349||||
6510286954181583438|-8806721442705067278||-744601634438522114|||2270436307102992576|||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://purl.org/dc/terms/description|||In einer ländlichen Tankstelle wird der Besitzer das Opfer von Raubmördern. Der Heidelberger Weinhändler Jürgen Santner, zufällig Zeuge des Überfalls, gibt eine ziemlich dürftige Schilderung des Verbrechens zu Protokoll. Kommissar Lutz, dem der Fall übertragen wird, kann sich Santners Zurückhaltung nicht recht erklären. Seinen Verdacht, dass Santner von den Tätern erpresst wird, kann er nicht belegen. Während Lutz zunächst ergebnislos recherchiert, fasst Santner einen Plan. Er will sein Wissen gewinnbringend anlegen und macht sich ebenfalls auf die Suche nach den Tankstellenräubern. Er ahnt nicht, in welche Gefahr er sich damit begibt.

|de||
6847859526031533130|-8806721442705067278||-3360599114530608577|||-5893294698776338646|||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://purl.org/dc/terms/title|||Augenzeuge|de||
7399730096935757377|-8806721442705067278||-1824146319768708692|5819198473605095967|||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://purl.org/dc/terms/references|http://www.daserste.de/unterhaltung/krimi/tatort/fallback-image-110~_v-facebook1200_f78777.jpg|||||
7782095998802941846|-8806721442705067278||-3016059829419529009|||-9124593498760923704|||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://purl.org/dc/elements/1.1/rights|||DasErste.de ARD|||
8075035669754047617|-8806721442705067278||-8836124518624230666||-6305794634349907444||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://data.linkedmdb.org/resource/movie/performance||r1445859834r19418r1332||||
8781027361554649693|-8806721442705067278||-8800921675913015609|-7023620399157488429|||||http://www.daserste.de/unterhaltung/krimi/tatort/sendung/augenzeuge-100.html||http://www.w3.org/1999/02/22-rdf-syntax-ns#type|http://purl.org/dc/dcmitype/Text|||||
Run Time: real 0.003 user 0.003334 sys 0.000000
sqlite> 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment