【SQL】Oracle查询转换之物化视图查询重写

物化视图是存储在表中的查询结果

当优化器找到与物化视图关联的查询兼容的用户查询时,数据库可以根据物化视图重写查询。这种技术改进了查询执行,因为数据库已经预计算了大部分查询结果

优化器查找与用户查询兼容的物化视图,然后使用基于成本的算法选择物化视图以重写查询。除非物化视图的成本低于使用物化视图生成的计划,否则优化器不会在生成计划时重写查询。

关于查询重新和优化器

一个查询要经过多次检查,以确定它是否是查询重写的候选对象。

如果查询无法使用视图,语句消耗的时间、资源会更多

优化器使用两种不同的方法来确定何时根据物化视图重写查询。第一个方法将查询的SQL文本与物化视图定义的SQL文本相匹配。如果第一种方法失败,那么优化器将使用更通用的方法来比较查询和物化视图之间的联接、选择、数据列、分组列和聚合函数。

查询重写对以下类型的SQL语句中的查询和子查询进行操作:

  • select
  • create table … as select
  • insert into … select

它还处理集合运算符UNION、UNION ALL、INTERSECT、INTERSECT ALL、EXCEPT、EXCEPT ALL、MINUS 和MINUS ALL中的子查询,以及DML语句(如INSERT、DELETE和UPDATE)中的子查询。

维度、约束和重写完整性级别会影响是否重写查询以使用物化视图。此外,可以通过rewrite和NOREWRITE提示以及query_rewrite_enabled session参数启用或禁用查询重写。

DBMS_MVIEW.EXPLAIN_REWRITE过程建议是否可以对查询进行查询重写,如果可以,则建议使用哪些物化视图。它还解释了为什么不能重写查询。

关于查询重新相关的初始化参数

参数名 参数值 描述
OPTIMIZER_MODE ALL_ROWS (default), FIRST_ROWS, or FIRST_ROWS_n 当OPTIMIZER_MODE设置为FIRST_ROWS时,OPTIMIZER使用混合成本和启发式方法来找到快速交付前几行的最佳计划。当设置为FIRST_ROWS_n时,优化器使用基于成本的方法并以最佳响应时间为目标进行优化,以返回前n行(其中n=1、10、100、1000)。
QUERY_REWRITE_ENABLED TRUE (default), FALSE, or FORCE 此选项启用优化器的查询重写功能,使优化器能够利用物化视图来提高性能。如果设置为FALSE,此选项将禁用优化器的查询重写功能,并指示优化器即使在未编写查询的估计查询成本较低的情况下也不要使用物化视图重写查询。如果设置为强制,则此选项启用优化器的查询重写功能,并指示优化器使用物化视图重写查询,即使未编写查询的估计查询成本较低。
QUERY_REWRITE_INTEGRITY STALE_TOLERATED, TRUSTED, or ENFORCED (the default) 此参数是可选的。但是,如果已设置,则该值必须是在“初始化参数值”列中指定的值之一。默认情况下,完整性级别设置为强制。在此模式下,必须验证所有约束。因此,如果使用ENABLE NOVALIDATE RELEND,某些类型的查询重写可能无法工作。要在此环境中启用查询重写(其中约束尚未验证),应将完整性级别设置为较低的粒度级别,如受信任或可容忍的过时。

查询重新的准确性

查询重写提供三个级别的重写完整性,由初始化参数QUERY_REWRITE_INTEGRITY 来控制,有三个值

  • ENFORCED:这是默认模式。优化器仅使用物化视图中的新数据,并且仅使用基于已启用的验证主键、唯一键或外键约束的关系。
  • TRUSTED: 在可信模式下,优化器相信维度和依赖约束中声明的关系是正确的。在这种模式下,优化器还使用预构建的物化视图或基于视图的物化视图,并使用未强制的关系以及强制的关系。它还信任已声明但未启用的已验证主键或唯一键约束以及使用维度指定的数据关系。此模式提供了更强大的查询重写功能,但如果您声明的任何受信任关系不正确,也会产生错误结果的风险
  • STALE_TOLERATED:优化器使用有效但包含陈旧数据的物化视图以及包含新数据的物化视图。此模式提供了最大的重写能力,但会产生产生不准确结果的风险。

如果将“重写完整性”设置为最安全级别(强制),则优化器仅使用强制主键约束和引用完整性约束,以确保查询结果与直接访问明细表时的结果相同。

如果将“重写完整性”设置为“强制”以外的级别,则有几种情况下,使用“重写”的输出可能与不使用“重写”的输出不同:

  • 物化视图可能与数据的主副本不同步。这通常是因为在对物化视图的一个或多个细节表执行大容量加载或DML操作后,物化视图刷新过程处于挂起状态。在某些数据仓库站点上,这种情况是可取的,因为某些物化视图在特定时间间隔内刷新的情况并不少见。
  • 维度对象隐含的关系无效。例如,层次结构中某一级别的值不会向上滚动到恰好一个父值。
  • 预构建物化视图表中存储的值可能不正确。
  • 由于未强制的表或视图约束定义了错误的数据关系,因此可能会出现错误的答案。

我们可以通过system/session 级别设置参数QUERY_REWRITE_INTEGRITY

查询重写举例

创建一个物化视图

CREATE MATERIALIZED VIEW cal_month_sales_mv
ENABLE QUERY REWRITE AS
SELECT t.calendar_month_desc, SUM(s.amount_sold) AS dollars
FROM sales s, times t WHERE s.time_id = t.time_id
GROUP BY t.calendar_month_desc;

假设,在一个典型的月份,商店的销售额约为100万。因此,这个物化聚合视图具有每个月销售的美元金额的预计算聚合。

询问每个日历月在商店销售的金额的总和:

SELECT t.calendar_month_desc, SUM(s.amount_sold)
FROM sales s, times t WHERE s.time_id = t.time_id
GROUP BY t.calendar_month_desc;

在缺少以前的物化视图和查询重写功能的情况下,Oracle数据库必须直接访问sales表,并计算销售金额之和以返回结果。这涉及从sales表中读取数百万行,这将由于磁盘访问而增加查询响应时间。查询中的连接还将进一步降低查询响应的速度,因为连接需要在数百万行上计算。

在存在物化视图的情况下,查询重写将透明地将以前的查询重写为以下查询:

SELECT calendar_month, dollars
FROM cal_month_sales_mv;

因为在物化视图中只有几十行,所以查询会立即返回结果。

官网文档地址: https://docs.oracle.com/en/database/oracle/oracle-database/21/tgsql/query-transformations.html#GUID-EA178F1F-7564-4621-B884-19A202943421

请使用浏览器的分享功能分享到微信等