Primer#

This primer shows how to start quasardb, create a time-series table, insert data, run queries, and organize entries with tags.

About quasardb#

quasardb is a distributed, column-oriented database for numerical and time-series data at petabyte scale. It continuously ingests data while it serves real-time queries across live and historical datasets.

quasardb combines ingestion, compressed tiered storage, and distributed query execution in one engine. Use it when you must:

  • Sustain high ingestion rates while queries continue to run

  • Store large numerical datasets efficiently across NVMe and object storage

  • Query live and historical data through one logical database

  • Reduce the need for separate streaming, historian, warehouse, and data-lake systems

You can access the same data through SQL, client APIs, and standard interfaces. You do not need to duplicate the data between separate processing systems.

Start a local cluster#

The following commands start a quasardb server in Docker. The server listens on port 2836. It also uses port 2837 for cluster communication.

Create a Docker network:

docker network create qdb-network

Start the server:

docker run --detach \
  --name qdb-server \
  --network qdb-network \
  --publish 2836-2837:2836-2837 \
  bureau14/qdb

Confirm that the container is running:

docker ps --filter name=qdb-server

For installation options and system requirements, refer to Installation.

Start the shell#

Run the quasardb shell in a second terminal:

docker run --rm --interactive --tty \
  --network qdb-network \
  bureau14/qdbsh \
  --cluster qdb://qdb-server:2836

The shell displays this prompt:

qdbsh >

Enter each SQL statement after the prompt. End a statement with a semicolon. For more information about the shell, refer to quasardb shell.

Create a table#

Create a time-series table named stocks:

CREATE TABLE stocks (
  $timestamp TIMESTAMP,
  close DOUBLE
);

$timestamp is the time index. The close column stores 64-bit floating-point values.

Display the table schema:

SHOW TABLE stocks;

Create a table only once. To remove the table and all its data, run:

DROP TABLE stocks;

Do not run this command if you want to continue the tutorial.

Insert data#

Insert three rows:

INSERT INTO stocks ($timestamp, close) VALUES
  (2026-01-01, 1.0),
  (2026-01-02, 2.0),
  (2026-01-03, 3.0);

Each value corresponds to the column at the same position in the column list. For more information, refer to INSERT INTO … VALUES.

Query the data#

Select the rows that you inserted:

SELECT $timestamp, close
FROM stocks
IN RANGE (2026-01-01, 2026-01-04);

The range includes its start and excludes its end. The query returns these values:

$timestamp

close

2026-01-01T00:00:00.000000000Z

1.0

2026-01-02T00:00:00.000000000Z

2.0

2026-01-03T00:00:00.000000000Z

3.0

You can use a duration to specify the end of a range:

SELECT $timestamp, close
FROM stocks
IN RANGE (2026-01-01, +3days);

Filter rows with WHERE:

SELECT $timestamp, close
FROM stocks
IN RANGE (2026-01-01, +3days)
WHERE close < 2.0;

Calculate the arithmetic mean on the server. avg() is an alias for arithmetic_mean():

SELECT avg(close) AS mean_close
FROM stocks
IN RANGE (2026-01-01, +3days);

This query returns one value: 2.0.

Group values into one-day intervals:

SELECT $timestamp, avg(close) AS mean_close
FROM stocks
IN RANGE (2026-01-01, +3days)
GROUP BY 1day;

Use OVER to calculate a three-day moving average of the daily values:

SELECT
  $timestamp,
  avg(avg(close)) OVER (
    RANGE ($timestamp - 2days, $timestamp)
  ) AS moving_avg_3day
FROM stocks
IN RANGE (2026-01-01, +3days)
GROUP BY 1day;

The inner avg(close) calculates one value for each day. The outer avg calculates the mean of the current daily value and the values from the two previous days. The time-based window moves with each result row.

SELECT * also returns the virtual $timestamp and $table columns for a time-series table. Select explicit columns when you do not need $table.

For complete query syntax, refer to SELECT and the function reference.

Use the Python API#

The Python API can create tables and write NumPy arrays. The following example creates a separate table named python_stocks and inserts three rows.

Install the API and NumPy in your Python environment before you run the example.

import numpy as np
import quasardb

timestamps = np.array(
    ["2026-01-01", "2026-01-02", "2026-01-03"],
    dtype="datetime64[ns]",
)
close_values = np.array([1.0, 2.0, 3.0], dtype="float64")

with quasardb.Cluster("qdb://127.0.0.1:2836") as cluster:
    table = cluster.table("python_stocks")

    if table.exists():
        table.remove()

    table.create([
        quasardb.ColumnInfo(quasardb.ColumnType.Double, "close")
    ])

    data = quasardb.WriterData()
    data.append(table, timestamps, [close_values])

    writer = cluster.writer()
    writer.push(data, push_mode=quasardb.WriterPushMode.Fast)

The example removes python_stocks if it exists. Do not use this pattern for a production table.

The fast push mode is suitable for large batch loads. For streaming data or frequent small writes, use the asynchronous push mode. For more information, refer to Batch inserter and Python.

Organize entries with tags#

Tags let you group entries independently of their names. Attach two tags to the stocks table:

ATTACH TAGS 'nyse', 'usd' TO stocks;

List the tags:

GET TAGS FROM stocks;

Find all time-series tables that have the nyse tag:

FIND (TAG='nyse' AND TYPE=TS);

Use FIND as the source of a query:

SELECT $timestamp, $table, close
FROM FIND (TAG='nyse' AND TYPE=TS)
IN RANGE (2026-01-01, +3days);

Remove a tag:

DETACH TAGS 'usd' FROM stocks;

For more information, refer to tag commands and key/value lookups.

Connect to a production cluster#

The client uses the connection URI to contact one or more initial nodes. It then discovers the cluster topology.

Specify multiple initial nodes so that the client can connect when one node is not available:

import datetime
c = quasardb.Cluster("qdb://127.0.0.1:2836,192.168.1.2:2836,192.168.1.3:2836,192.168.1.4:2836", timeout=datetime.timedelta(minutes=1))

Production clusters can require user credentials and a cluster public key. For security configuration, refer to Security.

Stop the local cluster#

When you finish the tutorial, stop and remove the server container:

docker stop qdb-server
docker rm qdb-server
docker network rm qdb-network

Next steps#

Continue with the documentation that applies to your work: