7 x 24 在线支持!
PeopleSoft Enterprise 在 Oracle数据库11g上的优化
PeopleSoft Enterprise 在 Oracle数据库11g上的优化
如果自己搞不定可以找诗檀软件专业ORACLE 优化团队成员帮您调优!
诗檀软件专业数据库优化团队
服务热线 : 13764045638 QQ号:47079569 邮箱:service@parnassusdata.com
该红皮书为在Oracle数据库环境中实现PeopleSoft的最佳性能提供了指导。
请记住,PeopleSoft根据需要更新此文档,以反映我们从该领域获得的最新反馈。 因此,本文档的结构,标题,内容和长度可能随每个发布版本而变化。 要查看自上次下载文件以来文档是否已更新,请将版本的日期与发布的版本的日期进行比较。
相关材料
本文档不是环境调整的一般介绍,我们假设我们的读者是有经验的IT专业人士,对PeopleSoft Internet Architecture和Oracle数据库有很好的了解。 为了充分利用本文档所涵盖的信息,我们建议您对系统管理,基础Internet架构,关系数据库概念和SQL以及如何使用PeopleSoft应用程序有基本了解。
本文档不是用于替换PeopleTools 8,8.4x或8.5x PeopleBooks提供的文档。 我们建议您在阅读本文档之前,先阅读PeopleBooks中的PeopleSoft应用程序相关信息,以确保您对PeopleSoft批处理技术有全面了解。
您可以在PeopleSoft安装指南PeopleBook的“Oracle调整”一章中找到许多与性能调优相关的基本概念。另外,我们建议您阅读Oracle 11g数据库管理和性能调优指南。
当使用Oracle的基于成本优化器(CBO)时,查询性能在很大程度上取决于适当的表和索引统计。 这些统计信息的维护对于优化数据库和查询性能至关重要。
自动维护任务管理
Oracle 11g引入了一项新功能,即自动维护任务管理,用于收集表,表空间和SQL的不同类型的统计信息。 此Oracle Autotask由三个预定义的自动维护任务组成:
1.自动优化器统计信息收集,它收集数据库中没有统计信息或仅存在过时统计信息的所有模式对象的优化器统计信息。
2.自动空间顾问,用于识别具有可用于回收的空间的段,并建议如何对这些段进行碎片整理。
3. SQL调优顾问,它会检查高负载SQL语句的性能,并建议如何调整这些语句。
它在预定的维护窗口运行,这是预期的在系统负载低的期间发生的时间间隔。 Oracle 11g具有七个预定义的维护窗口,具有不同的开始和结束时间:
• Monday - Friday from 10:00PM to 02:00AM
• Saturday - Sunday from 06:00AM to 02:00AM the next day
您可以使用DBMS_SCHEDULER.SET_ATTRIBUTE过程将预定义的维护窗口调整到与数据库环境相适应的时间。 您可以根据数据库的资源使用模式自定义维护窗口,或禁用某些默认窗口运行。 您可以使用DBA_AUTOTASK_WINDOW_CLIENTS视图检查为每个窗口启用的窗口和任务。 您还可以使用DBMS_SCHEDULER.CREATE_WINDOW过程创建自己的维护窗口.
要启用或禁用所有窗口的所有自动维护任务,请执行以下操作:
要禁用特定的维护任务,请执行以下操作:
要启用自动优化器统计信息收集,请执行以下操作:
要禁用自动空间顾问,请执行以下操作:
client_name的有效值(如DBA_AUTOTASK_CLIENT View中所示)为:
•自动优化器统计信息收集
•汽车空间顾问
•sql调优顾问
操作的有效值(在DBA_AUTOTASK_OPERATION View中指定)为:
•自动优化器统计工作
•自动空间顾问工作
•自动sql调优任务
窗口名称的有效值在DBA_AUTOTASK_WINDOW_CLIENTS视图中定义.
自动优化器统计信息集合调用DBMS_STATS.GATHER_DATABASE_STATS_JOB_PROC过程来更新统计信息。此内部过程与使用GATHER AUTO选项的DBMS_STATS.GATHER_DATABASE_STATS过程类似。主要区别在于,GATHER_DATABASE_STATS_JOB_PROC对需要统计信息的数据库对象进行优先级排序,以便在维护窗口关闭之前首先处理最需要更新的统计信息的对象。为了确定表统计信息何时变得过时,Oracle会自上次统计信息运行后检查DBA_TAB_MODIFICATIONS视图,这些表已被修改了10%以上。要启用此修改监视功能,数据库参数STATISTICS_LEVEL必须设置为ALL或TYPICAL。对表的所有DML更改(如“插入”,“更新”,“删除”或“截断”)都将被跟踪并存储在DBA_TAB_MODIFICATIONS中。监控信息记录在SGA中,并定时刷新到磁盘。您也可以通过调用DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO过程来刷新此数据。当指定GATHER AUTO时,Oracle将忽略所有首选项,并隐式确定哪些对象需要新的统计信息以及如何收集这些统计信息(有关更多信息,请参阅错误13791469).
有关Oracle 11g中的统计数据集的更多信息,请单击以下链接:
注意:237901.1自动收集模式或数据库统计信息
注意:756734.1 Oracle 11g:计划程序维护任务或自动任务(Doc ID 756734.1)
注意:465787.1升级到10g或11g期间如何管理CBO统计信息
注意:470316.1使用实际系统统计信息(已收集的CPU和IO信息)
手动生成表统计数据
DBMS_STATS包提供了手动生成统计信息的功能。 它已经扩展到适应新型的统计和监测数据。 要为DBMS_STATS.GATHER_ * _ STATS 使用的所有参数设置默认值,请使用 DBMS_STATS.SET _ * _ PREFS过程.
•SET_TABLE_PREFS使您能够为指定表的DBMS_STATS.GATHER _ * _ STATS过程使用的参数设置默认值。
•SET_SCHEMA_PREFS允许您为指定模式中所有对象的DBMS_STATS.GATHER _ * _ STATS过程使用的参数设置默认值。 它使用SET_TABLE_PREFS为指定模式中的所有表设置默认值。 添加的新对象将使用SET_GLOBAL_PREFS设置的默认值。
•SET_DATABASE_PREFS使您能够为指定数据库中所有user_defined和system_defined模式中所有对象的DBMS_STATS.GATHER _ * _ STATS过程使用的参数设置默认值。 它使用SET_TABLE_PREFS为指定数据库中的所有表设置默认值。 添加的新对象将使用SET_GLOBAL_PREFS设置的默认值。
•SET_GLOBAL_PREFS使您能够为数据库中没有设置表首选项的任何对象为DBMS_STATS.GATHER _ * _ STATS过程使用的参数设置默认值。
您可以为以下参数设置首选项:
DBMS_STATS.GATHER _ * _ STATS对首选项参数使用以下层次结构,但在命令中显式设置的参数值覆盖所有内容。 当Oracle检查首选项时,首先使用表首选项,然后使用模式首选项,数据库首选项以及最终的全局首选项。
如果未设置参数,并且如果不存在表首选项,则使用GLOBAL首选项。 要检查为DBMS_STATS设置的所有默认值,请使用此SQL:
设置所有首选项后,可以使用以下命令收集统计信息:
要获取使用选项LIST STALE收集自动统计信息定位的对象列表,请使用以下过程:
您应该在GLOBAL级别设置以下内容:
1. 要让Oracle确定样本大小,请设置以下参数:
ESTIMATE_PERCENT => DBMS_STATS.AUTO_SAMPLE_SIZE
Example
速度为10%的样品:
Run Num AUTO_SAMPLE_SIZE 10% SAMPLE 100% SAMPLE
1 00:02:21.86 00:02:31.56 00:08:24.10
2 00:02:38.11 00:02:49.49 00:07:38.25
3 00:02:39.31 00:02:38.55 00:07:37.83
100%样品的精度:
C1 59852 31464 60351
C2 1270912 608544 1289760
1. 1.要收集PeopleSoft表的直方图统计信息,请设置以下参数:
METHOD_OPT => ’FOR ALL INDEXED COLUMNS SIZE 1’
2. 然后,选择性地启用某些表的直方图,例如:
EXECUTE DBMS_STATS. SET_TABLE_PREFS ('PSFT', 'PS_JRNL_LN',METHOD_OPT’,’FOR COLUMNS SIZE 10 PROCESS_INSTANCE');
3. 在设置所有首选项后,使用此命令更新PSFT模式的统计信息:
EXECUTE DBMS_STATS.GATHER_SCHEMA_STATS( OWNNAME => 'PSFT'
,DEGREE => 8);
当前统计资料生成
Oracle Database 11g第2版(11.2.0.2)引入了一种新的统计信息收集模式,并发统计信息收集,可以减少收集统计信息所需的时间。 这种新模式的目标是使统计信息能够同时在一个表中的模式或数据库以及多个(子)分区中的多个表上进行收集。 通过允许Oracle完全使用多处理器环境,可以并发收集多个表上的统计信息可以减少统计信息所需的总时间。 传统上,并行性是通过提交多个dbms_stats作业并发执行的,每个dbms_stats作业包含degree参数,使Oracle可以在作业中的每个表上调用并行查询。 有了这个新功能,DBA只需要提交一个工作。 Oracle11gr2使用dbms_scheduler机制提交并行作业来执行统计信息收集.
并发统计收集由DBMS_STATS包中的全局参数CONCURRENT控制。 CONCURRENT参数是布尔值,因此可以设置为TRUE或FALSE。 默认情况下,它设置为FALSE。 要启用它,请执行以下操作:
当CONCURRENT设置为TRUE时,Oracle使用Oracle Job Scheduler和Advanced Queuing组件来同时创建和管理多个统计信息收集作业.
并发统计信息收集作业的最大数量受以下数据库参数限制:
您可以使用此SQL查询并发统计信息收集作业的状态:
系统统计生成
您可以收集诸如I / O和CPU性能和利用率的系统统计信息,以便优化器根据工作负载和硬件性能和利用率来考虑系统硬件特性并相应调整访问路径的成本。 当Oracle收集系统统计信息时,它将在指定的时间段内分析系统活动(工作负载统计信息)。 使用DBMS_STATS.GATHER_SYSTEM_STATS过程收集统计信息,并存储在SYS.AUX_STATS中。
要收集工作负载统计信息,请执行以下任一操作:
• 在工作负载窗口的开头运行DBMS_STATS.GATHER_SYSTEM_STATS(启动)过程,然后在工作负载窗口的末尾运行DBMS_STATS.GATHER_SYSTEM_STATS(停止)过程。
• 运行DBMS_STATS.GATHER_SYSTEM_STATS('interval',interval => N),其中N是统计信息收集自动停止的分钟数.
要删除系统统计信息,请运行dbms_stats.delete_system_stats()。 工作负载统计信息被删除并重置为默认的现在的数据统计.
统计表在临时表中运行
PeopleSoft在批处理中使用共享临时表,专用临时表或两者。 这些临时表在进程的开头几行或没有行; 在进程结束时,这些表将再次具有很少或没有行。 保持这些表更新的统计数据有些挑战。 临时表的生命周期如下:
4. 在AE执行开始时,所有行将自动截断(如果是专用的)或删除(如果共享).
5. 行已填充.
6. 如果程序员已经请求,所有行将在AE执行结束时被截断(如果专用)或删除(如果共享)。 此操作不会自动执行.
从PeopleSoft 8开始,AE程序可以在将行填充到临时表之后使用元SQL“%UpdateStats”。 这样做会在以后的SQL语句中使用表之前更新临时表中的统计信息.
Example
SQL中的命令应用程序引擎程序步骤:%UpdateStats(%表(INTFC_BI_HTMP))以Peopletools 8.48开头的元SQL将在运行时发出Oracle数据库命令:
关闭%UpdateStats
在运行时更新统计信息会产生一些开销。 如果要关闭此功能,请检查进程调度程序文档.
临时表的锁定统计
客户经常遇到挑战,以保持PeopleSoft专用临时表的准确统计。 发生大多数性能问题是因为在表没有行的情况下,常规数据库维护窗口中更新临时表统计信息时,或者表中的数据从另一个运行中收集的统计信息与数据量或数据分布有显着差异时更新。 解决方案是删除和锁定临时表统计信息。 更新表统计信息的COBOL或AE进程必须使用FORCE选项进行.
按照以下步骤锁定Application Engine临时表的统计信息:
1. 通过sqlplus运行此SQL来识别PeopleSoft临时表的列表:
2. 使用此SQL命令构建SQL脚本以删除具有0行统计信息的临时表的统计信息:
3. 通过sqlplus运行在步骤2中创建的脚本.
4. 构建SQL脚本以使用此SQL命令来锁定所有临时表的统计信息:
5. 通过sqlplus运行在步骤4中创建的脚本。 当您尝试更新其统计信息被锁定的表的统计信息时,将会收到此错误:
6. 修改Oracle Platform的SQL#4和SQL#5 DDL模型默认值,以在AE或COBOL处理期间使用meta-sql%UpdateStats更新统计信息时启用选项强制:
增强DBMS_STATS
待处理统计
从Oracle 11g开始,用户可以选择收集统计信息,但不会发布,直到新的统计信息经过彻底测试。 可以通过将数据库中的所有表,模式中的所有表或特定表的PUBLISH参数设置为FALSE来启用此选项.
For example:
1. 通过使用该命令将参数PUBLISH设置为FALSE,从而实现数据库级别:
参数ADD_SYS的值为TRUE将包括所有Oracle_owned表.
2. 通过使用该命令将参数PUBLISH设置为FALSE,可以使用模式级别:
3. 通过使用该命令将参数PUBLISH设置为FALSE来显示表级别:
PUBLISH参数设置为FALSE后,不会发布后续统计信息收集。 统计信息保存在名为USER_TAB_PENDING_STATS的表中。 优化器将继续使用存储在数据字典表中的统计信息。 要使用挂起的统计信息,必须将init.ora参数OPTIMIZER_USE_PENDING_STATISTICS设置为TRUE,然后运行常规工作负载。 您还可以使用DBMS_STATS.EXPORT_PENDING_STATS将挂起的统计信息导出到测试数据库以运行预期的工作负载。 统计时,使用DBMS_STATS.PUBLISH_PENDING_STATS使其可供所有人使用,或者如果新的统计信息不能产生可接受的执行计划,则使用DBMS_STATS.DELETE_PENDING_STATS将其删除.
例子
此示例介绍如何使用Pending统计信息:
假设对PS_VCHR_ACCTG_LN进行了大量修改,并且再次运行统计信息以反映更改,但DBA不希望优化器在当前计划可接受时生成坏计划。 以下可以做到:
1. 将表统计信息设置为待处理:
2. 更新PS_VCHR_ACCTG_LN的统计信息.
3. 使挂起的统计信息可用于用户会话并运行一些示例SQL语句:
4. 当新统计数据生成可接受的执行计划时,发布新的统计信息:
5. 关闭表中的挂起选项:
扩展统计
表达统计
此新功能有助于生成列中表达式的统计信息。 当函数应用于表的列时,优化器无法知道该表达式的选择性,因此无法使用该表达式为SQL语句生成最优的访问计划。 在11g中,用户可以创建和存储表达式列的统计信息。
在以下示例中,只有一行的值为“BROWN”,“ALLISON”的值。 从解释计划中,优化器估计将有1,503行将恢复.
创建表达统计之前:
SQL> select * from ps_personal_data where upper(name)='BROWN,ALLISON';
Execution Plan
--------------
----------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
----------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1503 | 507K| 1769 |
| 1 | TABLE ACCESS FULL| PS_PERSONAL_DATA | 1503 | 507K| 1769 |
----------------------------------------------------------------------
运行此命令创建统计表达式“表(PSPERSONAL_DATA =”:
验证扩展统计信息已创建:
创建表达式统计信息后,执行计划如下所示:
SQL> select * from ps_personal_data where upper(name)='BROWN,ALLISON';
Execution Plan
----------------
----------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
----------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3630 | 1768 |
| 1 | TABLE ACCESS FULL| PS_PERSONAL_DATA | 1 | 3630 | 1768 |
----------------------------------------------------------------------
如果在upper(name)上创建了索引,则执行计划如下所示:
SQL> Create index PSZPERSONAL_DATA ON PS_PERSONAL_DATA (UPPER(NAME));
SQL> select * from ps_personal_data where upper(name)='BROWN,ALLISON'; Execution Plan
--------------
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2076 | 5 |
| 1 | TABLE ACCESS BY INDEX ROWID| PS_PERSONAL_DATA | 1 | 2076 | 5 |
| 2 | INDEX RANGE SCAN | PSZPERSONAL_DATA | 1 | | 3 |
--------------------------------------------------------------------------------
多栏统计
在Oracle Database 11g第2版(11.2.0.2)中,您可以使Oracle自动确定基于给定工作负载的表所需的哪些扩展统计信息。 这个过程是三个步骤:
1. SEED_COL_USAGE.
Oracle必须遵守代表性的工作量来确定适当的扩展统计信息。 使用新的过程DBMS_STATS.SEED_COL_USAGE,你告诉Oracle应该观察工作量多长时间。 以下示例打开监视5分钟或300秒:
您应该在Oracle警报日志中看到以下条目:
ALTER SYSTEM SET _column_tracking_level=3 SCOPE=MEMORY;
2. 查看列使用情况报告.
监控窗口完成后,您可以查看使用新程序DBMS_STATS.REPORT_COL_USAGE记录的列使用信息.
SELECT DBMS_STATS.REPORT_COL_USAGE(‘FMS91’, ‘PS_LEDGER) FROM dual;
DBMS_STATS.REPORT_COL_USAGE('FMS91','PS_LEDGER')
-------------------------------------------------------------------------------- LEGEND:
EQ : Used in single table EQuality predicate RANGE : Used in single table RANGE predicate LIKE : Used in single table LIKE predicate
NULL : Used in single table is (not) NULL predicate EQ_JOIN : Used in EQuality JOIN predicate
NONEQ_JOIN : Used in NON EQuality JOIN predicate FILTER : Used in single table FILTER predicate JOIN : Used in JOIN predicate
DBMS_STATS.REPORT_COL_USAGE('FMS91','PS_LEDGER')
--------------------------------------------------------------------------------
GROUP_BY : Used in GROUP BY expression
.......................................................................
#################################################################### COLUMN USAGE REPORT FOR FMS91.PS_LEDGER
.......................................
1. ACCOUNT : EQ
2. ACCOUNTING_PERIOD : EQ RANGE
3. BUSINESS_UNIT : EQ RANGE LIKE
4. DEPTID : LIKE
5. FISCAL_YEAR : EQ RANGE
6. LEDGER : EQ
7. PROCESS_INSTANCE : EQ
8. PRODUCT : EQ LIKE
9. (BUSINESS_UNIT, PRODUCT) : FILTER JOIN
################################################################### DBMS_STATS.REPORT_COL_USAGE('FMS91','PS_LEDGER')
--------------------------------------------------------------------------------
报告显示,在30分钟监控窗口观察期间,上述这些PS_LEDGER表格列用于这些类型的操作。 项目#9是一组列,它们是组列统计信息的候选项.
3. 创建扩展统计信息.
在查看表的列使用情况报告后,可以通过运行以下命令来指示Oracle创建组列统计信息:
SELECT DBMS_STATS.CREATE_EXTENDED_STATS(('fms91','ps_ledger') FROM dual;
Once created, the extended statistics will be maintained for the table whenever statistics are gathered in the table.
创建后,只要在表中收集统计信息,就会维护表的扩展统计信息。
如果建议使用多组列统计信息,并且您决定仅实施一个组列统计信息,则可以使用此命令手动执行此操作:
SELECT DBMS_STATS.CREATE_EXTENDED_STATS(('fms91','ps_ledger', ’(BUSINESS_UNIT, PRODUCT)’ ) FROM
dual;
要验证是否为该表创建了组列统计信息,请执行以下操作:
1. 运行列使用情况报告:
SELECT DBMS_STATS.REPORT_COL_USAGE('fms91','ps_ledger') from dual;
DBMS_STATS.REPORT_COL_USAGE('FMS91','PS_LEDGER')
-------------------------------------------------------------------------------- LEGEND:
EQ : Used in single table EQuality predicate RANGE : Used in single table RANGE predicate LIKE : Used in single table LIKE predicate
NULL : Used in single table is (not) NULL predicate EQ_JOIN : Used in EQuality JOIN predicate
NONEQ_JOIN : Used in NON EQuality JOIN predicate FILTER : Used in single table FILTER predicate JOIN : Used in JOIN predicate
DBMS_STATS.REPORT_COL_USAGE('FMS91','PS_LEDGER')
--------------------------------------------------------------------------------
GROUP_BY : Used in GROUP BY expression
.......................................................................
#################################################################### COLUMN USAGE REPORT FOR FMS91.PS_LEDGER
.......................................
1. ACCOUNT : EQ
2. ACCOUNTING_PERIOD : EQ RANGE
3. BUSINESS_UNIT : EQ RANGE LIKE
4. DEPTID : LIKE
5. FISCAL_YEAR : EQ RANGE
6. LEDGER : EQ
7. PROCESS_INSTANCE : EQ
8. PRODUCT : EQ LIKE
9. SYS_STUKS781GZM7K2OCX_7KG0_JT$ : EQ
10. (BUSINESS_UNIT, PRODUCT) : FILTER JOIN
################################################################### DBMS_STATS.REPORT_COL_USAGE('FMS91','PS_LEDGER')
--------------------------------------------------------------------------------
2. 检查字典表:
3. 要删除扩展统计信息,请运行此命令:
exec DBMS_STATS.DROP_EXTENDED_STATS('fms91','ps_ledger','("BUSINESS_UNIT","PRODUCT")');
直方图
什么是直方图?
直方图在存在数据偏移的情况下提供了改进的选择性估计,从而导致具有非均匀数据分布的最佳执行计划。 直方图将列的值分成带,使得带中的所有列值都落在相同的范围内。 CBO使用直方图中的数据来获得列数据分布的准确估计.
基于不同值和频带数量,Oracle使用高度平衡的直方图或基于频率的直方图。 有关详细信息,请参阅Oracle文档.
PeopleSoft应用程序中直方图的候选列
柱状图可能会影响性能,只有在大幅改进查询计划时才应使用。 一般来说,应该创建直方图:
• 查询的WHERE子句中经常使用的列。
• 高度倾斜的数据分布。
• 提供的字面值,而不是使用WHERE子句中给定列的绑定变量。
• 作为索引的一部分的列.
因为典型的PeopleSoft应用程序使用SQL绑定,您应该关闭直方图以获得PeopleSoft应用程序的最佳执行计划.
此示例是生成不带直方图的表的统计信息:
此示例是在没有直方图的情况下在架构级别生成统计信息:
直方图是持久性对象,因此使用它们的维护和存储成本.
对于均匀分布的数据,CBO可以对不执行直方图的特定语句的执行成本进行相当准确的估计。 像所有其他优化器统计信息一样,直方图是静态的,只有在使用DBMS_STATS过程中的“SIZE”选项生成新统计信息时才会更改.
直方图对于具有以下特征的列无效:
•列数据均匀分布。
•查询的WHERE子句中未使用列。
•列是唯一的。
•列用于WHERE子句,但包含绑定变量而不是字面值。
诸如PROCESS_INSTANCE,ORD_STATUS之类的列可能受益于直方图。
此示例使用更新统计信息来使优化程序与PROCESS_INSTANCE一起使用复合索引:
查看直方图
可以使用以下字典视图显示有关该表中是否有直方图信息:
• USER_HISTOGRAMS
• ALL_HISTOGRAMS
• DBA_HISTOGRAMS
可以使用以下字典视图显示列直方图中的bands数:
• USER_TAB_COLUMNS
• ALL_TAB_COLUMNS
• DBA_TAB_COLUMNS
用自适应光标共享改变绑定行为的行为
以前版本的数据库的一个常见问题是,当使用绑定变量时,初始计划可能不是最佳的:
• •未来执行中使用的未来价值共享初始计划。
• •使用的第一套绑定可能不代表大多数执行,因此,在最适合大多数执行情况的情况下,初始计划可能被认为是坏的.
Oracle 11G引入了自适应光标共享的概念。 现在的想法是不再盲目地共享计划,只有当你认为绑定值不会降低当前存储的执行计划时,才能这样做。 自适应光标共享将指示Oracle窥视所有绑定,而不是仅仅第一组绑定,然后选择最适合每个绑定值集的计划。
这是它的工作原理。 SQL语句的第一次执行将导致硬解析。 如果存在直方图,则启用绑定窥视,并且游标使用绑定值来估计每个列值的选择性,并将SQL标记为绑定敏感。 在SQL的后续执行中,Oracle将再次窥视其绑定值并计算选择性。 如果执行计划不同,则SQL将被标记为绑定感知.
总而言之,自适应光标共享引入的更改是:
• •当绑定值相等时共享计划。
• •计划标有选择范围。
• •如果当前绑定值在范围内,Oracle将使用相同的计划。
• •如果绑定不相等,则创建新计划,生成不同选择范围的新计划。
• •此行为由数据库参数_optim_peek_user_binds控制; 默认情况下,它已启用。
• •由V $ SQL添加的两个新列监视游标:
• •IS_BIND_SENSITIVE - 优化器认为该计划可能取决于绑定的值。
• •IS_BIND_AWARE - 此语句存在多个执行计划.
什么是专用临时表?
在应用程序引擎中编写的批处理使用PeopleSoft指定的临时表(也称为专用临时表)以进行更好的处理.
这种技术可以最大限度地减少潜在的锁定问题并提高处理 这些是常规Oracle表,但在PeopleSoft字典表中标记为临时表。 在Oracle数据库上实现时,使用Oracle表构建PeopleSoft指定的临时表。 所需的临时表链接到程序属性窗口中的AE程序。
还为每个AE程序指定了所需的实例数.
以下是AE程序Bill Finalization(BIIF0001)的财产窗口。 指定的实例计数是运行多个程序实例时可以使用的临时表实例数量的限制。 如果运行的程序数量大于指定的计数(在本示例中为10),那么根据窗口中的Runtime单选按钮选择,附加进程将被放弃或将使用基本临时表.
创建PEOPLESOFT TEMPORARY TABLES 作为ORACLE GLOBAL TEMP TABLES
什么是Global Temporary Table (GTT)?
Oracle8i引入了GTT,可用于任何批处理的临时处理表。 GTT的实例将在运行时在用户的临时表空间中创建。 这些表是会话特定的。 会话关闭或事务提交后,表数据将被删除。 在创建表时,GTT提供了在提交后保留或删除行的选项。
可以使用GTT而不是专用临时表?
到目前为止,PeopleSoft没有提供脚本或实用程序来创建GTT,因此这将是客户的定制。 我们不建议您创建PeopleSoft临时表作为GTT,因为它可能会影响重新启动PeopleSoft程序的能力.
分区
分区是一种数据量管理技术。 当进行详细分析以设计分区密钥以符合数据的访问方式时,它具有性能优势。 在使用增加的db_writers和并行度的情况下,在多处理器机器上最有效。 分区解决了支持非常大的表和索引的关键问题,允许您将其解构为更小,更易于管理的称为分区的部分。 每个分区都有自己的名字,可能有自己的存储特性。 定义分区后,SQL语句可以访问和操作分区,而不是整个表或索引.
分区表
你能用2种方式分区表:
• 可管理性分区.
• 性能分区.
可管理性分区
分区使DBA能够采用分割和征服方法来管理数据库表,特别是当这些表增长时。 大多数人将实施这种分区方法来简化大型表的维护,并将历史数据与当前数据隔离开来。 此方法允许某些维护操作发生在日常操作活动不需要的分区上,例如压缩比2006年以前的数据或存档2001年以前的数据。
例如,通过Fiscal_year列分区PS_LEDGER将允许DBA删除包含Fiscal_year 2005数据的分区比单独删除行重组表更有效.
性能分区
如果您的目标是能够更快地访问数据,无论数据库是否具有10 GB或10 TB的数据,分区可以帮助您加快数据访问速度,如果实施正确。 这种分区策略需要深入了解数据的访问方式。 它有助于限制要检查或操作的数据量。 分配性能的目标必须产生以下好处:
• 消除大量不必要数据的扫描.
• 通过单个/复合分区密钥对大量相关数据进行物理分组.
注意:您使用索引查找少量所需数据; 您可以使用分区来消除大量不需要的数据.
如果您使用索引来检索所需的数据,那么如果最终结果很大并且分散在多个块中,则执行大量单块读取。 如果强制进行表扫描,则可以以多个块的块读取所需的数据,但是还必须读取相邻块中驻留的不需要的数据。 通过分区表,您可以利用分区修剪来对您感兴趣的数据进行多块读取.
在最近的PeopleSoft北美薪资基准测试中,我们能够消除90%的I / O瓶颈,并通过范围划分工资单表达到高吞吐量,例如Paygroup中的PS_PAY_EARNINGS,PS_PAY_TAX,PS_PAY_CHECK等。 由于Payroll作业流由PAYGROUP处理工资单,因此该策略允许每个并发工资单作业流在单个分区上运行。 每个作业流的所有更新,插入,删除和选择操作都将发生在一个且仅一个分区上,从而消除:
• 插入热点。 发生缓冲区忙等待的等待事件的一个主要原因是因为许多会话同时插入同一个表中。 通过按PAYGROUP划分表,您可以将不同地方的每个并发工资单作业流的插入分开,从而消除缓冲区忙等待.
• 集群在RAC上等待。 当多个工资核算作业流同时在同一个表中进行大量DML操作时,数据块在实例之间来回传递。 当块正在传输时,请求该块的会话必须等待在集群等待的类别下分组的不同事件,例如gc缓冲区忙,gc当前块2路,gc cr块2路等。 当许多节点在同一个块上遇到等待时,过多的等待可能导致数据库挂起情况。 如果数据在与工作负载相同的行中进行分区,则会降低在群集节点之间来回传递大量数据的可能性,从而最小化节点间流量.
• I / O争用。 由于每个分区可以分隔成不同的数据文件放置在不同的磁盘上,所以可以更有效地完成I / O.
对于没有Paygroup列的Payroll表,例如PS_TAX_BALANCE,PS_EARNINGS_BAL,PS_DEDUCTION_BAL,通过EMPLID对表进行散列分区以消除缓冲区占线等待并均匀分配I / O.
此示例显示如何使用paygroup的范围分区创建表:
DED_SUBSET_ID VARCHAR2(3) NOT NULL, DED_TAKEN_GENL VARCHAR2(1) NOT NULL, DED_SUBSET_GENL VARCHAR2(3) NOT NULL, STATE VARCHAR2(6) NOT NULL,
LOCALITY VARCHAR2(10) NOT NULL, PAY_FREQUENCY VARCHAR2(5) NOT NULL, TAX_PERIODS SMALLINT NOT NULL, TAX_METHOD VARCHAR2(1) NOT NULL, ADDL_TAXES VARCHAR2(1) NOT NULL, OVERRIDE_HOURLY_RT VARCHAR2(1) NOT NULL, TL_SOURCE VARCHAR2(1) NOT NULL, PAY_SHEET_SRC VARCHAR2(1) NOT NULL, BUSINESS_UNIT VARCHAR2(5) NOT NULL, EI_PRIOR_PD_CORR VARCHAR2(1) NOT NULL, COMP_RATECD_REG VARCHAR2(6) NOT NULL, COMP_RATECD_OT VARCHAR2(6) NOT NULL,
COMPRATE_USED_REG DECIMAL(18, 6) NOT NULL, COMPRATE_USED_OT DECIMAL(18, 6) NOT NULL, FICA_STATUS_EE VARCHAR2(1) NOT NULL, PAID_PRDS_PER_YEAR DECIMAL(5, 2) NOT NULL, FLSA_END_DT DATE,
ORIG_PAYGROUP VARCHAR2(3) NOT NULL, FLSA_STATUS VARCHAR2(1) NOT NULL, XREF_NUM DECIMAL(15) NOT NULL, UNION_CD VARCHAR2(3) NOT NULL, BEN_DED_STATUS VARCHAR2(1) NOT NULL, GENL_DED_STATUS VARCHAR2(1) NOT NULL, HP_CONTRACT_NUM SMALLINT NOT NULL, HP_CONTRACT_SEQ SMALLINT NOT NULL)
PARTITION BY RANGE (PAYGROUP) (
PARTITION PE_P000 VALUES LESS THAN ('100') TABLESPACE petab0,
PARTITION PE_P100 VALUES LESS THAN ('101') TABLESPACE petab1,
PARTITION PE_P101 VALUES LESS THAN ('102') TABLESPACE petab2,
PARTITION PE_P102 VALUES LESS THAN ('103') TABLESPACE petab3,
PARTITION PE_P103 VALUES LESS THAN ('104') TABLESPACE petab4,
PARTITION PE_P104 VALUES LESS THAN ('105') TABLESPACE petab5,
PARTITION PE_P105 VALUES LESS THAN ('106') TABLESPACE petab6,
PARTITION PE_P106 VALUES LESS THAN ('107') TABLESPACE petab7,
PARTITION PE_P107 VALUES LESS THAN ('108') TABLESPACE petab8,
PARTITION PE_P107 VALUES LESS THAN ('109') TABLESPACE petab9,
PARTITION PE_P999 VALUES LESS THAN (MAXVALUE) TABLESPACE petab10)
;
此示例显示如何通过EMPLID的哈希分区创建表:
性能和可管理性分区
在某些情况下,您可以通过使用不同的分区技术的组合来实现复合分区,从而为这两种场景,可管理性和性能进行分区。 Oracle 11g支持这些复合分区方法:
• Range-hash partitioning
• Range-list partitioning
• Range-range partitioning
• List-hash partitioning
• List-list partitioning
• List-range partitioning
• Hash-hash partitioning
• Interval-hash partitioning
• Interval -list partitioning
• Interval-range partitioning
两种数据分配方法的组合用于定义复合分区表。 首先,通过数据分发方法对表进行分区,然后使用第二数据分配方法将每个分区进一步细分为子分区。 给定分区的所有子分区一起表示数据的逻辑子集。 例如,范围散列复合分区表是第一范围分区,然后每个范围分区进一步使用散列分割技术进行子分区.
例如,通过Fiscal_year列分区PS_LEDGER允许DBA比单独删除行重组表更有效地删除包含Fiscal_year 2005的数据的分区。 您还可以在BUSINESS_UNIT的LIST上进一步分区PS_LEDGER,以便将给定的Business_unit的所有行分组在一起,从而提高Business_unit访问当前年数据的进程的性能.
另一个例子是,如果你有一家公司需要每五年存档50万名员工的数据,并且您通过Paygroup运行您的工资单。 您可以通过PAY_END_DT的范围对工资核算表进行分区,例如PS_PAY_EARNINGS,PS_PAY_TAX,PS_PAY_CHECK等,以便每月工资单的数据位于同一分区中; 例如,如果PAY_END_DT是分区键,那么Jan-2006分区将包含分区键值在01-01-2006和01-31-2006之间的行.
您可以进一步将您的工资核算表分配到PAYGROUP范围,以便每个付费组的每个月的数据将位于相同的分区中。 如果范围不适用于您,因为您的Paygroup的值未设置为范围,则可以使用LIST分区。 这种分区方法还可以将几个小的Paygroup集合组合成一个分区.
当工资单进程运行时,每个并发作业流将访问自己的分区,并且当对2006年1月的数据进行归档时,可以删除Jan-2006分区。 您还可以选择性地压缩非活跃月份的工资单数据.
这个例子展示了如何创建一个带范围分区的表:
BENEFIT_RCD_NBR SMALLINT NOT NULL, EARNS_END_DT DATE,
EARNS_BEGIN_DT DATE,
ADDLPAY_REASON VARCHAR2(3) NOT NULL, DISABLE_DIR_DEP VARCHAR2(1) NOT NULL, GROSSUP VARCHAR2(1) NOT NULL, PAY_LINE_STATUS VARCHAR2(1) NOT NULL, OK_TO_PAY VARCHAR2(1) NOT NULL, JOB_PAY VARCHAR2(1) NOT NULL, SINGLE_CHECK_USE VARCHAR2(1) NOT NULL, ACCT_CD VARCHAR2(25) NOT NULL, GL_PAY_TYPE VARCHAR2(6) NOT NULL, DEPTID VARCHAR2(10) NOT NULL,
JOBCODE VARCHAR2(6) NOT NULL, POSITION_NBR VARCHAR2(8) NOT NULL, SHIFT VARCHAR2(1) NOT NULL, SHIFT_RT DECIMAL(18, 6) NOT NULL, HOURLY_RT DECIMAL(18, 6) NOT NULL, FLSA_RT DECIMAL(18, 6) NOT NULL, RATE_USED VARCHAR2(1) NOT NULL, FLSA_REQUIRED VARCHAR2(1) NOT NULL, ERNCD_REG_HRS VARCHAR2(3) NOT NULL, ERNCD_OT_HRS VARCHAR2(3) NOT NULL, REG_PAY_HRS DECIMAL(6, 2) NOT NULL, REG_HRS DECIMAL(6, 2) NOT NULL, OT_HRS DECIMAL(6, 2) NOT NULL,
REG_HRLY_EARNS DECIMAL(10, 2) NOT NULL, OT_HRLY_EARNS DECIMAL(10, 2) NOT NULL, ERNCD_REG_EARNS VARCHAR2(3) NOT NULL, REG_PAY DECIMAL(10, 2) NOT NULL, REG_EARNS DECIMAL(10, 2) NOT NULL, REG_EARN_HRS DECIMAL(6, 2) NOT NULL, DED_TAKEN VARCHAR2(1) NOT NULL, DED_SUBSET_ID VARCHAR2(3) NOT NULL, DED_TAKEN_GENL VARCHAR2(1) NOT NULL, DED_SUBSET_GENL VARCHAR2(3) NOT NULL, STATE VARCHAR2(6) NOT NULL,
LOCALITY VARCHAR2(10) NOT NULL, PAY_FREQUENCY VARCHAR2(5) NOT NULL, TAX_PERIODS SMALLINT NOT NULL, TAX_METHOD VARCHAR2(1) NOT NULL, ADDL_TAXES VARCHAR2(1) NOT NULL, OVERRIDE_HOURLY_RT VARCHAR2(1) NOT NULL, TL_SOURCE VARCHAR2(1) NOT NULL, PAY_SHEET_SRC VARCHAR2(1) NOT NULL, BUSINESS_UNIT VARCHAR2(5) NOT NULL, EI_PRIOR_PD_CORR VARCHAR2(1) NOT NULL, COMP_RATECD_REG VARCHAR2(6) NOT NULL, COMP_RATECD_OT VARCHAR2(6) NOT NULL,
COMPRATE_USED_REG DECIMAL(18, 6) NOT NULL, COMPRATE_USED_OT DECIMAL(18, 6) NOT NULL, FICA_STATUS_EE VARCHAR2(1) NOT NULL, PAID_PRDS_PER_YEAR DECIMAL(5, 2) NOT NULL, FLSA_END_DT DATE,
ORIG_PAYGROUP VARCHAR2(3) NOT NULL, FLSA_STATUS VARCHAR2(1) NOT NULL, XREF_NUM DECIMAL(15) NOT NULL, UNION_CD VARCHAR2(3) NOT NULL, BEN_DED_STATUS VARCHAR2(1) NOT NULL, GENL_DED_STATUS VARCHAR2(1) NOT NULL, HP_CONTRACT_NUM SMALLINT NOT NULL, HP_CONTRACT_SEQ SMALLINT NOT NULL)
PARTITION BY RANGE (PAY_END_DT ) SUBPARTITION BY RANGE (PAYGROUP)
SUBPARTITION Yr2009_P000 VALUES LESS THAN ('100') TABLESPACE petab0,
SUBPARTITION Yr2009_P100 VALUES LESS THAN ('101') TABLESPACE petab1,
SUBPARTITION Yr2009_P101 VALUES LESS THAN ('102') TABLESPACE petab2,
SUBPARTITION Yr2009_P102 VALUES LESS THAN ('103') TABLESPACE petab3,
SUBPARTITION Yr2009_P103 VALUES LESS THAN ('104') TABLESPACE petab4,
SUBPARTITION Yr2009_P104 VALUES LESS THAN ('105') TABLESPACE petab5,
SUBPARTITION Yr2009_P105 VALUES LESS THAN ('106') TABLESPACE petab6,
SUBPARTITION Yr2009_P106 VALUES LESS THAN ('107') TABLESPACE petab7,
SUBPARTITION Yr2009_P107 VALUES LESS THAN ('108') TABLESPACE petab8,
SUBPARTITION Yr2009_P107 VALUES LESS THAN ('109') TABLESPACE petab9,
SUBPARTITION Yr2009_P999 VALUES LESS THAN (MAXVALUE) TABLESPACE petab10),
(PARTITION Yr2010 values less than (to_date('12-31-2010','mm-dd-yyyy')) SUBPARTITION Yr2010_P000 VALUES LESS THAN ('100') TABLESPACE petab0, SUBPARTITION Yr2010_P100 VALUES LESS THAN ('101') TABLESPACE petab1, SUBPARTITION Yr2010_P101 VALUES LESS THAN ('102') TABLESPACE petab2, SUBPARTITION Yr2010_P102 VALUES LESS THAN ('103') TABLESPACE petab3, SUBPARTITION Yr2010_P103 VALUES LESS THAN ('104') TABLESPACE petab4, SUBPARTITION Yr2010_P104 VALUES LESS THAN ('105') TABLESPACE petab5, SUBPARTITION Yr2010_P105 VALUES LESS THAN ('106') TABLESPACE petab6, SUBPARTITION Yr2010_P106 VALUES LESS THAN ('107') TABLESPACE petab7, SUBPARTITION Yr2010_P107 VALUES LESS THAN ('108') TABLESPACE petab8, SUBPARTITION Yr2010_P107 VALUES LESS THAN ('109') TABLESPACE petab9,
SUBPARTITION Yr2010_P999 VALUES LESS THAN (MAXVALUE) TABLESPACE petab10),
(PARTITION Yr2011 values less than (to_date('12-31-2011','mm-dd-yyyy')) SUBPARTITION Yr2011_P000 VALUES LESS THAN ('100') TABLESPACE petab0, SUBPARTITION Yr2011_P100 VALUES LESS THAN ('101') TABLESPACE petab1, SUBPARTITION Yr2011_P101 VALUES LESS THAN ('102') TABLESPACE petab2, SUBPARTITION Yr2011_P102 VALUES LESS THAN ('103') TABLESPACE petab3, SUBPARTITION Yr2011_P103 VALUES LESS THAN ('104') TABLESPACE petab4, SUBPARTITION Yr2011_P104 VALUES LESS THAN ('105') TABLESPACE petab5, SUBPARTITION Yr2011_P105 VALUES LESS THAN ('106') TABLESPACE petab6, SUBPARTITION Yr2011_P106 VALUES LESS THAN ('107') TABLESPACE petab7, SUBPARTITION Yr2011_P107 VALUES LESS THAN ('108') TABLESPACE petab8, SUBPARTITION Yr2011_P107 VALUES LESS THAN ('109') TABLESPACE petab9,
SUBPARTITION Yr2011_P999 VALUES LESS THAN (MAXVALUE) TABLESPACE petab10);
索引分区
你可以用2种方式分区一个索引:
• Local partition
• Global partition
本地分区索引
本地分区索引是与其基础表进行等分区分的索引。 特定索引分区中的所有键仅引用存储在单个底层表分区中的行。 当在具有属性LOCAL的分区表上创建索引时,Oracle会在与基础表相同的列上分割索引,创建相同数量的分区或子分区,并将它们与基础表的相应分区赋予相同的分区边界 。 当基础表中的分区被添加,删除,合并或拆分时,Oracle还会自动维护索引分区,从而确保索引与表保持等分。.
此示例创建由PAYGROUP均衡分割的唯一LOCAL索引:
全局分区索引
全局分区索引是不与其基础表进行等价分区的索引。 特定索引分区中的所有键可以引用存储在多个基础表分区或子分区中的行。 全局分区索引比本地索引更难管理,因为当基础表分区中的数据被移动或删除(SPLIT,MOVE,DROP或TRUNCATE)时,全局索引的所有分区都会受到影响.
此示例显示如何在EMPLID列上创建全局散列分区索引,而基础表PS_PAY_CHECK由Paygroup进行范围分区。 此索引将帮助检索给定emplID的数据的SQL语句。 没有全局索引,Oracle必须检查每个索引分区以找到emplID的匹配项.
索引分区指南
本地和全局分区索引之间的主要区别是本地索引的分区的索引条目指向基础表的正好一个分区,而全局索引的分区的索引条目可能指向任何或所有分区的 底层表。 因此,全局索引的分区数可能与底层表的分区数不同.
当决定使用什么样的分区索引时,您应该考虑以下这个指南r:
1. 如果表分区列是索引键的子集,则使用本地索引.
2. 如果索引是唯一的,并且不包括分区键列,则使用全局索引.
3. 如果您的优先级是可管理性,则使用本地索引.
4. 如果应用程序主要是OLTP类型,并且用户需要快速响应时间,则使用全局索引.
5. 如果应用程序是DSS类型,并且用户对吞吐量更感兴趣,则使用本地索引.
PeopleSoft提供的索引本质上是通用的。 根据客户的业务需求和数据组成,索引要求可能会有所不同。 以下提示将有助于DBA有效管理索引.
索引提示
1. 查看产品提供的索引推荐文档,看看是否有任何建议适用于您的安装.
2. 为进程运行Oracle跟踪/ TKPROF报告,并检查访问路径以确定索引的用法.
3. 考虑添加附加索引,具体取决于您的处理和性能需求.
4. 检查可用索引并删除任何未使用的索引,以提高插入/更新/删除DML的性能。 有时,在批处理过程中未使用的索引可能对在线页面有用; 反之亦然。 在删除任何索引之前执行彻底的系统分析。 索引删除可能会严重影响其他程序的性能.
重建索引
当发现性能问题时,您应该重建索引,从而SQL执行计划正在通过范围扫描或全索引扫描访问索引,并且为相对较小的数目目睹了大量的逻辑IO(也可能是物理IO)的扫描返回的行。
通常,当从表中删除大量行时,可能会发生这种情况。在索引中,所有行都被逻辑地删除,但是物理上它们仍然保留,直到索引被重建。出于运行时性能原因,Oracle有意识地决定不合并近空块或重新平衡物理索引块。该决定导致删除的块在索引中停留,直到重建为止。在范围扫描和全索引扫描期间,仍然会读取这些已删除/空的块,从而导致性能下降。
在撰写本文时,很少有关于索引重建标准的信息似乎可用于11g。以下Oracle支持说明可以提供有关何时重建或合并索引的洞察:
• 注989186.1:调查b-tree索引结构的脚本。 该脚本将根据现有表和索引统计信息验证b-tree索引的结构.
• 注989093.1:索引重建,需求与影响。 本说明概述重建索引的含义s.
基于函数的索引
基于函数的索引是创建的索引:
• 表达式,如算术表达式或包含包函数的表达式.
• 按降序排列.
基于函数的索引与表达式
这些索引是在索引的列周围包含表达式的索引。 它们在PeopleSoft中非常罕见,并且旨在提高特定SQL语句的性能.
例子
表PS_CUSTOMER具有索引PS0CUSTOMER,其中NAME1作为前导列:
SELECT SETID,CUST_ID,NAME1 FROM PS_CUSTOMER WHERE NAME1 LIKE 'Adventure%'; SQL>
SETID CUST_ID NAME1
----- --------------- -----------------
SHARE 1008 Adventure 54
查询使用索引PS0CUSTOMER并更快地返回结果.
SELECT SETID,CUST_ID,NAME1 FROM PS_CUSTOMER WHERE NAME1 LIKE 'ADVENTURE%'; SQL>
No rows selected
查询使用索引PS0CUSTOMER并返回结果更快,但不提供行.
如果数据以混合大小写存储,例如前面的示例,则使用一致的大小写过滤器获取结果的唯一方法是使用“UPPER”函数。
SELECT SETID,CUST_ID,NAME1 FROM PS_CUSTOMER WHERE UPPER(NAME1) LIKE 'ADVENTURE%';
SQL>
SETID CUST_ID NAME1
----- --------------- -----------------
SHARE 1008 Adventure 54
查询不使用PS0CUSTOMER索引,因此需要很长时间才能返回。 但是,返回的数据是正确的.
在这种情况下,使用基于函数的索引是有帮助的。
CREATE INDEX ON PSFCUSTOMER ON PS_CUSTOMER (UPPER(NAME1));
SELECT SETID,CUST_ID,NAME1 FROM PS_CUSTOMER WHERE UPPER(NAME1) LIKE 'ADVENTURE%';
SQL>
SETID CUST_ID NAME1
----- --------------- -----------------
SHARE 1008 Adventure 54
查询使用PSFCUSTOMER索引,更快地返回查询,并提供正确的输出.
基于函数的索引与降序列
PeopleSoft从PeopleTools 8.48开始生成带有DESCENDING列的索引。 这些索引在Oracle中被视为基于函数的索引。 这是一个例子:
当您从DBA_IND_COLUMNS中选择降序列名称时,它将显示为SYS_NC00033 $,这是一个系统生成的列名。 要查找真正的列名,您必须查看DBA_IND_EXPRESSIONS的COLUMN_EXPRESSION.
Oracle 11gR2上的最新基准显示,使用基于功能的索引的执行计划的成本较高,导致计划被丢弃,从而导致性能问题。 我们建议您删除所有具有降序列的索引,并用升序列重新创建它们.
删除并重新创建基于函数的索引的步骤
检索基于函数的索引的DDL,然后删除并重新创建索引作为升序索引。 为此,请执行以下步骤:
1. 登录到sqlplus并运行以下命令来生成脚本来删除基于函数的索引:
2. 登录到sqlplus,然后运行以下脚本输出到一个脚本来重新创建索引:
3. 在运行脚本之前设置此数据库参数以重新创建索引。 此设置将使Oracle忽略脚本的下降部分,并重新创建索引为升序:
Steps to Generate Statistics of the Whole Schema
运行这两个SQL命令:
LINGUISTIC INDEXES
在PeopleTools 8.4x中,PeopleSoft允许多语言客户使用除二进制排序之外的排序。 我们针对Oracle平台的语言排序实现旨在允许支持多个语言环境的中央数据库,并根据语言环境提供正确的排序顺序.
这是如何工作的:
客户使用默认的二进制排序顺序来实现数据库.
然后,客户根据PeopleTools选项PIA页面选择特定的语言排序顺序。 (排序顺序选项)。 在这个例子中,Dutch(General)要改变排序:
1. 选择PeopleTools,Utilities,Administration,PeopleTools选项。
2. 从排序顺序选项下拉列表框中选择一个选项。
3. 单击保存.
这将导致底层API层(PSORA)在连接进行工作单元时发出ALTER SESSION NLS_COMP = ANSI.
ALTER SESSION NLS_COMP = ANSI否定了默认的二进制排序顺序,并指示DB使用从NLS_LANGUAGE值(当未设置NLS_SORT时)派生的语言排序顺序用于SQL比较运算符,例如(=,>,<,BETWEEN, CASE WHEN,ORDER BY等等)。 如果在客户端上设置NLS_LANGUAGE作为注册表项或环境变量,则该客户端设置优先于数据库设置。 因此可以导出和使用特定于区域的排序顺序.
由于索引默认内置二进制顺序,因此当NLS_SORT显式或隐式设置为除BINARY以外的任何内容时,查询将始终使用全表扫描或合并笛卡尔加入。 由于现有的索引未被使用,因此会导致性能问题。 随着出货,PeopleTools只支持二进制排序。 但是,如果您准备好进行索引调整和测试,您可以将语言排序实现为自定义,然后在任何升级后可以重新实现这些排序.
提高语言排序性能的推荐方法是在SELECT列表上面列出的比较操作子句中引用的列上创建语言功能索引.
以下示例显示如何创建语言索引。
当使用NLS_COMP = ANSI运行时,以下SQL正在进行全表扫描: SELECT LAST_NAME_SRCH, FIRST_NAME_SRCH, EMPLID
FROM PS_NAMES
WHERE LAST_NAME_SRCH LIKE 'C%' ORDER BY LAST_NAME_SRCH;
由于NLS_LANGUAGE设置为DUTCH,因此创建语言索引以支持SQL:
CREATE INDEX PS1NAMES_DUTCH ON PS_NAMES (NLSSORT("LAST_NAME_SRCH", 'NLS_SORT = DUTCH'));
使用语言索引时,必须执行以下操作:
1. 将初始化参数QUERY_REWRITE_ENABLED设置为TRUE。
2. 将初始化参数NLS_COMP设置为ANSI或LINGUISTIC。
3. 初始化参数NLS_SORT或NLS_LANGUAGE必须指示您要用于语言排序的语言定义。
4. 例如:NLS_LANGUAGE = DUTCH
5. 使用基于成本的优化器,因为语言索引不能被基于规则的优化器识别。
6. SQL语句必须包含一个谓词来指定WHERE NLSSORT(column_name)IS NOT NULL.
当执行共享池中不存在的SQL语句时,必须完全解析。 Oracle必须为共享池中的语句分配内存,在语法和语义上检查语句,依此类推。 这被称为硬解析,并且在使用的CPU和执行的锁存器的数量方面都非常昂贵。
当Oracle服务器解析查询并且找不到库缓存中查询的完全匹配时,会发生硬解析。 这是由于SQL语句的低效共享,并且可以通过在查询中使用绑定变量而不是文字来改进。 有时,硬解析会导致CPU使用率过高。
可以在PeopleSoft Application Engine跟踪中识别硬解析数(128)。 以下是AE轨迹的示例(128):
C o m p i l e E x e c u t e F e t c h Total
SQL Statement Count Time Count Time Count Time Time
BL6100.10000001.S 252 0.6 252 1.5 0 0.0 2.1
在Oracle Trace中,输出语句显示为单独的语句,每个语句分析一次。 依靠Oracle跟踪输出来识别由于文字而不是绑定变量难解析的SQL有些困难。
甲骨文从Oracle8i介绍了这个新的参数CURSOR_SHARING。 默认情况下,其值设置为EXACT。 这意味着数据库在解析时会查找SQL语句的完全匹配。 您应该将参数设置为EXACT for PeopleSoft应用程序.
SQR/COBOL - CURSOR_SHARING
大多数SQR和COBOL程序都被写入使用绑定变量。 如果发现任何没有使用绑定变量的程序,并且无法修改代码,那么CURSOR_SHARING选项FORCE是有用的。 使用此设置,数据库将查找类似的语句,不包括传递给SQL语句的文字值。 Oracle用系统绑定变量替换文字值,并将它们视为单个语句和解析一次。
在会话级别设置值更合适。 如果您识别不使用绑定变量并需要强制他们在数据库级别使用绑定的程序(SQR / COBOL),则在程序开头添加ALTER SESSION命令应该是更好的选择。
如果您不愿意更改应用程序,则通过触发器实现会话级别命令将为您提供更大的灵活性.
Session Level (Using Trigger)
您可以使用以下示例触发器代码来实现会话级别选项:
例子
从SQR / COBOL程序发出的SQL语句:
上述语句在WHERE子句中使用一个字面值,从而为每个执行一个硬解析。 每一个艰难的解析都有一定的性能开销。 最小化它们将提高性能。
该语句针对BUSINESS_UNIT和INV_ITEM_ID的每个组合执行。 根据该基准测试中使用的数据组合,发生BUSINESS_UNIT和INV_ITEM_ID的大约13,035个独特组合和大约19,580个执行总数.
使用CURSOR_SHARING = FORCE的Oracle TKPROF输出:
通过在会话级别设置上述参数,整体处理时间显着减少。 总体统计,没有绑定变量:
call
-------
Parse count
------ 26389 cpu
--------
98.27 elapsed
----------
99.54 disk
----------
0 query
----------
1074 current
----------
0 rows
----------
0
Execute 404647 51.09 50.11 1757 242929 371000 78376
Fetch 517618 47.85 47.43 3027 1455101 235446 189454
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 948654 197.21 197.08 4784 1699104 606446 267830
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 27118 5.35 5.06 0 49 1 0
Execute 33788 2.42 2.22 0 5577 235 229
Fetch 54988 2.44 2.57 1 97241 0 47621
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 115894 10.21 9.85 1 102867 236 47850
具有绑定变量的总体统计信息:
call
-------
Parse count
------ 26389 cpu
--------
15.44 elapsed
----------
15.69 disk
----------
0 query
----------
0 current
----------
0 rows
----------
0
Execute 404647 44.02 43.51 173 231362 333538 78376
Fetch 517618 45.47 43.02 2784 1439571 235104 189454
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 948654 104.93 102.22 2957 1670933 568642 267830
Misses in library cache during parse: 64
Misses in library cache during execute: 1
OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 356 0.08 0.10 0 0 0 0
Execute 357 0.47 0.48 0 5568 228 228
Fetch 667 0.00 0.01 0 1333 0 552
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 1380 0.55 0.59 0 6901 228 780
从上述跟踪统计数据,请注意,使用绑定变量,库高速缓存未命中数量减少:
Original Timing Time with CURSOR_SHARING option %Gain
197 Sec 102 Sec 48%
在PeopleSoft数据库升级到Oracle 11g后,如果出现严重的性能下降,则需要执行以下操作:
1. 删除并重新创建PeopleTools 8.48及更高版本中引入的功能索引。 在这里记录的步骤。
2. 锁定PeopleSoft临时表的统计信息。 可以在这里找到这样做的指示。
3. 从PeopleSoft模式中删除直方图统计信息。 可以在这里找到这样做的指示。
4. 添加数据库参数,出于性能原因列出.
如果性能问题仍然存在,请联系Oracle支持。 将Oracle数据库中的性能问题报告给Oracle支持时,需要以下信息:
1. 确认我们所需的最小补丁已安装:
• 生成补丁库存清单:
o 登录到DB服务器.
o 将目录更改为cd $ ORACLE_HOME / Opatch.
o 发出以下命令:opatch lsinventory
• 登录到Oracle支持,以确保正在应用所有必需的最小补丁。 使用此链接来做到这一点:
2. 给我们一份你的init.ora或spfile.ora的副本。 如果他们帮助我们更好地诊断问题,还需要提醒日志和AWR报告.
使用“SQLTEXPLAIN.SQL”生成SQL的解释计划
对于一个SQL语句的增强型解释计划和诊断信息,sqltexplain实用程序是非常有用和强烈推荐的。 此实用程序的详细信息在Oracle支持说明215187.1中提供.
UNNESTED SUBQUERY
对于从Oracle 9i之前的Oracle版本升级到10g或11g的客户,必须设置以下隐藏的数据库参数:
_Unnested_subquery = false
不可见的子查询是升级到Oracle 11g时存在的许多性能问题的主要原因。
从Oracle 9i开始,Oracle会以一切可能的方式自动不需要子查询。 我们的大多数表都有非常好的索引来支持我们的SQL语句,而不需要它们。 通过设置_ unnest_subquery = true,Oracle被指示将该语句重写为不需要的版本。 此操作将增加优化程序在优化阶段期间必须评估的排列次数,从而使其运行更长时间。 对于在线SQL,此开销可能会非常高,因为大多数在线SQL语句只运行少于1到2秒。 升级到Oracle 11g时,由于OLTP事务的响应时间较长,大部分删除此设置的客户端都将其退回.
这是一份关于工资单的AWR报告的摘录
• With “ _Unnested_subquery = True”:
Statistic Name Time (s) % of DB Time
sql execute elapsed time 84,647.87 90.91
DB CPU 52,390.54 56.27
parse time elapsed 4,257.56 4.57
hard parse elapsed time 416.74 0.45
• With “_Unnested_subquery = false”:
Statistic Name Time (s) % of DB Time
sql execute elapsed time 67,820.20 93.27
DB CPU 34,192.87 47.03
parse time elapsed 296.17 0.41
hard parse elapsed time 15.56 0.02
我们建议您在生产过程中实施之前评估在测试环境中设置此参数的性能.
使用说明和SQL计划管理
对于需要将良好执行计划与不良SQL陈述相关联的客户,Oracle 11g提供了一种新的SQL计划管理方法。 此功能将允许用户在升级后更正回退的SQL语句,而无需修改原始语句。
这是它的工作原理:
1. 从AWR报告或PeopleSoft跟踪中捕获长时间运行的SQL。 从AWR报告或v $ sql视图获取sqlid。 如果您没有上述任何一种,那么只需通过SqlPlus运行原始的不良SQL。 查询v $ sql视图以获取SQL_ID.
2. 在v $ SQL视图中查找上述语句的SQL_ID:
3. 使用SQL_ID为上述SQL创建Sql计划基准:
检索SQL句柄和次优计划名称以在Dba_sql_plan_baselines中禁用计划:
4. 使用DBMS_SPM.ALTER_SQL_PLAN_BASELINE来禁用坏计划.
5. 验证坏计划是否被禁用.
6. 使用提示调整sql,直到满意性能:
7. 查找提示的sql语句的sql_id和plan_hash_value:
8. Create a new accepted plan for the original SQL statement by associating the SQL_ID and the PLAN_HASH_VALUE of the hinted SQL to the original SQL statement’s SQL_HANDLE retrieved in step 4
自动工作记录
Oracle 10g提供了一个名为Automatic Workload Repository(AWR)的自动数据库性能监控工具,替代了早期版本中的手动STATSPACK方法。 AWR每小时自动生成一次性能数据的快照(默认情况下),并收集工作负载存储库中的统计信息。 AWR收集的各种指标包括:
• 等待事件,如磁盘I / O等待,网络等待,锁定等待,提交等待等等。
• 会话历史详细信息,显示顶级SQL花费时间和资源。
• CPU,磁盘,网络和内存的操作系统指标.
此信息对于解决性能问题和查找过去任何时间点的数据库负载非常有用。 我们建议您使用默认频率保持此AWR运行。 快照的历史记录保留7天(默认情况下),并且在SYSAUX表空间中通常不占用超过300 MB。 如果系统平均有10个以上的并发会话,可能需要更多的空间。
数据库初始化参数“STATISTICS_LEVEL”必须设置为“TYPICAL”或“ALL”(默认为“TYPICAL”),参数“TIMED_STATISTICS”必须设置为“TRUE”才能使数据库正确填充工作负载存储库.
生成HTML或文本AWR报告
To generate an HTML or text AWR report:
1. 从SQL * Plus中运行awrrpt.sql脚本,并使用具有DBA角色的用户登录:
@$ORACLE_HOME/rdbms/admin/awrrpt.sql
2. 指定是否需要HTML或文本报告.
Enter value for report_type: html
3. 指定要列出的前几天的快照数.
Enter value for num_days: 2
4. 将显示显示生成快照的快照ID和时间的列表。 输入AWR记录的开始和结束快照ID.
Enter value for begin_snap : Enter value for end_snap:
5. 输入输出报告名称或接受默认名称:
Enter value for report_name:
Using the report name awrrpt_1_150_160
6. 将产生AWR报告.
如果您需要诊断特定的问题,则可以在执行可疑程序之前立即手动创建快照。 通常,这不是必需的。
此示例显示如何通过SQL * Plus手动创建快照:
BEGIN DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT (); END;
/
分析AWR报告
大多数情况下,数据库调优活动由用户抱怨交易或批处理作业的响应时间触发。 响应时间分析包括查找数据库中花费的时间。 数据库中给定事务的响应时间总是由以下两部分组成:
Response Time = Service Time + Wait Time
其中服务时间是数据库的CPU消耗量,等待时间是数据库中所有等待事件的总和。
AWR报告中最重要的部分是五大定时事件部分。 有了这个清单,您可以快速找出需要关注的主要领域。 当CPU使用率比等待时间更重要时,调查等待事件将不太可能在响应时间内节省大量成本。 因此,您应该比较前五个时间事件所花费的时间,并将调整工作引导到最大的消费者.
例子
Top 5 Timed Foreground Events
Event Waits Time(s) Avg wait (ms) % DB time Wait Class
DB CPU 22,510 90.86
db file sequential read 6,417,197 3,080 0 12.43 User I/O
direct path write temp 11,200 395 35 1.60 User I/O
log file sync 1,525 230 151 0.93 Commit
db file parallel read 234,899 208 1 0.84 User I/O
瞥一眼上面,系统CPU处理CPU占用了处理时间的90.86%。 要进一步了解CPU消耗的细节,需要查看“时间模型统计”部分。.
Time Model Statistics
Statistic Name Time (s) % of DB Time
DB CPU 22,510.23 90.86
sql execute elapsed time 18,771.27 75.77
parse time elapsed 274.29 1.11
hard parse elapsed time 1.82 0.01
PL/SQL execution elapsed time 1.23 0.00
hard parse (sharing criteria) elapsed time 0.03 0.00
repeated bind elapsed time 0.00 0.00
connection management call elapsed time 0.00 0.00
sequence load elapsed time 0.00 0.00
DB time 24,774.29
background elapsed time 1,683.75
background cpu time 458.17
如图所示,DB CPU总数的75.77%用于SQL执行时间。 查看有关问题SQL的SQL Statistics部分,例如具有高Gets,高物理读取,高解析等的SQL Statistics部分.
SQL STATISTICS
• SQL Ordered by Elapsed Time: 包括在处理过程中花费了大量执行时间的SQL语句.
• SQL Ordered by CPU Time: 包括在处理过程中消耗大量CPU时间的SQL语句.
• SQL Ordered by Gets: 这些SQL在检索数据时执行大量逻辑读取.
• SQL Ordered by Reads: 这些SQL在检索数据时执行了大量物理磁盘读取.
• SQL Ordered by Parse Calls: 这些SQL经历了大量的重新编译操作.
• SQL Ordered by Sharable Memory: 包括消耗大量SGA共享池内存的SQL语句游标.
• SQL Ordered by Version Count: 由于某些原因,这些SQL在共享池中有大量的版本.
要获取等待事件的详细信息,请转到“等待事件统计”部分.
Wait Class Waits %Time -outs Total Wait Time (s) Avg wait (ms) %DB time
DB CPU 22,510 90.86
User I/O 6,813,008 0 3,781 1 15.26
Commit 1,525 0 230 151 0.93
Network 69,369,222 0 59 0 0.24
Configuration 162 26 11 67 0.04
Concurrency 252,127 0 5 0 0.02
System I/O 281 0 0 0 0.00
Other 591 14 0 0 0.00
Application 448 0 0 0
以下是Oracle数据库中最常见的等待事件:
最常见的I / O相关等待事件是“db文件顺序读取”。它发生在通过索引访问的索引数据或表数据读取的单个块上。 如果此等待事件为高,则按如下进行调整:
1. 通过Reads部分排序的SQL查找具有Physical Reads的Top SQL语句。 生成SQL语句的解释计划.
a. 如果涉及到索引范围扫描,如果索引是非选择性的,则可能会访问比必要更多的块。 通过创建一个更有选择性的索引,我们可以访问较少的索引块(并减少物理I / O)来访问相同的表数据。
b. 如果索引是分段的,那么我们再次访问更多的块,因为每个块的索引数据较少。 在这种情况下,重建索引会将其内容压缩为更少的块。
c. 如果所使用的索引具有较大的聚类因子,则必须访问更多的表数据块,以获取每个索引块中的行。 通过重建表,其行按特定索引列排序,我们可以减少聚类因子,因此可以减少每个索引块必须访问的表数据块数。 例如,如果表有列A,B,C和D,并且索引在B,D上,那么我们可以按照B,D顺序导出表数据,并重新加载表.
2. 如果没有特定的SQL语句执行计划不正确,则可能会发生以下情况之一:
a. 特定数据文件上的I / O可能由于其磁盘上的过多活动而被缓慢服务。 在这种情况下,查看AWR报告的“文件I / O统计”部分将有助于找到这样的热盘,并通过手动将数据文件移动到其他存储或通过使用条带化,RAID和其他技术来自动扩展I / O 为我们执行I / O负载平衡.
3. 如果没有具有次优执行计划的SQL,并且I / O以相同的响应时间从所有磁盘均匀分布,则较大的缓冲区缓存可能有所帮助。 在Oracle Database 11g中,引入了自动内存管理(AMM)功能,通过使用两个名为MEMORY_MAX_TARGET和MEMORY_TARGET的新参数来自动确定PGA和SGA的自动调整大小。 有关AMM的更多详细信息,请参阅此Oracle支持说明443746.1.
另一个常见的I / O相关的等待事件是“db file scatter read”。 当从磁盘读取多块磁盘到缓冲区高速缓存中的非连续缓冲区时,会发生这种情况。 此类读取最多可以发送一次此参数DB_FILE_MULTIBLOCK_READ_COUNT指定的块数。 这些通常发生在全表扫描和快速全索引扫描。 如果此等待事件为高,则可以调查由Reads部分排序的SQL中具有Physical Reads的Top SQL语句,以查看其执行计划是否包含全表或快速完全索引扫描。 在需要进行多重扫描的情况下,可以通过将实例参数DB_FILE_MULTIBLOCK_READ_COUNT设置为如下来调整Oracle发布的多块I / O的大小::
DB_BLOCK_SIZE x DB_FILE_MULTIBLOCK_READ_COUNT = max_io_size of system
从Oracle10g Release 2开始,如果未明确设置此参数,则初始化参数DB_FILE_MULTIBLOCK_READ_COUNT现在将自动调整为使用默认值128。 该值与平台相关,对于大多数平台而言为1MB。 因为参数以块表示,所以它将被设置为等于可以有效地除以标准块大小的最大I / O大小的值。
另一个常见的I / O相关等待事件是“控制文件并行写入”“当Oracle将物理块写入所有控制文件并等待I / O完成时,会发生这种情况。 此等待的详细信息将在“后台等待事件”部分中报告。 如果系统范围等待这个等待事件是重要的,那么这表示对控制文件的许多写入(控制文件复制太多),或者写入控制文件的速度慢。 可能的解决方案可以:
• 将控制文件副本的数量减至最低,以确保不会同时丢失所有副本。
• 启用异步I / O或将控制文件移动到更快的磁盘.
另一个流行的等待事件是“日志文件同步”。 当用户会话发出COMMIT并等待LGWR完成从日志缓冲区中刷新所有重做到磁盘时,会发生这种情况。
要了解什么是延迟日志文件同步,需要检查一些其他等待事件,例如“LGWR等待重做复制”,“日志文件并行写入”,“日志文件单写”和重做统计信息。
这个等待事件的一些一般调整提示是:
• Move all the log members to high speed disks
• Move log members to low I/O activities disk controllers
从Oracle 10gR2开始,Oracle引入了一个异步提交。 在Oracle 11g中,异步提交由两个初始化参数COMMIT_LOGGING和COMMIT_WAIT控制,以更改提交行为。 当Oracle事务发生提交时,会发生三件事情:
1. Oracle将系统更改号码(SCN)分配给已提交的事务
2. 日志记录器(LGWR)将事务的重做信息从重做日志缓冲区写入磁盘上的重做日志文件及其SCN。
3. Oracle发布由事务持有的所有锁并将其标记为完整.
Commit的默认行为是使用IMMEDIATE进行COMMIT_LOGGING和等待COMMIT_WAIT.
▪ 立即与批次:IMMEDIATE选项告诉LGWR将提交事务的重做信息立即写入磁盘。 如果您希望LGWR缓冲重做信息,直到写入方便,您可以指定选项BATCH。
▪ 等待与否:WAIT选项指示LGWR等待重做信息成功写入磁盘,然后再将提交标记为已完成。 大多数等待日志文件同步事件是由这种等待引起的。 如果您不希望LGWR等待写入重做记录并将提交标记为已完成,则可以指定选项NOWAIT.
作为一般规则,CPU时间占主导地位的系统通常比等待时间占优势的系统要少。 另一方面,由于糟糕的Sql访问路径或严重写入的SQL可能导致CPU使用量过大,所以不应该忽略它。 在Oracle 11gR2中,我们看到“合并笛卡尔加入”或“哈希加入”,这可能是CPU使用率高的根本原因。.
此外,随着系统负载的增加,CPU时间等待时间的比例总是降低。 等待时间急剧增加是争议的征兆,需要解决良好的可扩展性。 需要一天中定期进行数据库工作的快照来检测这些性能问题.
这些Oracle Support参考说明可用于数据库调优:
注190124.1 COE绩效法
注意:443746.1本说明讨论了Oracle11g引入的自动内存管理(AMM)功能以及如何启用它
注223730.1自动PGA内存管理
说明30286.1具有不同RAID配置的I / O调优
说明30712.1 Init.ora参数“DB_FILE_MULTIBLOCK_READ_COUNT”参考说明
该脚本基于以下假设:PS临时表在PSRECDEFN中定义为具有rectype = 7,PS常规表定义为rectype = 0。它将为常规表和索引生成适当的update statistics命令, 跳过PS临时表和索引。 它可能需要更改和修改以满足您的需要.
SET SERVEROUTPUT ON SIZE UNLIMITED SET LINESIZE 1000
SET PAGESIZE 10000
/**
** Oracle USA, Inc.
** Date: 16-Jan-2007
**
** Format: SQL*Plus (10g) DBA script.
**
** Purpose:
** To generate statistics on all non-system schema table and index objects
** that are considered by the database to be stale and/or missing, while not
** generating statistics for PeopleSoft "temporary" tables and indexes.
**
** Please note:
** For this script to function properly, the executing user
** may need the DBA role. This script directly accesses:
** DBA_INDEXES
** DBMS_STATS
** All the table/index objects within all the schemas in the database.
**
** Other rights may also be needed.
**/
DECLARE
lot_ObjectsNeedingStats dbms_stats.objecttab; lts_StartTime TIMESTAMP(2);
lts_FinishTime TIMESTAMP(2);
lvc_tableowner VARCHAR2(30);
lvc_tablename VARCHAR2(30);
lvc_PSRecordName VARCHAR2(30);
lint_tmp NUMBER(2,0);
lb_IsTempTable BOOLEAN;
sql_stmt VARCHAR2(2000);
BEGIN
/**
** Delete Old Status Info here
**
** If an external table is used to hold the log
** of the executions, truncate it here.
**/
/**
** Flush Monitoring info
**
** This forces the database to "flush" the modification data
** so that dbms_stats can tell whether the stats are stale.
** Documentation says this is not needed. Doing it just in case.
**/ DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;
/**
** Find all tables and indexes that have stale stats
**/
DBMS_STATS.GATHER_DATABASE_STATS ( cascade => TRUE
,options => 'LIST AUTO'
,objlist => lot_ObjectsNeedingStats );
FOR i IN NVL( lot_ObjectsNeedingStats.first, 0 ) .. NVL( lot_ObjectsNeedingStats.last, 0 ) LOOP
/**
** Filter out all the system objects
**/
IF lot_ObjectsNeedingStats( i ).ownname NOT IN ( 'SYS'
,'SYSTEM'
,'SYSMAN'
,'CTXSYS'
,'DBSNMP' ) THEN
/**
** Non System object
**
** Determine whether this object is an "INDEX" or "TABLE"
**/
IF lot_ObjectsNeedingStats( i ).objtype = 'INDEX' THEN SELECT table_owner
,table_name INTO lvc_tableowner
,lvc_tablename FROM dba_indexes WHERE 1 = 1
AND owner = lot_ObjectsNeedingStats( i ).ownname AND index_name = lot_ObjectsNeedingStats( i ).objname;
ELSE
lvc_tableowner := lot_ObjectsNeedingStats( i ).ownname; lvc_tablename := lot_ObjectsNeedingStats( i ).objname;
END IF; /** Object Type checking **/
/**
** Trim off the default "PS_" from the table name if it exists
**/
IF SUBSTR( lvc_tablename, 1, 3 ) = 'PS_' THEN lvc_PSRecordName := SUBSTR( lvc_tablename, 4 );
ELSE
lvc_PSRecordName := lvc_tablename; END IF; /** Strip "PS_" **/
/** Set the temp table trap **/ lb_IsTempTable := FALSE;
/** rectype = 7 denotes a PeopleSoft temp table **/
sql_stmt := 'SELECT 1 FROM ' || lvc_tableowner || '.PSRECDEFN WHERE recname = :b1 and rectype = 7';
/**
** Check to see if the record
** is a base temp table.
**
** Example Table name = PS_TEMP_TAO
**/ BEGIN
EXECUTE IMMEDIATE sql_stmt INTO lint_tmp
USING lvc_PSRecordName;
-- If we make it here, we found a record lb_IsTempTable := TRUE;
EXCEPTION
AND '9' THEN
WHEN NO_DATA_FOUND THEN
/**
** Record was not a base temp table
**
** Check if record is a single digit temp instance
**
** Example Table name = PS_TEMP_TAO1
**/
IF SUBSTR( lvc_PSRecordName, LENGTH( lvc_PSRecordName ), 1 ) BETWEEN '0'
/** Remove the last digit **/
lvc_PSRecordName := SUBSTR( lvc_PSRecordName, 1, LENGTH(
lvc_PSRecordName ) - 1 );
/**
** Do the Check
**/ BEGIN
EXECUTE IMMEDIATE sql_stmt INTO lint_tmp
USING lvc_PSRecordName;
-- If we make it here, we found a record lb_IsTempTable := TRUE;
EXCEPTION
WHEN NO_DATA_FOUND THEN
/**
** Record was not a single digit temp instance.
**
** Check if record is a double digit temp instance
**
** Example Table name = PS_TEMP_TAO26
**/
IF SUBSTR( lvc_PSRecordName, LENGTH( lvc_PSRecordName ), 1 )
BETWEEN '1' AND '9' THEN
lvc_PSRecordName ) - 1 );
/** Remove the 2nd to last digit **/
lvc_PSRecordName := SUBSTR( lvc_PSRecordName, 1, LENGTH(
/**
** Do the Check
**/ BEGIN
EXECUTE IMMEDIATE sql_stmt INTO lint_tmp
USING lvc_PSRecordName;
-- If we make it here, we found a record lb_IsTempTable := TRUE;
EXCEPTION
WHEN NO_DATA_FOUND THEN
-- We have not found a temp table! NULL;
WHEN OTHERS THEN RAISE;
END; /** 2 digit dedicated temp table Check **/ END IF; /** Check 2nd last char for digit **/
WHEN OTHERS THEN RAISE;
END; /** single digit dedicated temp table Check **/ END IF; /** Checking last digit **/
WHEN OTHERS THEN
IF SQLCODE = -942 THEN /** table or view does not exist **/
/** Non PeopleSoft Table/Index found.
** Treat as though it was not a temp table.
** Generate Stats
**/
NULL;
ELSE
/** Unexpected error **/ RAISE;
END IF;
END; /** base temp table check**/
IF lb_IsTempTable = FALSE THEN lts_StartTime := SYSTIMESTAMP;
dbms_output.put_line( 'Generating stats on ' || LOWER( lot_ObjectsNeedingStats( i ).objtype ) || ' ' || lot_ObjectsNeedingStats( i ).ownname || '.'
|| lot_ObjectsNeedingStats( i ).objname || '.' );
IF lot_ObjectsNeedingStats( i ).objtype = 'INDEX' THEN
/*
PROCEDURE GATHER_INDEX_STATS
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ -------- OWNNAME VARCHAR2 IN
INDNAME VARCHAR2 IN
PARTNAME VARCHAR2 IN DEFAULT
ESTIMATE_PERCENT NUMBER IN DEFAULT
STATTAB VARCHAR2 IN DEFAULT
STATID VARCHAR2 IN DEFAULT
STATOWN VARCHAR2 IN DEFAULT
DEGREE NUMBER IN DEFAULT
GRANULARITY VARCHAR2 IN DEFAULT
NO_INVALIDATE BOOLEAN IN DEFAULT
STATTYPE VARCHAR2 IN DEFAULT
FORCE BOOLEAN IN DEFAULT
*/
EXECUTE IMMEDIATE '
BEGIN
DBMS_STATS.GATHER_INDEX_STATS(
ownname => ''' || lot_ObjectsNeedingStats( i ).ownname || '''
,indname => ''' || lot_ObjectsNeedingStats( i ).objname || '''
,partname => ''' || lot_ObjectsNeedingStats( i ).partname || '''
,estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE
,degree => DBMS_STATS.AUTO_DEGREE
); END;
';
ELSE
/*
PROCEDURE GATHER_TABLE_STATS
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ -------- OWNNAME VARCHAR2 IN
TABNAME VARCHAR2 IN
PARTNAME VARCHAR2 IN DEFAULT
ESTIMATE_PERCENT NUMBER IN DEFAULT
BLOCK_SAMPLE BOOLEAN IN DEFAULT
METHOD_OPT VARCHAR2 IN DEFAULT
DEGREE NUMBER IN DEFAULT
GRANULARITY VARCHAR2 IN DEFAULT
CASCADE BOOLEAN IN DEFAULT
STATTAB VARCHAR2 IN DEFAULT
STATID VARCHAR2 IN DEFAULT
STATOWN VARCHAR2 IN DEFAULT
NO_INVALIDATE BOOLEAN IN DEFAULT
STATTYPE VARCHAR2 IN DEFAULT
FORCE BOOLEAN IN DEFAULT
*/
EXECUTE IMMEDIATE '
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(
ownname => ''' || lot_ObjectsNeedingStats( i ).ownname || '''
,tabname => ''' || lot_ObjectsNeedingStats( i ).objname || '''
,partname => ''' || lot_ObjectsNeedingStats( i ).partname || '''
,estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE
,block_sample => FALSE
,method_opt => ''FOR ALL COLUMNS SIZE AUTO''
,degree => DBMS_STATS.AUTO_DEGREE
,cascade => FALSE
); END;
'; END IF;
lts_FinishTime := SYSTIMESTAMP;
/**
** Create status string here.
**
** If so inclined.
**/
ELSE
dbms_output.put_line( 'NOT Generating stats on temp ' || LOWER( lot_ObjectsNeedingStats( i ).objtype ) || ' ' || lot_ObjectsNeedingStats( i ).ownname || '.'
|| lot_ObjectsNeedingStats( i ).objname || '.' ); END IF; /** Gen Stats **/
/**
** Insert status info
**
** If so inclined
**
END;
/
COMMIT;
**/
END IF; /** System object filter **/ END LOOP; /** Object stale stats loop **/