文章
姚 鑫 · 四月 29 阅读大约需 10 分钟

第九章 冻结计划

第九章 冻结计划

大多数SQL语句都有一个关联的查询计划。查询计划是在准备SQL语句时创建的。默认情况下,添加索引和重新编译类等操作会清除此查询计划。下次调用查询时,将重新准备查询并创建新的查询计划。冻结计划使可以跨编译保留(冻结)现有查询计划。查询执行使用冻结的计划,而不是执行新的优化并生成新的查询计划。

对系统软件的更改也可能导致不同的查询计划。通常,这些升级会带来更好的查询性能,但软件升级可能会降低特定查询的性能。冻结计划使可以保留(冻结)查询计划,以便查询性能不会因系统软件升级而改变(降级或提高)。

如何使用冷冻计划

使用冻结计划有两种策略-乐观策略和悲观策略:
- 乐观:如果假设更改系统软件或类定义会提高性能,请使用此策略。运行查询并冻结计划。导出(备份)冻结的计划。解冻该计划。更改软件。重新运行查询。这会产生一个新的计划。比较这两个查询的性能。如果新计划没有提高性能,可以从备份文件中导入先前冻结的计划。
- 悲观:如果假设系统软件或类定义的更改可能不会提高特定查询的性能,请使用此策略。运行查询并冻结计划。更改软件。使用%NOFPLAN关键字重新运行查询(这会导致冻结的计划被忽略)。比较这两个查询的性能。如果忽略冻结的计划没有提高性能,请保持冻结该计划并从查询中删除%NOFPLAN

软件版本升级自动冻结计划

将InterSystems IRIS®Data Platform升级到新的主要版本时,现有的查询计划将自动冻结。这可确保重大软件升级永远不会降低现有查询的性能。升级软件版本后,对性能关键型查询执行以下步骤:

  1. 执行计划状态为冻结/升级的查询,并监控性能。这是在软件升级之前创建的优化查询计划。
  2. %NOFPLAN关键字添加到查询中,然后执行并监视性能。这将使用软件升级提供的SQL优化器优化查询计划。它不会解冻现有的查询计划。
  3. 比较性能指标。

- 如果%NOFPLAN性能更好,则软件升级改进了查询计划。解冻查询计划。删除%NOFPLAN关键字。
- 如果%NOFPLAN性能较差,则软件升级会使查询计划降级。保持查询计划冻结状态,将查询计划从冻结/升级升级为冻结/显式。删除%NOFPLAN关键字。
4. 测试性能关键型查询后,可以解冻所有剩余的冻结/升级计划。

当在比最初创建计划时使用的InterSystems软件版本更新的InterSystems软件版本下准备/编译查询时,会发生这种自动冻结。例如,考虑一条在系统软件版本xxxx.1下准备/编译的SQL语句。随后升级到版本xxxx.2,再次准备/编译SQL语句。系统将检测到这是SQL语句在新版本上的第一次准备/编译,并自动将计划状态标记为冻结/升级,并将现有计划用于新的准备/编译。这确保使用的查询计划不会比以前版本的查询计划差。

只有主要版本的InterSystems系统软件升级才会自动冻结现有查询计划。维护发布版本升级不会冻结现有查询计划。例如,主要版本升级(如从2018.1升级到2019.1)将执行此操作。维护版本升级(如2018.1.0到2018.1.1)不执行此操作。

在管理门户SQL界面中,SQL语句计划状态列将这些自动冻结的计划指示为冻结/升级,计划版本指示原始计划的系统间软件版本。

可以使用INFORMATION.SCHEMA.STATEMENTS Frozen=2属性列出当前命名空间中的所有冻结/升级计划。

可以使用以下$SYSTEM.SQL.Statement方法冻结单个查询计划或多个查询计划:FreezeStatement()用于单个计划;FreezeRelation()用于关系的所有计划;FreezeSchema()用于架构的所有计划;FreezeAll()用于当前命名空间中的所有计划。有相应的解冻方法。

  • 冻结方法可以提升(“冻结”)标记为冻结/升级到冻结/显式的查询计划。通常,可以使用此方法有选择地将适当的冻结/升级计划升级为冻结/显式,然后解冻所有剩余的冻结/升级计划。
  • 解冻方法可以解冻指定范围内的冻结/升级查询计划:命名空间、架构、关系(表)或单个查询。

冻结计划界面

冻结计划界面有两种,用途不同:
- Management Portal SQL语句界面,用于冻结(或解冻)单个查询的计划。
- $SYSTEM.SQL.Statement冻结和解冻方法,用于冻结或解冻命名空间、架构、表或单个查询的所有计划。

在Management Portal SQL界面中,选择Execute Query选项卡。编写查询,然后单击显示计划按钮以显示当前查询执行计划。如果计划被冻结,则查询计划部分的第一行是“冻结计划”。

在管理门户SQL界面中,选择SQL语句选项卡。这将显示SQL语句列表。此列表的计划状态列指定解冻、解冻/并行、冻结/显式或冻结/升级。(如果语句没有关联的查询计划,则计划状态列为空。)

可以使用INFORMATION.SCHEMA.STATEMENTS Frozen属性值列出当前命名空间中所有SQL语句的计划状态:UNFRECTED(0)Frozen/EXPLICIT(1)Frozen/Upgrade(2)UNFORMATED/PARALLEL(3)

要冻结或解冻计划,请在SQL语句文本列中选择SQL语句。这将显示“SQL语句详细信息”框。在此框的底部显示对帐单文本和查询计划。如果计划未冻结,则这些横断面的背景颜色为绿色,如果计划已冻结,则背景颜色为蓝色。在其正上方的对帐单操作下,可以根据需要选择冻结计划或解冻计划按钮。然后选择关闭。
- 冻结计划按钮:单击此按钮将冻结此语句的查询优化计划。冻结计划并编译该SQL语句时,SQL编译将使用冻结的计划信息并跳过查询优化阶段。
- 解冻计划按钮:点击该按钮将删除该语句冻结的计划,该语句的新编译将进入查询优化阶段,以确定要使用的最佳计划。

还可以使用$SYSTEM.SQL.Statement冻结和解冻方法冻结或解冻一个或多个计划。通过指定适当的方法,可以指定冻结或解冻操作的范围:单个计划的FreezeStatement();关系的所有计划的FreezeRelation();架构的所有计划的FreezeSchema();当前命名空间中的所有计划的FreezeAll()。有相应的解冻方法。

权限

用户只能查看他们具有EXECUTE权限的那些SQL语句。这既适用于Management Portal SQL语句列表,也适用于INFORMATION.SCHEMA.STATEMENTS类查询。

管理门户SQL语句访问要求对%Development资源具有“USE”权限。任何可以在管理门户中看到SQL语句的用户都可以冻结或解冻该语句。

对于SQL语句的目录访问,如果您具有执行该语句的权限或对%Development资源具有“Use”权限,则可以看到这些语句。

对于$SYSTEM.SQL.Statement冻结或解冻方法调用,必须对%Developer资源拥有“U”权限。

冻结计划不同

如果计划被冻结,可以确定解冻该计划是否会导致不同的计划,而无需实际解冻该计划。此信息可以帮助您确定哪些SQL语句值得使用%NOFPLAN进行测试,以确定解冻计划是否会带来更好的性能。

可以使用INFORMATION.SCHEMA.STATEMENTS FrozenDifferent属性列出当前命名空间中此类型的所有冻结计划。

冻结的计划可能会因以下任一操作而与当前计划不同:
- 重新编译该表或该表引用的表
- 使用SetMapSelecability()激活或停用索引
- 在表上运行TuneTable
- 升级InterSystems软件版本

重新编译会自动清除现有的缓存查询。对于其他操作,必须手动清除现有缓存查询才能使新查询计划生效。

这些操作可能会也可能不会产生不同的查询计划。有两种方法可以确定它们是否这样做:
- 手工检查个别冻结计划
- 每天自动扫描所有冻结计划

如果计划尚未由这两个操作中的任何一个检查,或者计划未冻结,则列出新计划的SQL语句列为空。解冻选中的冻结计划会将新建计划列重置为空。

手动冻结计划检查

在冻结计划的SQL语句详细资料页的顶部有一个检查冻结按钮。按此按钮将显示解冻不同计划复选框。如果选中此框,则解冻计划将导致不同的查询计划。

对冻结计划执行此检查冻结测试后:
- 如果选中解冻计划不同框,则列出新计划的SQL语句列包含“1”。这表明解冻计划将导致不同的计划。
- 如果未选中解冻计划不同框,则列出新计划的SQL语句列将包含“0”。这表明解冻计划不会产生不同的计划。
- 已冻结的缓存查询的New Plan为“0”;清除缓存查询,然后解冻该计划会导致SQL语句消失。
- 已冻结的Natural查询在New Plan列中为空。

执行此测试后,检查冻结按钮消失。如果要重新测试冻结的计划,请选择刷新页面按钮。这将重新显示检查冻结按钮。

日冻结计划自动检查

InterSystems SQL每晚2:00自动扫描SQL语句清单中的所有冻结语句。这次扫描最多持续一个小时。如果扫描未在一小时内完成,系统会记下它停止的位置,并从该点继续进行下一次每日扫描。可以使用管理门户监视此每日扫描或强制其立即扫描:选择系统操作、任务管理器、任务计划,然后选择扫描冻结计划任务。

此扫描检查所有冻结的计划:
- 如果冻结的计划具有与当前版本相同的InterSystems软件版本,InterSystems IRIS®Data Platform将计算两个计划的引用表和时间戳的散列,以创建可能已更改的内部计划列表。对于这个子集,它然后执行两个计划的逐个字符串比较,以确定哪些计划实际上不同。如果两个计划之间有任何不同(无论有多小),它都会在列出New Plan列的SQL语句中用“1”标记SQL语句。这表明解冻计划将导致不同的查询计划。
- 如果冻结的计划具有与当前版本相同的InterSystems IRIS版本,并且两个计划的逐字符串比较完全匹配,则它会将列出新计划的SQL语句列中的SQL语句标记为“0”。这表明解冻计划不会导致不同的查询计划。
- 如果冻结的计划具有与当前版本(冻结/更新)不同的InterSystems软件版本,InterSystems IRIS将确定对SQL优化器逻辑的更改是否会导致不同的查询计划。如果是,它将用“1”标记“SQL Statements Listing New Plan”列中的SQL语句。否则,它会用“0”标记SQL语句New Plan列。

可以通过调用INFORMATION.SCHEMA.STATEMENTS来检查此扫描的结果。以下示例返回所有冻结计划的SQL语句,指示冻结的计划是否与未冻结的计划不同。请注意,解冻语句可以是Frozen=0Frozen=3

SELECT Frozen,FrozenDifferent,Timestamp,Statement FROM INFORMATION_SCHEMA.STATEMENTS 
WHERE Frozen=1 OR Frozen=2

冻结计划出错

如果语句的计划被冻结,并且计划使用的定义发生了某些更改,从而导致计划无效,则会发生错误。例如,如果从语句PLAN使用的类中删除了索引:

  • 该声明的计划仍处于冻结状态。
  • 在“SQL语句详细信息”页上,“编译设置”区域显示“计划错误”字段。例如,如果查询计划使用索引名indxdob,然后您修改了类定义以删除索引indxdob,则会显示如下消息: Map 'indxdob' not defined in table 'Sample.Mytable', but it was specified in the frozen plan for the query.
  • 在SQL语句详细资料页上,查询计划区域显示由于冻结计划中的错误而无法确定计划。

如果在冻结计划处于错误状态时重新执行查询,则InterSystems IRIS不使用冻结计划。相反,系统会创建一个新的查询计划,该计划将在给定当前定义的情况下工作,并执行查询。此查询计划被分配了与前一个查询计划相同的缓存查询类名。

在计划解冻或修改定义以使计划返回有效状态之前,出错的计划将一直处于错误状态。

如果修改定义以使计划返回有效状态,请转到SQL语句详细资料页,然后按清除错误按钮以确定是否已更正错误。如果更正,计划错误字段将消失;否则将重新显示计划错误消息。如果已更正定义,则不必显式清除计划错误,SQL即可开始使用冻结计划。如果已更正定义,则清除错误按钮会使SQL语句详细资料页的冻结查询计划区域再次显示执行计划。

计划错误可能是 “soft error.”。当计划使用索引,但查询优化器当前无法选择该索引时,可能会出现这种情况,因为SetMapSelecability()已将其可选择性设置为0。这样做可能是为了[重建]索引。当InterSystems IRIS遇到具有冻结计划的语句的软错误时,查询处理器会尝试自动清除错误并使用冻结计划。如果该计划仍然出错,则该计划将再次标记为出错,并且查询执行将尽可能使用最佳计划。

%NOFPLAN关键字

可以使用%NOFPLAN关键字覆盖冻结的计划。包含%NOFPLAN关键字的SQL语句将生成新的查询计划。冻结的计划将保留,但不会使用。这允许测试生成的计划行为,而不会丢失冻结的计划。

DECLARE <cursor name> CURSOR FOR SELECT %NOFPLAN ...  
SELECT %NOFPLAN ....  
INSERT [OR UPDATE] %NOFPLAN ...  
DELETE %NOFPLAN ...  
UPDATE %NOFPLAN 

SELECT语句中,%NOFPLAN关键字只能在查询中的第一个SELECT之后立即使用:它只能与UNION查询的第一个分支一起使用,不能在子查询中使用。%NOFPLAN关键字必须紧跟在SELECT关键字之后,位于DISTINCTTOP等其他关键字之前。

导出和导入冻结计划

可以将SQL语句作为XML格式的文本文件导出或导入。这使可以将冻结的计划从一个位置移动到另一个位置。SQL语句导出和导入包括关联查询计划的编码版本和指示该计划是否冻结的标志。

00
1 0 0 21
Log in or sign up to continue