--- title: "Materialized view" sidebarTitle: "Materialized View" description: "Create, open, list and drop a table whose contents are defined by a query." icon: table keywords: ["materialized view", "create_materialized_view", "catalog", "ddl"] availability: oss: available enterprise: varies summary: >- Materialized views are created and managed in the embedded library. On a deployment they are off by default and have to be enabled, and the SDK creates them through the deployment's SQL endpoint; see [Against a deployment](#deployment). --- A materialized view is a table whose contents are defined by a query over another table. The query is recorded in the view's schema, and a refresh brings its stored rows up to date with the source. The result is an ordinary table -- queryable, indexable, searchable, and present in `table_names()`. Nothing about reading it is special. This page covers creating and managing one. Keeping it current is [Refresh a materialized view](/feature-engineering/materialized-views). In SQL, see [`REFRESH MATERIALIZED VIEW`](/sql/dml/refresh#refresh-materialized-view) and [`SHOW MATERIALIZED VIEWS`](/sql/ddl/materialized-view#show). ## Creating one {#create} ```python Python icon="python" view = db.create_materialized_view( "recent_docs", source="documents", select=["id", "title", "embedding"], where="created_at > '2026-01-01'", ) ``` ```typescript TypeScript icon="square-js" const view = await db.createMaterializedView("recent_docs", "documents", { select: ["id", "title", "embedding"], where: "created_at > '2026-01-01'", }); ``` `source` names the table it derives from. A local source does not need stable row ids or any other storage option; an earlier deployment version may require stable row ids (see [Against a deployment](#deployment)). `select`, `where` and `limit` record the query -- there is no separate definition step. ## Opening, listing and dropping {#manage} | | Python | TypeScript | SQL | | --- | --- | --- | --- | | create | `create_materialized_view` | `createMaterializedView` | `CREATE MATERIALIZED VIEW` | | open | `open_materialized_view` | `openMaterializedView` | -- | | list | `list_materialized_views` | `listMaterializedViews` | `SHOW MATERIALIZED VIEWS` | | refresh | `refresh` | `refresh` | `REFRESH MATERIALIZED VIEW` | | drop | `drop_table` | `dropTable` | `DROP TABLE` | `list_materialized_views` finds views by reading every table's schema, so it costs one open per table. `SHOW MATERIALIZED VIEWS` asks the server instead and is cheaper on a catalog with many tables. A view is dropped with `drop_table`, because a materialized view **is** a table. That also means dropping one removes stored rows -- unlike dropping a [view](/management/view), which removes only a saved query. ## Working with the view {#working} `view.table` is the underlying table, for querying, indexing, or search. `view.definition` is the recorded query -- select list, predicate, limit -- which is how you check what a view contains without inferring it from the rows. Both are properties; on an async view, the definition is read with `await view.definition()`. ## Against a deployment {#deployment} Enterprise `create_materialized_view` works on a `db://` connection as well as a local one. There the SDK creates and refreshes the view through SQL, and the work runs on the cluster rather than in your process, so the deployment's [SQL endpoint](/basics/sql#sql-is-remote) has to be reachable. Materialized views are off by default on a deployment and have to be enabled there, and an earlier deployment version may require a view's source to have stable row ids; see [Against a deployment](/feature-engineering/materialized-views#availability). ## What to read next {#next} How a refresh works, and what it writes. The non-materialized counterpart, defined in SQL.