In this quickstart, you create a table, build a vector index backed by the bundled granite embedding model, and run your first semantic similarity search — all in under five minutes.
Prerequisites
Before you begin, make sure you have:
- Virtuoso Open Source (single-server) built with the ONNX plugin (
--enable-onnxruntime) - The
vonnxplugin loaded in yourvirtuoso.ini(thevirtuoso.inithatmake installwrites already loads it)
If you need help building Virtuoso with ONNX support, see the SQL vector index how-to for full build instructions.
Step 1: Verify the bundled model loaded
After starting Virtuoso, confirm the embedding model is registered and its handle is non-null (a null handle means the ONNX model failed to load):
SELECT model_name, handle
FROM DB.DBA.ONNX_MODELS;You should see output similar to:
| model_name | handle |
|---|---|
| granite-384-local | 1 |
Step 2: Create a table and insert sample data
Create a table with a single-column integer primary key and a text column, then insert a few sample rows:
CREATE TABLE DB.DBA.DOCS (
id INTEGER NOT NULL PRIMARY KEY,
content LONG VARCHAR
);
INSERT INTO DB.DBA.DOCS VALUES (1, 'How do I Install Virtuoso on Linux?');
INSERT INTO DB.DBA.DOCS VALUES (2, 'How do I install virtuoso on Windows?');
INSERT INTO DB.DBA.DOCS VALUES (3, 'How do I install virtuoso on macOS?');Step 3: Create a vector index
Create the vector index, binding it to the bundled model:
CREATE VECTOR INDEX DOCS_VEC
ON DB.DBA.DOCS (content)
USING 'granite-384-local'
WITH (
dimensions = 384,
distance_metric = 'cosine'
);When this statement returns, the index is built and searchable — existing rows are backfilled inline, so there is no separate loading step.
Step 4: Search with X_SIMILAR and VECTOR_DISTANCE
Now run your first semantic search. Pass the query as plain text — the server embeds it with the index's bound model and searches the HNSW graph for the closest matches:
SELECT TOP 10 id, content,
VECTOR_DISTANCE(content, 'how to install') AS distance,
X_SIMILAR(content, 'how to install') AS score
FROM DB.DBA.DOCS
ORDER BY VECTOR_DISTANCE(content, 'how to install');Example output:
| id | content | distance | score |
|---|---|---|---|
| 1 | How do I Install Virtuoso on Linux? | 0.229 | 0.886 |
| 2 | How do I install virtuoso on Windows? | 0.250 | 0.875 |
| 3 | How do I install virtuoso on macOS? | 0.283 | 0.858 |
All three rows are semantically related to the query, so they score well above the ~0.73 that unrelated text gets with this model (see below).
What about unrelated queries?
Try a query that has nothing to do with the indexed content:
SELECT TOP 10 id, content,
VECTOR_DISTANCE(content, 'is the sun yellow') AS distance,
X_SIMILAR(content, 'is the sun yellow') AS score
FROM DB.DBA.DOCS
ORDER BY VECTOR_DISTANCE(content, 'is the sun yellow');Example output:
| id | content | distance | score |
|---|---|---|---|
| 2 | How do I install virtuoso on Windows? | 0.530 | 0.735 |
| 1 | How do I Install Virtuoso on Linux? | 0.530 | 0.735 |
| 3 | How do I install virtuoso on macOS? | 0.537 | 0.731 |
Unrelated content does not land at a cosine distance of 1.0 with this model: even text with nothing in common sits at a distance of about 0.53 — a cosine similarity of about 0.47, not 0 — which X_SIMILAR reports as a score of about 0.73. Judge relevance by the gap between related and unrelated text (here 0.86–0.89 against ~0.73) rather than against an absolute 1.0, and set a threshold from your own corpus, e.g. WHERE X_SIMILAR(content, '...') > 0.8.
Clean up
When you are done, remove the index and table:
DROP INDEX DOCS_VEC;
DROP TABLE DB.DBA.DOCS;Next steps
- SQL vector index how-to — Complete guide for creating, querying, and maintaining SQL vector indexes
- SPARQL vector index how-to — Use vector indexes with RDF data and SPARQL queries
- Vector index overview — Architecture, HNSW parameters, and embedding model options
Related content
Reference:
- granite-embedding-30m-english — The bundled embedding model
- HNSW algorithm — Background on Hierarchical Navigable Small World graphs
PreviousVector index overview for Virtuoso NextTutorial: Semantic search over OpenLink FAQs with a SPARQL vector index