> ## Documentation Index
> Fetch the complete documentation index at: https://docs.chaintable.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How analytics works

> Understand how online tables synchronize to analytics storage, and how SQL execution, saved results, and data updates relate.

Analytics supports filtering, joins, and aggregation across records. Online table data first synchronizes to analytics storage. SQL then reads the analytics tables and generates a saved result for pages, charts, and dashboards. These steps happen independently, so several stages separate new data in an online table from an updated chart.

## Why use separate analytics storage

BlockDB's online access is organized around record IDs, blocks, and time. It suits continuous writes and reads of specific objects. Analytical queries often read a small number of fields across many records, such as scanning transfer amounts over a period and aggregating them by day.

Chaintable uses different storage paths for these access patterns. Online data synchronizes from BlockDB to analytics storage, where a SQL engine executes queries.

| Component                    | What it stores or processes                         | Role in analytics                                                            |
| ---------------------------- | --------------------------------------------------- | ---------------------------------------------------------------------------- |
| Analytics storage            | Analytics table data and metadata                   | Persist data for SQL queries                                                 |
| Columnar data files          | Records organized by column                         | Read only required columns and use statistics to skip irrelevant data blocks |
| Table metadata and snapshots | Table schemas and the data included in each version | Organize data into tables that can be updated and read consistently          |
| SQL engine                   | Query planning and execution                        | Read analytics tables to filter, join, and aggregate data                    |

For example, aggregating daily transfer volume requires columns such as time and amount, rather than every business field in each record. Columnar storage can reduce the data scanned. How many files or data blocks can be skipped still depends on query conditions, file layout, and statistics.

## How online data synchronizes

The synchronization service reads BlockDB table schemas and data, updates the corresponding analytics tables, and publishes a new data version when a batch completes. Current records and historical records synchronize separately. For a state table, latest supports current-value analysis, while archive supports analysis of historical changes; choosing one changes what your statistics mean.

Synchronization depends on how the data is organized:

* **Block events and state history** can synchronize by block range. The service compares BlockDB block-bundle summaries, identifies new or changed ranges, reads them again, and replaces the corresponding analytics data files. Subscriptions can also trigger synchronization for changes to recent blocks.
* **Normal Tables and state latest** may repeatedly overwrite the same record. The service performs a full read to generate a new set of files, then replaces the corresponding analytics table data.
* **Time history** must account for historical bucketing and consolidation. Depending on configuration, the service can process recent and older data separately and update the relevant time ranges.

Block-bundle summaries let the service compare data by range without rescanning the entire event table each time. Rechecking also compensates for missed change notifications. Recent-block synchronization and complete bundle checks serve different purposes; new data does not always have to wait for a full bundle to form before it can be processed.

Synchronization is asynchronous. Data volume, task queues, batch commits, and retries after failures all affect latency. SQL may not yet see a value already available through the online SDK. Tables can also advance at different rates, so check their respective coverage when joining them.

## What analytics table snapshots guarantee

A snapshot represents a published version of an analytics table. A new version becomes visible to queries only after its synchronization batch completes, preventing queries from reading a partially completed update.

This guarantees completeness of the published table version. A committed snapshot can still lag behind the online table. Separately synchronized tables do not necessarily share the same chain height or the same source-side commit. If an analysis requires block consistency, restrict the block range in SQL and confirm that all required tables have synchronized that range.

To analyze object state at a historical block, use historical versions and select each object's latest version at or before that block. Querying latest returns current state as of synchronization and cannot reconstruct past state.

## SQL execution

After you click **Run**, the system generates a result through these steps:

1. Check the account's analytics quota, save the SQL and parameters for this run, and create a query job.
2. Submit SQL to the query engine. The engine uses analytics table metadata to plan what to read, then filters, joins, and aggregates the data.
3. Collect returned rows, column names, types, and execution statistics, and save the query result.
4. Associate the job with its result files. Once the job completes, the page can read the saved result.

A job may wait, execute, succeed, or fail, subject to its deadline, query resources, and result-size limits. Filter and aggregate in SQL where possible, returning a result suitable for inspection instead of retrieving large amounts of detail and relying only on page filters.

## Saved results

A query definition stores SQL, parameters, and configuration. A query result stores data from one execution. Editing and saving SQL does not generate a new result; click **Run** again.

A query result is an independent dataset computed from analytics tables. Pagination, sorting, and keyword filtering on the result page read that execution's saved result. They do not rerun the original SQL or advance source-table synchronization. Charts and dashboards use query results; existing results do not become new statistics automatically when source tables change.

To determine whether data is up to date, check three stages separately:

| Stage                    | Question it answers                                    | How to get new data                                        |
| ------------------------ | ------------------------------------------------------ | ---------------------------------------------------------- |
| Online table             | Has the data been written to BlockDB?                  | The data-building task completes its writes                |
| Analytics table snapshot | Has new data synchronized and become available to SQL? | Wait for the corresponding synchronization batch to commit |
| Query result             | Which execution produced these statistics?             | Rerun the query after synchronization completes            |

For example, transfers written at 10:00 may not finish synchronizing until 10:02. Statistics calculated at 10:01 do not include those transfers. That saved result remains unchanged after synchronization; rerun the query so the chart can use statistics that include the new transfers.

See [SQL queries](/guides/analytics/sql-queries) for writing and running queries, and [Visualizations and dashboards](/guides/analytics/visualizations-and-dashboards) for using their results.
