在生产环境中修复Oracle查询性能的最佳方法是什么?更改应用程序代码?使用计划基线? 让我们假设在Oracle数据库上有一个C++应用程序执行一个特定的SQL查询。
在过去的几年中,在客户的环境中,这个查询在生产过程中运行良好,但突然有一天,这个查询的执行时间增加了10倍左右。(假设此查询工作的表中不断添加数据) 在进行分析时,专家们发现,Oracle的优化器没有生成最佳计划,原因可能与数据库统计数据/数据倾斜/所有其他可能影响优化器生成次优计划的参数有关 通过在查询中放置提示来强制优化器生成良好的执行计划,效果非常理想。 应用程序开发团队现在正面临压力,要求更改应用程序代码,并在构建查询时在查询中注入提示 应用程序开发团队不想更改应用程序代码,因为他们有数百名其他客户并不抱怨这种特定的查询性能。 更改应用程序代码还意味着更高的维护成本,因为他们将需要适当的机制来禁用提示。当客户将数据库升级到较新版本时,不再需要提示 有问题的客户不愿意雇佣DBA,DBA可以执行SQL命令,使用计划基线功能优化查询在生产环境中修复Oracle查询性能的最佳方法是什么?更改应用程序代码?使用计划基线? 让我们假设在Oracle数据库上有一个C++应用程序执行一个特定的SQL查询。,oracle,code-maintainability,optimizer-hints,Oracle,Code Maintainability,Optimizer Hints,在过去的几年中,在客户的环境中,这个查询在生产过程中运行良好,但突然有一天,这个查询的执行时间增加了10倍左右。(假设此查询工作的表中不断添加数据) 在进行分析时,专家们发现,Oracle的优化器没有生成最佳计划,原因可能与数据库统计数据/数据倾斜/所有其他可能影响优化器生成次优计划的参数有关 通过在查询中放置提示来强制优化器生成良好的执行计划,效果非常理想。 应用程序开发团队现在正面临压力,要求更改应用程序代码,并在构建查询时在查询中注入提示 应用程序开发团队不想更改应用程序代码,因为他们有数
在这种情况下,应用程序开发团队有哪些选项?创建一个手动SQL配置文件,在不更改应用程序SQL的情况下注入提示。虽然这仍然是一个“DBA”任务,但它只需要运行一个命令,并且比SQL计划基线简单得多 使用下面的PL/SQL块。替换SQL_ID、名称、说明和提示列表,然后向客户发送完整命令
--Large SQL statements are better loaded from SQL_ID.
declare
v_sql_id constant varchar2(128) := '2z0udr4rc402m'; --CHANGE ME
v_sql clob;
begin
--Find the SQL, it should be in one of these.
begin
select sql_fulltext into v_sql from gv$sql where sql_id = v_sql_id and rownum = 1;
exception when no_data_found then null;
end;
if v_sql is null then
begin
select sql_text into v_sql from dba_hist_sqltext where sql_id = v_sql_id and rownum = 1;
exception when no_data_found then
raise_application_error(-20000, 'Could not find this SQL_ID in GV$SQL or DBA_HIST_SQLTEXT.');
end;
end if;
--Create profile.
dbms_sqltune.import_sql_profile
(
sql_text => v_sql,
name => 'Some_Meaningful_Name', --CHANGE ME
description => 'Add useful description here.', --CHANGE ME
force_match => true,
profile => sqlprof_attr('full(a)', 'parallel(8)') --CHANGE ME
);
end;
/
“最佳”解决方案是深入了解客户的系统,找出他们与其他人不同的原因。他们是否有一些奇怪的优化器参数,他们是否禁用了stats作业,等等。但是如果这是客户唯一的问题,那么我会使用SQL配置文件并将其称为“完成”。创建一个手动SQL配置文件,以在不更改应用程序SQL的情况下注入提示。虽然这仍然是一个“DBA”任务,但它只需要运行一个命令,并且比SQL计划基线简单得多 使用下面的PL/SQL块。替换SQL_ID、名称、说明和提示列表,然后向客户发送完整命令
--Large SQL statements are better loaded from SQL_ID.
declare
v_sql_id constant varchar2(128) := '2z0udr4rc402m'; --CHANGE ME
v_sql clob;
begin
--Find the SQL, it should be in one of these.
begin
select sql_fulltext into v_sql from gv$sql where sql_id = v_sql_id and rownum = 1;
exception when no_data_found then null;
end;
if v_sql is null then
begin
select sql_text into v_sql from dba_hist_sqltext where sql_id = v_sql_id and rownum = 1;
exception when no_data_found then
raise_application_error(-20000, 'Could not find this SQL_ID in GV$SQL or DBA_HIST_SQLTEXT.');
end;
end if;
--Create profile.
dbms_sqltune.import_sql_profile
(
sql_text => v_sql,
name => 'Some_Meaningful_Name', --CHANGE ME
description => 'Add useful description here.', --CHANGE ME
force_match => true,
profile => sqlprof_attr('full(a)', 'parallel(8)') --CHANGE ME
);
end;
/
“最佳”解决方案是深入了解客户的系统,找出他们与其他人不同的原因。他们是否有一些奇怪的优化器参数,他们是否禁用了stats作业,等等。但是如果这是客户唯一的问题,那么我只需要使用SQL概要文件,并将其称为“完成”。如果我是你,我会在应用程序代码的查询中添加一个使用提示的条件,该条件可以是db版本或规则。这并非闻所未闻。Ofc,我假设RCA在这里是不存在问题的。您的4位数Oracle版本是什么?您使用的是企业版吗?您是否拥有Tuning Pack和/或Diagnostic Pack许可证?如果我是您,我会在应用程序代码的查询中添加一个使用提示的条件,该条件可以是db版本或规则。这并非闻所未闻。Ofc,我假设RCA在这里是不存在问题的。您的4位数Oracle版本是什么?您使用的是企业版吗?您是否有调谐包和/或诊断包许可证?