# bitemporal data and questdb performance

**URL:** <https://community.questdb.com/t/bitemporal-data-and-questdb-performance/956>\
**Category:** Community\
**Created:** [February 12, 2026, 9:27am UTC](https://community.questdb.com/t/bitemporal-data-and-questdb-performance/956 "2026-02-12T09:27:00Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![nick](https://avatars.discourse-cdn.com/v4/letter/n/f9ae1b/32.png) [@nick](https://community.questdb.com/u/nick)\
**Post date:** [February 12, 2026, 9:27am UTC](https://community.questdb.com/t/bitemporal-data-and-questdb-performance/956/1 "2026-02-12T09:27:00Z")

</div>

If I want to support bitemporal data with rare corrections, is the right thing to do to have a table designed like this:

`CREATE TABLE events ( event_id SYMBOL, event_time TIMESTAMP, -- designated timestamp record_time TIMESTAMP, -- when we learned about it -- other data columns value DOUBLE, -- ... ) TIMESTAMP(event_time) PARTITION BY DAY;`

and then query it like this:

`-- Get the most recent version of each event as of now SELECT * FROM events LATEST ON event_time PARTITION BY event_id;`

Is this the right approach? Is it going to use indexes / avoid scans or be slow? What if I then put a materialized view over further aggregations of the query that involves this latest clause - will it still incrementally update the view efficiently?

---

<div class="post-metadata">

**Author:** ![nwoolmer](https://yyz2.discourse-cdn.com/flex004/user_avatar/community.questdb.com/nwoolmer/32/24_2.png) [@nwoolmer](https://community.questdb.com/u/nwoolmer)\
**Post date:** [February 17, 2026, 10:55am UTC](https://community.questdb.com/t/bitemporal-data-and-questdb-performance/956/2 "2026-02-17T10:55:57Z")

</div>

Hi @nick ,

It depends. It’s best to avoid `UPDATE` where possible, as this has impact on any materialized views that depend on the table. But, if you aren’t relying on materialized views, and updates are rare, then it may be best to just use that.

`LATEST ON` is a good solution if the dataset is not significantly skewed. However, with a skewed dataset, the query can become slower over time as it has to scan more and more historical data to find the infrequently updated symbol.

There is also the option of a caching daily `last` values using a materialized view: [Materialized views | QuestDB](https://questdb.com/docs/concepts/materialized-views/#advanced-latest-on-optimization)

This is not a good fit if you have very high cardinality `event_id`, and where most of them only have a handful of rows. It is more for the case where you have an `event_type` and you want the latest row for each type, where cardinality is bounded.

In summary, I think `LATEST ON` is the way to go, so long as you bound you the query to ensure it does not scan too much historical data. Adding an index can speed this up, but will consume additional storage space, and should not be used for infinite cardinality fields like an auto-generated id.

We are adding some optimisations for this kind of thing in the near future, which will specifically help for cases where the query is not time-bounded and the filtering key is high cardinality.
