10-minute quickstart
Get started with self-hosted TimescaleDB in about 10 minutes
This guide helps you run TimescaleDB locally, create your first hypertable with the columnstore enabled, write data to the columnstore, and see instant analytical query performance.
Prerequisites for this procedure
To follow these steps, you'll need:
- Docker installed on your machine
- 8GB RAM recommended
- The
psqlclient (included with PostgreSQL) or any PostgreSQL client like pgAdmin
Step 1: Start TimescaleDB
Section titled “Step 1: Start TimescaleDB”Start TimescaleDB using one of these options.
The easiest way to get started:
This script is intended for local development and testing only. Do not use it for production deployments. For production-ready installation options, see the TimescaleDB installation guide.
On Linux or Mac:
curl -sL https://tsdb.co/start-local | shThis command:
- Downloads and starts TimescaleDB, if not already downloaded.
- Exposes PostgreSQL on port
6543, a non-standard port that avoids conflicts with other PostgreSQL instances on port 5432. - Automatically tunes settings for your environment using timescaledb-tune.
- Sets up a persistent data volume.
Run TimescaleDB directly with Docker. This option also works on Windows:
docker run -d --name timescaledb \ -p 6543:5432 \ -e POSTGRES_PASSWORD=password \ timescale/timescaledb-ha:pg18This example uses port 6543, mapped to container port 5432, to avoid conflicts if you have other PostgreSQL instances running on the standard port 5432.
Wait about 1 to 2 minutes for TimescaleDB to download and initialize.
Step 2: Connect to TimescaleDB
Section titled “Step 2: Connect to TimescaleDB”Connect using psql:
psql -h localhost -p 6543 -U postgres# When prompted, enter password: passwordYou should see the PostgreSQL prompt. Verify TimescaleDB is installed:
SELECT extname, extversion FROM pg_extension WHERE extname = 'timescaledb';Expected output:
extname | extversion-------------+------------ timescaledb | 2.x.xPrefer a GUI? If you would rather use a graphical tool instead of the command line, you can download pgAdmin and connect to TimescaleDB using the same connection details (host: localhost, port: 6543, user: postgres, password: password).
Step 3: Create your first hypertable
Section titled “Step 3: Create your first hypertable”Create a hypertable for IoT sensor data with the columnstore enabled:
-- Create a hypertable with automatic columnstoreCREATE TABLE sensor_data ( time TIMESTAMPTZ NOT NULL, sensor_id TEXT NOT NULL, temperature DOUBLE PRECISION, humidity DOUBLE PRECISION, pressure DOUBLE PRECISION) WITH ( tsdb.hypertable);tsdb.hypertable converts this into a TimescaleDB hypertable.
See more:
Step 4: Insert sample data
Section titled “Step 4: Insert sample data”Add some sample sensor readings:
-- Enable timing to see time to execute queries\timing on
-- Insert sample data for multiple sensors-- SET timescaledb.enable_direct_compress_insert = on to insert data directly to the columnstore (columnnar format for performance)SET timescaledb.enable_direct_compress_insert = on;INSERT INTO sensor_data (time, sensor_id, temperature, humidity, pressure)SELECT time, 'sensor_' || ((random() * 9)::int + 1), 20 + (random() * 15), 40 + (random() * 30), 1000 + (random() * 50)FROM generate_series( NOW() - INTERVAL '90 days', NOW(), INTERVAL '1 seconds') AS time;
-- Once data is inserted into the columnstore we optimize the order and structure-- this compacts and orders the data in the chunks for optimal query performance and compressionDO $$DECLARE ch TEXT;BEGIN FOR ch IN SELECT show_chunks('sensor_data') LOOP CALL convert_to_columnstore(ch, recompress := true); END LOOP;END $$;This generates ~7,776,001 readings across 10 sensors over the past 90 days.
Verify the data was inserted:
SELECT COUNT(*) FROM sensor_data;Step 5: Run your first analytical queries
Section titled “Step 5: Run your first analytical queries”Now run some analytical queries that showcase TimescaleDB's performance:
-- Enable query timing to see performance\timing on
-- Query 1: Average readings per sensor over the last 7 daysSELECT sensor_id, COUNT(*) as readings, ROUND(AVG(temperature)::numeric, 2) as avg_temp, ROUND(AVG(humidity)::numeric, 2) as avg_humidity, ROUND(AVG(pressure)::numeric, 2) as avg_pressureFROM sensor_dataWHERE time > NOW() - INTERVAL '7 days'GROUP BY sensor_idORDER BY sensor_id;
-- Query 2: Hourly averages using time_bucket-- Time buckets enable you to aggregate data in hypertables by time interval and calculate summary values.SELECT time_bucket('1 hour', time) AS hour, sensor_id, ROUND(AVG(temperature)::numeric, 2) as avg_temp, ROUND(AVG(humidity)::numeric, 2) as avg_humidityFROM sensor_dataWHERE time > NOW() - INTERVAL '24 hours'GROUP BY hour, sensor_idORDER BY hour DESC, sensor_idLIMIT 20;
-- Query 3: Daily statistics across all sensorsSELECT time_bucket('1 day', time) AS day, COUNT(*) as total_readings, ROUND(AVG(temperature)::numeric, 2) as avg_temp, ROUND(MIN(temperature)::numeric, 2) as min_temp, ROUND(MAX(temperature)::numeric, 2) as max_tempFROM sensor_dataGROUP BY dayORDER BY day DESCLIMIT 10;
-- Query 4: Latest reading for each sensor-- Highlights the value of Skipscan executing in under 100ms without skipscan it takes over 5secSELECT DISTINCT ON (sensor_id) sensor_id, time, ROUND(temperature::numeric, 2) as temperature, ROUND(humidity::numeric, 2) as humidity, ROUND(pressure::numeric, 2) as pressureFROM sensor_dataORDER BY sensor_id, time DESC;Notice how fast these analytical queries run, even with aggregations across millions of rows. This is the power of TimescaleDB's columnstore.
Next steps
Section titled “Next steps”Now that you have TimescaleDB running locally, explore more:
- Create continuous aggregates for faster real-time analytics.
- Connect your app to TimescaleDB.
- Try a tutorial with a real-world dataset.