You should check the execution plan for your query. You can see it by adding EXPLAIN clause at the beginning of the query text:
EXPLAIN SELECT
timestamp,
first(price) AS open,
last(price) AS close,
min(price),
max(price),
sum(amount) AS volume
FROM trades
WHERE symbol = 'BTC-USD' AND timestamp > dateadd('d', -1, now())
SAMPLE BY 15m ALIGN TO CALENDAR;
If you see Async ...
nodes in the output, e.g. Async JIT Group By
or Async JIT Filter
, it means that the corresponding parts of the query execution plan run in parallel, i.e. on multiple threads.
Note that by default, parallel execution is disabled on machines with less than 4 cores.
Also, in many cases, if your query runs on a single thread, you can rewrite it in a parallel-friendly way. Sometimes this can be as simple as moving the aggregates and the filter from the outer query for the sub-query.
Here is a simple example:
SELECT symbol, sum(price)
FROM (
SELECT symbol, price FROM trades
UNION ALL
SELECT symbol, price FROM trades
)
WHERE symbol = 'BTC-USD';
This query will run single-threaded since the GROUP BY and the filter is applied to a UNION ALL sub-query. But if you rewrite it in the following way, both parts of the sub-query will be handled on multiple threads:
SELECT symbol, sum(price)
FROM (
SELECT symbol, sum(price) FROM trades
WHERE symbol = 'BTC-USD'
UNION ALL
SELECT symbol, sum(price) FROM trades
WHERE symbol = 'BTC-USD'
);