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

# How to speed up queries

> How to speed up cube queries with the Atoti Configuration API by precomputing aggregates with global and partial aggregate providers (`IAggregateProvidersConfigurator`) and by reusing measure values with the measure cache (`IMeasureCacheConfigurator`).

By default, a cube computes the aggregates of every query at query time.
Precomputed aggregate providers store aggregates ahead of queries, so queries read them instead of computing them.
The measure cache stores computed measure values, so later queries reuse them.

## Prerequisites

Before speeding up queries, make sure:

* A cube is created (see [configure cubes](/solutions/enterprise-risk-suite/1.0/foundry/cube/overview.md))
* The cube dimensions and measures are defined (see [create dimensions and hierarchies](/solutions/enterprise-risk-suite/1.0/foundry/cube/structure.md) and [create measures](/solutions/enterprise-risk-suite/1.0/foundry/cube/measures.md))

## How to configure aggregate providers

An aggregate provider is the component from which a cube retrieves aggregated values.
Each cube has one global provider, which can serve any query.
By default, the global provider is a just-in-time provider: it computes aggregates at query time and stores nothing.
A precomputed provider stores aggregates ahead of queries, so queries read them instead of computing them.

Use a partial provider to precompute only the aggregates that queries request often.
A partial provider covers a subset of the cube hierarchies and measures.
The global provider serves any query that the partial providers cannot cover.

| Provider type | Global provider | Partial provider | Behavior |
| - | - | - | - |
| Just-in-time | `IGlobalProviderDescription.jit()` (default) | Not available | Computes aggregates at query time and stores nothing. |
| Bitmap | `IGlobalProviderDescription.bitmap()` | `IPartialProviderDescription.bitmap(name)` | Precomputes and stores aggregates. |
| Leaf | `IGlobalProviderDescription.leaf()` | `IPartialProviderDescription.leaf(name)` | Precomputes and stores aggregates. |

Configure the providers with the `IAggregateProvidersConfigurator` returned by `ICubeConfigurator.aggregateProviders()`:

* `globalProvider(IGlobalProviderDescription)` replaces the global provider. The global provider can only be set when the cube is created.
* `addPartial(IPartialProviderDescription)` adds a named partial provider.
* `removePartial(String)` removes the partial provider with the given name.

The bitmap and leaf builders accept an optional partitioning (`partitionedOn`) and optional tuning (`configuration`, which takes a `ProviderConfiguration`).
The partial provider builder also restricts the covered hierarchies, levels, and measures with `includingOnlyHierarchies`, `includingOnlyLevels`, and `includingOnlyMeasures`.
The `filteredOn` method of the partial provider builder restricts the slices of data that the provider stores.

The following example replaces the global provider with a bitmap provider.
It also adds a leaf partial provider for the `MyMeasure` measure at the `Country` level:

```java theme={"languages":{"custom":["/engine/python-sdk/6.2/languages/pycon.tmLanguage.json"]}}
IAggregateProvidersConfigurator aggregateProviders =
    cubeConfigurator.aggregateProviders();
// Replace the default just-in-time global provider
aggregateProviders.globalProvider(IGlobalProviderDescription.bitmap().build());
// Precompute the aggregates of one measure at the Country level
aggregateProviders.addPartial(
    IPartialProviderDescription.leaf("CountryProvider")
        .includingOnlyLevels(new LevelIdentifier("Geography", "Country", "Country"))
        .includingOnlyMeasures("MyMeasure")
        .build());
```

## How to configure the measure cache

The measure cache stores the values of measures so that later queries reuse them instead of computing them again.
Its size is limited: when the cache needs space for a new value, it discards the least recently used one.

The measure cache is disabled by default.
Enable it when queries request the same measure values repeatedly.

Configure the cache with the `IMeasureCacheConfigurator` returned by `IMeasuresConfigurator.measureCache()` (from `ICubeConfigurator.measures()`):

* `withSize(int)` enables the cache. The size is the number of `(location, measure)` pairs the cache can store, and must be strictly positive.
* `cachingOnlyMeasures(Set<String>)` caches only the listed measures. Without this setting, an enabled cache stores all the measures.
* `cachingOnlyBranches(Set<String>)` creates a cache only for the most recent version of the listed branches. Without this setting, an enabled cache covers all the branches.
* `sharingOnly()` stores no values, but queries running at the same time share their computations.
* `disable()` turns off both caching and the sharing of computations. This is the default setting.

The following example enables a cache of 100,000 `(location, measure)` pairs for the `MyMeasure` measure only:

```java theme={"languages":{"custom":["/engine/python-sdk/6.2/languages/pycon.tmLanguage.json"]}}
cubeConfigurator
    .measures()
    .measureCache()
    .withSize(100_000)
    .cachingOnlyMeasures(Set.of("MyMeasure"));
```

## Related pages

* [Create measures](/solutions/enterprise-risk-suite/1.0/foundry/cube/measures.md): measure definitions, aggregations, and measure factories
* [Create dimensions and hierarchies](/solutions/enterprise-risk-suite/1.0/foundry/cube/structure.md): dimension types, hierarchy definitions, and relationship types
