Materializing dimensions and metrics in semantic views¶
To improve the query performance of a semantic view, you can materialize selected dimensions and metrics in the view, similar to how you materialize data in a materialized view.
When you query the semantic view, Snowflake reads from the materialized dimensions and metrics, rather than scanning the base table and computing the information.
Note
If MAX_STALENESS is set too low and background refreshes can’t keep up, Snowflake automatically suspends the
materialization. To recover, either increase MAX_STALENESS or optimize the materialization definition (for example,
by using only incrementally maintainable metrics or adding an IMMUTABLE WHERE condition).
Preparing a semantic view to support materialization¶
Before you can materialize the dimensions and metrics in a semantic view, you must:
- Set the MAX_STALENESS property of the semantic view.
- Verify that you are using a role that has been granted the privileges to materialize the dimensions and metrics.
Setting the maximum staleness of the materialized dimensions and metrics¶
The MAX_STALENESS property determines the maximum amount of time that the materialized dimensions and metrics can be stale (out of date) before they are refreshed. For example, if you don’t want the materialized dimensions and metrics to be out of date by more than 1 hour, set the MAX_STALENESS property to ’1 hour’.
You can set this property when running the CREATE SEMANTIC VIEW command to create a new semantic view:
You can also set this property on an existing semantic view by running ALTER SEMANTIC VIEW … SET MAX_STALENESS:
Note
The minimum allowed MAX_STALENESS is 120 seconds.
The following example creates a semantic view with a maximum staleness of 1 hour:
The MAX_STALENESS property defines the maximum acceptable staleness for materialized data. The system uses this value to determine how frequently materializations are refreshed. Queries are only rewritten to use a materialization when the materialization is not older than the value of the MAX_STALENESS property.
Note
You can’t unset MAX_STALENESS while materializations exist on the semantic view. Drop all materializations first if you need to remove the property.
Granting the privileges to materialize the dimensions and metrics¶
To materialize the dimensions and metrics in a semantic view and manage those materializations, you must use a role that has been granted the following privileges:
- the OWNERSHIP privilege on the semantic view
- the ADD SEMANTIC VIEW MATERIALIZATION privilege on the schema that contains the semantic view
To grant this privilege to a role, run the GRANT <privileges> … TO ROLE command. For more information about granting privileges, see Access control privileges.
Note
The SHOW MATERIALIZATIONS command requires only the SELECT privilege on the semantic view.
Materializing dimensions and metrics¶
To materialize dimensions and metrics in a semantic view, run ALTER SEMANTIC VIEW … ADD MATERIALIZATION:
where:
-
name: Specifies the name of the semantic view. -
materialization_name: Specifies the name of the materialization to add. -
WAREHOUSE = warehouse_name: Specifies the warehouse to use when materializing the dimensions and metrics. -
REFRESH_MODE = { AUTO | FULL | INCREMENTAL }: Specifies how the materialization is refreshed.AUTO(default): Snowflake automatically determines the best refresh strategy. For materializations that span multiple entities, AUTO typically resolves to FULL.FULL: Forces a full recomputation of the materialization on every refresh.INCREMENTAL: Forces incremental refresh, processing only the changed data. Use this to incrementalize queries that AUTO mode would otherwise process as full refreshes. Not all query shapes support incremental refresh (for example,COUNT(DISTINCT ...)doesn’t support it).
-
IMMUTABLE WHERE ( immutable_condition ): Specifies a condition that identifies rows that don’t change.You specify this to improve performance by limiting the scope of both incremental and full refreshes.
Tip
Use unqualified column names in the IMMUTABLE WHERE condition (for example,
order_daterather thanorders.order_date). The condition is evaluated on the result of the semantic view query, which uses unqualified names.Important
Snowflake strongly recommends specifying this clause to reduce the cost and time of materialization refreshes. For more information, see Improving refresh performance with IMMUTABLE WHERE.
-
DIMENSIONS dimension_name [ , ... ]: Specifies the dimensions to materialize. -
METRICS metric_name [ , ... ]: Specifies the metrics that you want to pre-aggregate. -
WHERE ( filter_condition ): Specifies a filter that limits which rows the materialization stores. This is different fromIMMUTABLE WHERE:WHEREcontrols which rows are included in the materialization and determines when queries can be rewritten to use it.IMMUTABLE WHEREis a refresh optimization hint that identifies rows that don’t need to be recomputed.Use unqualified column names (for example,
order_yearrather thanorders.order_year). The condition is evaluated on the result of the semantic view query, which uses unqualified names.For more information, see Materializing a filtered subset of data.
Note
You can’t use the following metric types in materializations:
For example:
To force incremental refresh for a multi-entity materialization:
You can add multiple materializations to a semantic view. Each materialization specifies a subset of dimensions and metrics to pre-aggregate.
You can also use this command to update the definition of an existing materialization. If you run ADD MATERIALIZATION with the same name:
- Same definition: The operation is a no-op.
- Different definition: The existing materialization is dropped and replaced with the new definition.
Snowflake automatically refreshes the materialization regularly to fulfill the desired MAX_STALENESS. If the refreshes take
too long and the materializations become more stale than the limit, they aren’t used for rewrites. In those cases, check the
refresh history and consider increasing the MAX_STALENESS on the semantic view:
How materializations are used when processing a query¶
When you query a semantic view, Snowflake uses the materializations to fulfill the query. The planner selects the lowest-cost materialization that covers the requested dimensions and metrics. The next sections explain how materializations are used when Snowflake processes a query.
- Reaggregation of additive metrics
- How dimensions in a WHERE clause are handled
- When materializations are not used
Reaggregation of additive metrics¶
When a materialization contains more dimensions than the query requests, Snowflake can reaggregate additive metrics. For
example, a materialization on (customer_name, order_year) with SUM(total_revenue) can serve a query requesting only
customer_name by summing across years.
If the metrics use the following functions, Snowflake can reaggregate the metrics:
Note
Metrics or dimensions with an expression on top of the aggregation (for example, 2 * SUM(x) + COUNT(y)) are also
considered additive and can be reaggregated.
If metrics use the following functions, Snowflake can’t reaggregate the metrics:
- COUNT(DISTINCT … )
- APPROX_COUNT_DISTINCT
- MEDIAN
- PERCENTILE_CONT and PERCENTILE_DISC
- AVG
- Any
DISTINCTaggregation - Derived metrics referencing non-additive metrics
How dimensions in a WHERE clause are handled¶
Dimensions used in a WHERE clause count as covered dimensions. For example, a materialization on
(customer_name, order_year) can be used when the following query is processed:
Expressions on dimensions in the WHERE clause (for example, MOD(orders.order_year, 2) = 0) are also supported, as long
as the underlying dimension is covered by the materialization. The same applies to expressions on top of additive metrics
and dimensions.
When materializations are not used¶
Snowflake falls back to scanning the base tables in the following situations:
- No materialization covers the requested dimensions or metrics.
- The materialization exceeds the value of the MAX_STALENESS property.
- A masking policy or row access policy exists on a column that is referenced by the materialization.
- Non-additive metrics require reaggregation.
- The materialization is in SUSPENDED state.
- The query’s WHERE clause is less restrictive than the materialization’s WHERE filter, or the query filters on a column that isn’t a materialized dimension. See Materializing a filtered subset of data.
Materializing a filtered subset of data¶
You can use a WHERE clause when adding a materialization to limit which rows are stored. This is useful for
materializing only the most recent or most frequently queried data (for example, orders from the last two years).
Snowflake rewrites a query to use this materialization when the query’s WHERE clause is compatible with the materialization’s filter:
| Query WHERE clause | Rewrite? | Reason |
|---|---|---|
WHERE order_year > 2020 | ✓ Yes | Identical to the materialization filter. |
WHERE order_year > 2022 | ✓ Yes | More restrictive than the filter, and order_year is a materialized dimension so Snowflake can apply the extra filter on top of the stored data. |
WHERE order_year > 2019 | ✗ No | Less restrictive — the materialization doesn’t contain rows from 2020 or earlier. |
WHERE order_year > 2020 AND category = 'X' | ✗ No | category is not a materialized dimension, so the extra filter can’t be applied to the stored data. |
Note
Use unqualified column names in the WHERE condition (for example, order_year rather than orders.order_year).
The condition is evaluated on the result of the semantic view query, which uses unqualified names.
Improving refresh performance with IMMUTABLE WHERE¶
If the semantic view contains non-additive metrics (for example, COUNT(DISTINCT ... )) or complex queries spanning multiple
entities, REFRESH_MODE = INCREMENTAL is not supported and Snowflake performs a full recomputation on every refresh.
You can still improve the performance of these full refreshes by specifying the IMMUTABLE WHERE clause. The IMMUTABLE WHERE clause identifies rows that don’t change, which limits the scope of the full refresh. Rows that satisfy the condition are treated as immutable, so Snowflake only recomputes the mutable portion.
For example, the following statement adds a materialization where all orders before January 1, 2020 are treated as immutable:
Updating the immutable condition¶
You can update the IMMUTABLE WHERE condition of an existing materialization without recreating it. This is useful when you need to move a watermark date forward as more data becomes historical.
To update the condition, run ADD MATERIALIZATION again with the same name and updated IMMUTABLE WHERE clause:
Note
- Enlarging the immutable region (moving the boundary forward in time) refreshes without full reinitialization.
- Shrinking the immutable region or dropping it entirely triggers a full reinitialization.
- To remove the IMMUTABLE WHERE clause entirely, re-issue the ADD MATERIALIZATION without it.
Suspending and resuming materializations¶
You can manually suspend a materialization to stop its background refreshes and prevent it from being used for query rewrites. To resume it later, use the RESUME command.
Materializations are also automatically suspended when:
- The semantic view is altered in a way that breaks the materialization definition (see Preserving materializations when altering a semantic view).
- A refresh fails or takes too long to complete within the
MAX_STALENESSwindow. Check the refresh history to investigate.
For example:
Note
Materializations are also automatically suspended when the semantic view is altered in a way that breaks the materialization definition. For more information, see Preserving materializations when altering a semantic view.
Preserving materializations when altering a semantic view¶
By default, running CREATE OR REPLACE SEMANTIC VIEW drops all existing materializations and requires you to recreate them. To preserve materializations across changes to the semantic view, use CREATE OR ALTER SEMANTIC VIEW instead.
If you manage your semantic view through the
SYSTEM$CREATE_SEMANTIC_VIEW_FROM_YAML
stored procedure, pass TRUE for the create_or_alter argument to get the same behavior.
When you use CREATE OR ALTER:
- A materialization is only suspended if a calculation, relationship, or entity that it uses (directly or indirectly) is altered
in a breaking way. For example, changing a metric’s aggregation function from
SUMtoCOUNTsuspends materializations that depend on that metric. - Adding a new calculation, relationship, or entity, or altering one that isn’t used by any materialization, doesn’t affect existing materializations.
- Non-breaking changes (such as updating comments or tags) keep materializations active.
- Suspended materializations aren’t removed. If you decide to revert to the old calculation definition, you can resume the materialization:
If the definition is no longer compatible, drop and recreate the materialization.
Refreshing a materialization manually¶
If you want to refresh the materialization of a set of dimensions and metrics, run ALTER SEMANTIC VIEW … REFRESH MATERIALIZATION:
Note
You must use a role that has been granted the privileges to materialize the dimensions and metrics.
For example, the following statement refreshes the revenue_by_customer materialization for the revenue_analysis semantic view:
When you run this command, the manual refresh uses the current warehouse of the session. Background refreshes occur automatically based on the MAX_STALENESS property using the warehouse specified when the materialization was created.
Managing materializations declaratively with YAML¶
You can manage all materializations on a semantic view declaratively using
SYSTEM$MANAGE_SEMANTIC_VIEW_MATERIALIZATIONS_FROM_YAML. This stored procedure synchronizes
the materializations on a semantic view with a YAML specification:
- Materializations in the YAML that don’t exist are created.
- Materializations that exist but have a changed definition are replaced.
- Materializations that already exist with the same definition are left unchanged (no-op).
- Materializations that exist on the semantic view but aren’t in the YAML are dropped.
The YAML specification uses the following structure:
For example:
To drop all materializations, pass an empty list:
Removing a materialization¶
To remove a materialization from a semantic view, run ALTER SEMANTIC VIEW … DROP MATERIALIZATION:
Note
You must use a role that has been granted the privileges to materialize the dimensions and metrics.
For example, the following statement removes the revenue_by_customer materialization from the revenue_analysis semantic view:
Listing the materializations for a semantic view¶
To list the materializations for a semantic view, run the SHOW MATERIALIZATIONS command:
Note
You must use a role that has been granted the SELECT privilege on the semantic view.
For example, to list the materializations for the revenue_analysis semantic view:
The command returns tabular output in the following columns:
| Column | Description |
|---|---|
name | Name of the materialization. |
state | State of the materialization. The state can be one of the following:
|
suspend_reason | Reason why the materialization is suspended. |
stale_by | Time when the materialization will be stale. |
warehouse | Warehouse that is used to materialize the dimensions and metrics. |
dimensions | Dimensions that are materialized. |
metrics | Metrics that are materialized. |
immutable_where | Condition that is used to identify immutable rows. |
refresh_mode | The resolved refresh mode for the materialization (FULL or INCREMENTAL). When REFRESH_MODE is set to AUTO, this column shows the mode that was automatically selected. |
refresh_mode_reason | Explanation of why a particular refresh mode was chosen. Populated when AUTO selects FULL due to query complexity. |
Monitoring materialization refreshes¶
You can monitor materialization refreshes using refresh history and event tables.
Viewing refresh history¶
To view the history of refreshes for a materialization, call the SEMANTIC_VIEW_MATERIALIZATION_REFRESH_HISTORY table function in the INFORMATION_SCHEMA schema:
For example, to view the history of refreshes for the revenue_by_customer materialization:
The function returns tabular output in the following columns:
| Column | Description |
|---|---|
name | Name of the materialization. |
schema_name | Name of the schema that contains the semantic view. |
database_name | Name of the database that contains the semantic view. |
state | State of the refresh. The state can be one of the following:
|
state_message | Error or status message from the refresh. |
refresh_start_time | Time when the refresh started. |
refresh_end_time | Time when the refresh completed. |
warehouse | Warehouse used for the refresh. |
refresh_action | Action taken during the refresh (for example, INITIALIZE, REINITIALIZE, REFRESH, NO_DATA). |
Setting up alerting with event tables¶
You can configure materializations to emit refresh events to an event table, allowing you to create alerts for failures or suspension.
To enable event logging for a materialization:
To disable event logging:
Materialization refresh events appear in the event table with snow.executable.type = 'SEMANTIC_VIEW_MATERIALIZATION'.
You can query the event table and set up alerts based on refresh status, similar to
dynamic table alerting.