Choose between dynamic tables, streams and tasks, and materialized views¶
Like streams and tasks, dynamic tables provide a way to transform data in your pipeline. This topic compares these approaches to help you choose the right one.
Dynamic tables compared to streams and tasks¶
Although dynamic tables serve a similar purpose compared to streams and tasks, there are important differences.
Comparison between streams and tasks and dynamic tables¶
| Key Characteristics | Streams and Tasks | Dynamic Tables |
|---|---|---|
| Data transformation | Tasks use an imperative approach: You write procedural code to transform data from base tables. | Dynamic tables use a declarative approach: You write a query that specifies the result you want, and data is retrieved and transformed from the base tables used in the query. Except for Supported non-deterministic functions in incremental and full refresh modes, the query can’t contain non-deterministic functions. |
| Refresh timing | You define a schedule for executing the code that transforms the data. | An automated refresh process determines the schedule for performing refreshes. The process schedules these refreshes to meet the specified target level of freshness (lag). |
| Orchestration | The procedural code can contain calls to non-deterministic code, stored procedures, and other tasks. The procedural code can contain calls to UDFs and external functions. | Although the SELECT statement for a dynamic table can contain joins, aggregations, window functions, and other SQL functions and constructions, the statement cannot contain calls to stored procedures and tasks. Currently, the SELECT statement also cannot contain calls to external functions. This limitation is due to the way in which dynamic tables are refreshed. To refresh the data, an automated process analyzes the SELECT statement for the dynamic table in order to determine the best approach to refresh the data. The automated process cannot determine this for certain types of queries. For the complete list of restrictions on the SELECT statement, see Supported queries in incremental and full refresh modes and General limitations. |
| Data freshness | Tasks can use streams to refresh data in target tables incrementally. You can schedule these tasks to run on a regular basis. | An automated refresh process performs incremental refreshes of dynamic tables on a regular basis. The process determines the schedule based on the target “freshness” of the data that you specify. |
Example: Comparison of data transformation between streams and tasks and dynamic tables¶
The example in Transform loaded JSON data on a schedule uses streams and tasks to transform and insert new data into a target
table (names) as the data is streamed into a landing table (raw).
The following examples demonstrate how to perform the same transformation using dynamic tables. When creating a dynamic table, you specify the query for the results that you want to see. For the incremental refresh of the data, you don’t need to create a stream to track changes and write a task to examine those changes and apply the changes to the target table. The automated refresh process does this for you based on the query that you specify.
| SQL Statements for Streams and Tasks | SQL Statements for Dynamic Tables |
|---|---|
Dynamic tables compared to materialized views¶
Dynamic tables have some similarities to materialized views in that both materialize the results of a query. However, there are important differences:
| Key Characteristics | Materialized Views | Dynamic Tables |
|---|---|---|
| Query performance | Materialized views are designed to improve query performance transparently. For example, if you query the base table, the query optimizer in Snowflake can rewrite the query automatically to query the materialized view instead. | Dynamic tables are designed to build multi-level data pipelines. Although dynamic tables can improve query performance, the query optimizer in Snowflake does not automatically rewrite queries to use dynamic tables. A dynamic table is used in a query only if you specify the dynamic table in the query. |
| Query complexity | A materialized view can only use a single base table. A materialized view cannot be based on a complex query (that is, a query with joins or nested views). | A dynamic table can be based on a complex query, including one with joins and unions. |
| Data freshness | Data accessed through materialized views is always current. If a DML operation changes the data in the base table, Snowflake either updates the materialized view or uses the updated data from the base table. | The data is current up to the target lag time for the dynamic table. Dynamic table maintenance and refresh is automatically managed by a separate compute service, including refresh logic, along with the compute for any updates, typically at additional cost. For more information, see Understanding costs for dynamic tables. |
When not to use dynamic tables¶
This topic describes general and cross-feature limitations on dynamic tables.
General limitations¶
The following general limitations apply to using dynamic tables:
- A single account can hold a maximum of 50,000 dynamic tables.
- You can’t truncate data from a dynamic table.
- You can’t create a temporary dynamic table.
- When you use a dynamic table to ingest shared data, the query can’t select from a shared dynamic table or a shared secure view that references an upstream dynamic table.
- You can’t use secondary roles with dynamic tables because dynamic table refreshes act as their owner role. For more information, see Authorization through primary role and secondary roles.
- You can’t use dynamic SQL (for example, session variables or unbound variables of anonymous blocks) in the dynamic table’s definition.
- In a dynamic table definition, SELECT blocks that read from user-defined table functions (UDTF) must explicitly specify columns and can’t
use
*. - Dynamic tables can become stale if they are not refreshed within the MAX_DATA_EXTENSION_TIME_IN_DAYS period of the input tables. Once stale, they must be recreated to resume refreshes.
- When creating a dynamic table that uses a warehouse named DEFAULT, you must use double quotes around the name, following the
double-quoted identifier requirements. For example,
CREATE DYNAMIC TABLE ... WAREHOUSE = "DEFAULT". For more information on creating dynamic tables, see Create dynamic tables. - Dynamic tables don’t support sources that include directory tables, external tables, streams, and materialized views.
- You can’t create dynamic tables that read from views that query other dynamic tables, unless the view is wrapped in DYNAMIC_TABLE_REFRESH_BOUNDARY().
- You can’t clone dynamic Iceberg tables. Additionally, cloning a database or schema containing a dynamic Iceberg table does not clone the table to the new location.
- You can’t set the DATA_RETENTION_TIME_IN_DAYS object parameter to zero if your base table is a shared table.
Immutability constraints¶
The following limitations apply when you work with immutability constraints and backfilled data:
- Currently, only regular and dynamic tables can be used for backfilling.
- You can’t specify policies or tags in the new dynamic table because they are copied from the backfill table.
- Clustering keys in the new dynamic table and backfill table must be the same.
Support for cross-feature interactions¶
The following cross-feature interactions are not supported:
- Using the query acceleration service (QAS) for dynamic table refreshes.
- Masking policies with database roles on shared tables.
- Aggregation and projection policies cannot be applied to the base tables of dynamic tables. If a base table has aggregation or projection policies associated with it, the dynamic table will fail to create.