How it is built
Architecture overview
A knowledge graph stores facts as entities (a person, a company, a molecule, a product) joined by typed relations, so that questions about how things relate can be answered by following edges instead of reading documents. Each fact is a statement of the form subject, predicate, object, plus where it came from and when it held. The system has two halves that meet in a store. A construction pipeline turns raw sources (text, tables, other databases) into statements: find mentions, link them to known entities, extract relations, merge duplicates, check against a schema. A serving side indexes the statements so that a graph pattern (find all pairs of people who share a university and an employer) runs as joins over sorted indexes, and so that a free-text name resolves to an entity in milliseconds. The idea that makes it work is a stable identifier per entity: every source is mapped to it, every index is keyed by it, and the quality of the graph is the quality of that mapping. Hogan et al. survey the data models, schema languages, construction and quality work behind this (Hogan et al. 2021); Wikidata is the open collaborative example (Vrandečić and Krötzsch 2014), and Google introduced the term to a wide audience for search in 2012 ("things, not strings").
Parts:
- Statement store — triples with provenance, indexed in several sort orders, updated continuously —
triple-store-indexing(no page yet), B+ tree, LSM-tree,dictionary-encoding(no page yet), MVCC,radix-trie(no page yet), Swiss table, Fast hash functions - Query engine — pattern matching over the indexes —
worst-case-optimal-join(no page yet), Sort-merge join, Hash join, BFS and DFS - Text-to-mention — find and type entity mentions in text — Named entity recognition, Byte-pair encoding (BPE) tokenization, Transformer block, Text normalization, Unicode text tokenization for search, Convolutional codes and the Viterbi decoder (the Viterbi decode used for tag sequences)
- Linking — map a mention to an entity id or to NIL — Entity linking, Inverted index, BM25 ranking, Embeddings, Cross-encoder reranking, Sorted-list intersection, Delta encoding, Bit packing and PFOR, Varint (LEB128), Top-k selection, d-ary heap
- Relation extraction — turn sentences into candidate triples —
relation-extraction(no page yet), Text classification, Calibration, Linear and logistic regression - Entity resolution — merge records that describe the same thing — Entity resolution,
record-linkage(no page yet), Near-duplicate detection with MinHash LSH,fuzzy-string-matching(no page yet),edit-distance(no page yet),rolling-hash(no page yet), Union-find - Graph analytics and embeddings — importance, similarity and missing links —
pagerank(no page yet), Sparse matrices (CSR),reproducible-reduction(no page yet),knowledge-graph-embeddings(no page yet), Negative sampling, Loss functions, AdamW, Reverse-mode autodiff, L-BFGS, LU and Cholesky, SIMD programming
sources: web pages, PDFs, tables, partner DBs, human edits
│
▼
NER ──► entity linking ──► relation extraction ──► entity resolution ──► validation (schema, constraints)
(mentions) (ids, NIL) (candidate triples) (merge, canonical id) │ accept / queue for review
▲ ▲ ▼
│ alias index + vectors ┌──────────── statement store ───────────────┐
│ (inverted index, ANN) │ dictionary: term ⇄ integer id │
│ │ SPO / POS / OSP sorted indexes (LSM or B+) │
│ │ provenance, validity time, version (MVCC) │
│ └───────────────┬────────────────────────────┘
text query ─► link query ─► graph pattern (SPARQL-like) ─► join plan ─► results │
▲ analytics: PageRank, embeddings
└────────── scores written back as features
How the parts fit together
Statement store
The data model is the one in RDF 1.1: a statement is a triple of subject, predicate and object, with entities named by
IRIs (W3C RDF 1.1 Concepts). A "property graph" model with attributes on edges is the common alternative; the storage
ideas below apply to both. Real graphs use long strings for terms, so the store first maps every term to a small
integer through dictionary-encoding (no page yet) and holds triples as three integers. triple-store-indexing
(no page yet) keeps the triples in several sort orders (subject-predicate-object, predicate-object-subject,
object-subject-predicate), so any pattern with one or two bound positions is a range scan on some index; the
indexes compress well because neighbouring keys share prefixes (Delta encoding on the integer
ids, radix-trie for the dictionary side). The index structure is a choice with a known trade-off: a
B+ tree reads fast and updates in place, an LSM-tree absorbs a stream of small writes as
sequential I/O and merges in the background, which is what a graph that gets continuous edits wants.
Readers must see a consistent graph while writers edit, so MVCC keeps timestamped versions and gives every query
a snapshot. In memory, the dictionary and the caches use an open-addressing table (Swiss table) with a
fast hash. The contract with the rest: every statement has a stable id, a source, a time and
a confidence; nothing is deleted, only superseded, so history and "who said so" remain answerable.
Query engine
A graph query is a pattern: several triple patterns that share variables. Evaluating it is a join of the matching
ranges. For acyclic patterns the classic plan joins pairs of triple patterns one at a time with a
Sort-merge join over two sorted indexes (the sort orders above make the inputs already sorted) or a
Hash join on the smaller side. For cyclic patterns (a triangle of friends, a motif in a molecule), pairwise
joins can produce intermediate results far larger than the final answer. worst-case-optimal-join (no page yet; the
leapfrog triejoin of Veldhuizen) instead binds one variable at a time and intersects the sorted lists of candidates, so
its running time is bounded by the size of the largest possible answer. The graph's indexes in several sort orders are
what make that intersection cheap. Path questions ("how is A connected to B in at most four hops") are traversals
(BFS and DFS), which a query language exposes as property paths. The contract: the engine takes a pattern and a
snapshot id and streams solutions, with cost estimates coming from statistics kept per predicate. The W3C standard
language for RDF graphs is SPARQL 1.1.
Text to mention
Most knowledge enters as text. Named entity recognition finds the character spans of mentions and labels their type (person, organisation, place, gene), by tagging each token of a BPE tokenisation with a Transformer and decoding the tags into spans; older systems use a Viterbi decode over tag sequences (Convolutional codes and the Viterbi decoder shows the algorithm). Before and after, Text normalization and Unicode tokenization make "Müller", "Mueller" and "MÜLLER" meet. The contract: spans with offsets into the original text, a type, and a score; offsets matter later, for provenance.
Linking
Entity linking maps each mention to an entity id, or to NIL when the entity is not in the graph yet. It is a retrieval problem followed by a reranking problem. Candidates come from an alias table, an Inverted index over names and descriptions scored with BM25, and from a vector index of entity Embeddings (a vector database, see the vector-db system page). The posting lists are compressed (Delta encoding, Bit packing, Varint) and intersected by merging and galloping; the best few are kept with Top-k selection on a d-ary heap. A Cross-encoder then reads the mention in its context and each candidate description together and picks one; BLINK (Wu et al. 2019) is the well-known recipe: a bi-encoder for dense retrieval, a cross-encoder to rerank. The NIL decision matters: forcing a link for an unknown entity pollutes the graph with confident mistakes. Contract: a linked mention carries the entity id, a score and the alternatives considered.
Relation extraction
Given two linked mentions in a sentence, relation-extraction (no page yet) decides which predicate, if any, holds, as a
Text classification problem over the sentence with marked entities, or by letting a language model
generate triples directly (REBEL, Huguet Cabot and Navigli 2021, is an example of the generative route). The output is
a candidate, not a fact: its probability must be calibrated so thresholds mean the same thing across
relations, and a logistic combination of the extractor's score, the number of
independent sources and the source's reliability gives the confidence stored with the statement. Extraction errors are
the main source of wrong facts, so candidates go through validation before they join the graph.
Entity resolution
Two sources describe "the same" company with different names, and a text extractor invents a new id for an entity that
exists. Entity resolution fixes it: blocking cuts the n² pairs to plausible ones (by name keys,
MinHash buckets, or shared neighbours), pair scoring compares attributes
(record-linkage in the Fellegi-Sunter sense, fuzzy-string-matching with edit-distance for names, no pages yet, and
rolling-hash fingerprints for long strings), and clustering merges the matches transitively with
Union-find. Merging is the risky step: a wrong merge fuses two people into one and poisons everything
downstream. The conservative rule is to keep both ids, record a same-as link with a confidence, and merge only above a
high threshold; a human queue handles the band between. The graph's own structure helps: two companies with the same
CEO, address and founding year are more likely the same than their names alone suggest.
Graph analytics and embeddings
Two derived products come from the whole graph. pagerank (no page yet) computes an importance score for every
entity by power iteration on the link graph stored as a Sparse matrix in CSR form; it feeds ranking
in search and the choice of which entities to verify first, and reproducible-reduction (no page yet) makes the
floating-point sums order-independent so a rerun gives the same scores. knowledge-graph-embeddings (no page yet; TransE,
RotatE and relatives) learn a vector per entity and relation so that true triples score higher than corrupted ones, trained
with negative sampling, a margin or log loss and AdamW over
autodiff. Their use is link prediction: suggest missing facts (for review, not for
automatic insertion) and score extracted candidates against what the graph already implies. RotatE (Sun et al. 2019)
models each relation as a rotation in complex space, which captures symmetric, inverse and compositional patterns.
Smaller solvers such as L-BFGS and LU/Cholesky handle the convex parts (fitting calibration
and linear models), and SIMD accelerates the dot products in scoring.
Data and control flow
Ingesting one document (seconds to minutes, order of):
- Fetch and normalise the text; keep the source id and timestamp.
- NER marks mention spans and types.
- Linking retrieves candidates from the alias index and vector index, reranks with the cross-encoder, and returns an id or NIL for each mention.
- Relation extraction proposes triples between linked mentions; each has a calibrated probability and the sentence offsets as evidence.
- NIL mentions with enough context become new provisional entities; resolution checks whether they match existing ones.
- Validation applies schema constraints (types of subject and object per predicate, cardinality, value formats; W3C SHACL is the standard language for such shapes). Rejected or low-confidence triples go to a review queue.
- Accepted statements are written with provenance to the store under a new version; the indexes (and the alias and vector indexes) are updated.
Answering one graph query (milliseconds to seconds, order of):
- Free-text names in the question are linked to ids with the same linker (fast path: alias table).
- The question becomes a pattern; the planner picks index orders and a join strategy from per-predicate statistics.
- The engine opens a snapshot, runs range scans and joins (worst-case-optimal for cyclic parts), and streams solutions.
- Results are ranked (importance score, confidence, recency) and returned with the provenance of each statement.
Scaling
In the order they bite:
- Join blow-up: cyclic and highly connected patterns create huge intermediates. Levers: worst-case-optimal joins, good statistics, early filtering by type, limiting path depth.
- Store size and write rate: billions of triples, continuous edits. Levers: dictionary encoding, compressed sorted indexes, LSM-style ingestion, partitioning by predicate or by subject hash, read replicas for queries.
- Hub entities: a few nodes (a country, "human") have millions of edges and dominate cost. Levers: statistics-aware plans, special indexes for type edges, caching, per-predicate limits.
- Extraction throughput: models are the slow part of construction. Levers: batch GPU inference, cheaper models for triage, extract only from sources whose facts are missing.
- Resolution cost: pairs grow quadratically. Levers: blocking, MinHash buckets, incremental resolution of new records only.
- Quality: error rate, not speed, limits trust. Levers: constraints, multiple independent sources, sampling-based audits of each source and relation, a review queue ranked by importance score.
Failure modes
| Failure | Symptom | Cause | Fix |
|---|---|---|---|
| Wrong merge | one entity with two people's facts | resolution threshold too low, name collision | conservative merging, same-as with confidence, unmerge by provenance |
| Missed merge | duplicate entities, split facts | blocking too strict, spelling variants | multiple blocking keys, fuzzy and phonetic keys, periodic global re-resolution |
| Forced linking | unknown entity linked to a famous namesake | no NIL option, over-confident reranker | calibrate scores, NIL threshold, require context agreement |
| Hallucinated relation | plausible but false triples | generative extractor with no evidence check | require an evidence span, confidence threshold, schema validation |
| Join explosion | query times out on a cyclic pattern | pairwise join plan | worst-case-optimal join, pattern rewrite, result limits |
| Hub skew | one entity makes queries slow | millions of edges on one node | statistics-aware planner, caching, partial indexes |
| Stale facts | "current CEO" is last year's | no validity time, no re-check | valid-from/valid-to on statements, refresh jobs for volatile predicates |
| Schema drift | constraints reject good data or admit junk | schema not updated as the domain changes | versioned schema, constraint reports as a quality dashboard |
| Embedding over-trust | "predicted" facts treated as true | link prediction used as ground truth | mark as inferred, review before insert, keep out of the base graph |
| Lost provenance | cannot explain or retract a fact | statements stored without source and time | provenance required on write; retraction by source |
Real implementations
| name | what it is | repo | licence | notes |
|---|---|---|---|---|
| Apache Jena | RDF framework with a triple store (TDB) and a SPARQL server | apache/jena | Apache-2.0 | Java; reference for RDF and SPARQL behaviour |
| Oxigraph | graph database implementing SPARQL, in Rust | oxigraph/oxigraph | Apache-2.0 | small, embeddable |
| QLever | SPARQL engine for very large graphs with text search | ad-freiburg/qlever | Apache-2.0 | built for query speed on big RDF |
| Wikibase | the software behind Wikidata | wikimedia/Wikibase | — | statements with references and qualifiers |
| Blazegraph | RDF and SPARQL store, graph database | blazegraph/database | GPL-2.0 | archived on GitHub |
| BLINK | bi-encoder plus cross-encoder entity linking | facebookresearch/BLINK | MIT | archived on GitHub |
| REBEL | generative relation extraction | Babelscape/rebel | — | triples generated end to end |
| KnowledgeGraphEmbedding | reference code for RotatE and related models | DeepGraphLearning/KnowledgeGraphEmbedding | MIT | link prediction training |
The Wikidata Query Service exposes Wikibase data through a SPARQL API (MediaWiki documentation). Google's Knowledge Graph and enterprise graphs are closed; only descriptions exist.
Sources
- A. Hogan et al., Knowledge Graphs, ACM Computing Surveys, 2021. paper
- D. Vrandečić, M. Krötzsch, Wikidata: A Free Collaborative Knowledgebase, Communications of the ACM, 2014 paper.
- W3C, RDF 1.1 Concepts and Abstract Syntax. spec; SPARQL 1.1 Query Language. spec; Shapes Constraint Language (SHACL). spec
- T. L. Veldhuizen, Leapfrog Triejoin: a worst-case optimal join algorithm, 2012. paper
- L. Wu et al., Scalable Zero-shot Entity Linking with Dense Entity Retrieval, 2019 (BLINK). paper
- P.-L. Huguet Cabot, R. Navigli, REBEL: Relation Extraction By End-to-end Language generation, Findings of EMNLP 2021. paper
- Z. Sun et al., RotatE: Knowledge Graph Embedding by Relational Rotation in Complex Space, ICLR 2019. paper
- Google, Introducing the Knowledge Graph: things, not strings, 2012. blog
- MediaWiki, Wikidata Query Service. docs