何时在 Unix 上使用 Oracle 数据库

Web 应用程序的高性能取决于能够快速处理请求和非常高效地抓取查询结果的数据库。本文将介绍如何分析 Oracle 等待事件,以便提高性能。文中还会介绍如何使用操作系统实用程序,有效地收集 Oracle 数据库的性能统计数据,并通过分析它们来识别问题。

监视数据库性能和分析等待事件

要提高 Oracle 数据库的性能,需要分析 Oracle 等待事件,发掘可帮助识别瓶颈和调优数据库设置的线索。在提高 Oralce 数据库处理效率的同时,也会提高依赖于该数据库的所有系统和软件的性能。本文将介绍如何使用普通的操作系统实用程序来有效地收集 Oracle 数据库的性能统计数据,并通过分析它们来识别问题。

一些因素会影响 Oracle 数据库性能。具体地讲,以下因素会显著影响性能。

低效的 SQL 语句会影响性能

在构造 SQL 语句时请留心,因为它们可能给查询性能带来重大影响。语句越具体,就能越快地得到结果。例如,假设您需要查看 employee 表中一位具有 employee_id 123 的特定员工 employee1 的详细信息。employee 表包含 employee_name、 employee_sal 和employee_id,其中 employee_id 是主键。您可以使用以下选项之一,这些选项按最低效到最高效的顺序列出。

· 使用查询 select * from employee 抓取该表中的所有记录。从结果中寻找特定的员工。如果查询结果包含许多记录,那么这将是一个缓慢的过程。

· 使用查询 select * from employee where employee_name='employee1'。where 子句缩小了搜索范围,让该过程更快结束。

· 使用查询 select * from employee where employee_id=123。因为 employee_id 是主键,所以此查询是最快的选项。

要构造能最有效地增强性能的 SQL 语句,可以应用以下最佳实践:

· 避免不包含 where 条件和主键的查询。

· 大量的删除语句会导致非连续数据块不断增加。一个删除语句仅清除一个数据块中的数据,但不会让该数据块变得可供使用。因为删除语句不会降低上限,所以它们不会减少必须在未来的查询中搜索的数据的总数据量。尽可能地使用截断功能(truncate),因为它会重设上限。

· 仅在必要时使用 COMMIT 语句。避免频繁地使用该语句,因为它们会启动缓冲区清除,这可能导致过量的 I/O 处理。

低效的数据库配置会影响性能

没有经过精心配置的数据库可能影响数据库性能。特定的数据库初始化参数和配置参数不仅会影响启动配置,还会影响请求的处理。如果为针对最高效的处理而配置以下参数,那么它们可能会影响性能。

PCTFREE 参数

PCTFREE 参数设置了一个数据块中要保留作为空闲空间的最低比例,利用该比例寻找可能已存在的行的更新。太低的 PCTFREE 值可能在更新期间引起问题。太高的值可能造成空间浪费,导致更大型、不必要的数据块移动。

PCTUSED 参数

PCTUSED 参数设置在向数据块添加新行之前,该数据块中将用于行数据和开销的最低比例。一个数据块的填充率达到 PCTFREE 确定的限制后,Oracle 会将该数据块视为无法插入新行,直到该数据块的这一比例下降到 PCTUSED 参数上设置的值以下。在达到这个阈值之前,Oracle 仅将数据块的空闲空间用于更新该数据块中已包含的行。

系统全局区域 (System Global Area, SGA) 内存不足会影响性能

系统全局区域 (SGA) 是一组共享内存结构,这些结构包含一个 Oracle 数据库实例的数据和控制信息。如果多个用户同时连接到同一个实例,该实例的 SGA 中的数据会在用户之间共享。因此,SGA 有时称为共享全局区域。为了确保高效的数据库性能,需要确定 SGA 需要的最优内存并适当地配置它。内存太少可能显著降低数据库性能。

等待事件会影响性能

等待事件是在需要处理一个请求时,数据库操作期间可能发生的事件。在发送一个读取/写入 Oracle 数据库的请求时,该请求会调用多个进程。这些进程可能遇到会终止或延迟处理的硬件、软件、操作系统或配置问题。这些阻碍因素都被称为等待事件。一个数据库要有效执行,必需保持等待子句尽可能少。分析在一个操作期间发生的所有等待子句,如果等待期限太长,则修复它们。但是,无法完全消除所有等待事件。

Oracle Database 11g 有 1000 多个等待事件,这可能导致请求处理的延迟。这些等待事件大体划分为:

· 集群

· 网络

· 管理

· 配置

· 提交

· 应用程序

· 并发性

· 系统 I/O

· 用户 I/O

· CPU

使用 Oracle Enterprise Manager 分析等待事件

使用 Oracle Enterprise Manager (OEM) 监视一个数据进程中的等待事件。OEM 采用图形的形式显示一个进程执行期间的数据库状态。它还提供一个详细的分析视图,您可从中下钻到每个事件并查找关联的 SQL 语句,如图 1 所示。右侧的图例显示了正发生的等待事件的类型。

图 1. 来自 Oracle Enterprise Manager 的示例屏幕截图

如何监视性能和分析等待事件_数据库

点击查看大图

(docs.oracle.com 于 2011 年发布的原始图像:http://docs.oracle.com/cd/E11857_01/em.111/e11982/database_management.htm)

图 2 给出了来自图 1 中使用的数据的用户 I/O 等待类的详细视图。单击 OEM 中的 User I/O,查看导致用户 I/O 类型的等待的等待时间的细节页面。

图 2. 正在发生的会话等待

 

点击查看大图

(docs.oracle.com 于 2011 年发布的原始图像:http://docs.oracle.com/cd/E11857_01/em.111/e11982/database_management.htm)

使用 shell 脚本分析等待事件

如果不想使用工具来采集数据,可以使用 shell 脚本和原生的操作系统实用程序,从 Oracle 数据库收集等待事件统计数据。使用以下步骤收集统计数据,通过分析它们来了解瓶颈来源,并借助数据库管理员来修复问题。

准备数据

准备足够的数据,使数据库足够运行几个小时或一整晚。检测一些问题(比如缓存问题)通常需要较长的时间,这些问题可能不会在数据库操作的最初几小时内发生。一定要给数据库增加负担,以模仿生产负载。确保您拥有有效的数据组合,使查询结果包含实时、插入、更新、删除和截断操作。每种数据操作语言 (DML) 语法元素的资源使用情况各不相同;因此,需要尽力让数据集与在生产环境中收到的数据相同或接近。

第 1 步. 创建脚本

要从 V$ACTIVE_SESSION_HISTORY, V$EVENT_NAME, V$SQLAREA 视图获取等待事件的细节和 SQL 语句,可以在 3 个表上创建一个简单的 joinc 操作。

V$ACTIVE_SESSION_HISTORY

显示数据库中采样的会话活动。它包含每秒采集一次的活动数据库会话快照。

V$EVENT_NAME

显示等待事件的信息。

V$SQLAREA

列出共享 SQL 区域的统计数据,包含每个 SQL 字符串一行。它提供在内存中、已解析和准备好运行的 SQL 语句的统计数据。

因为这些视图中的数据会定期清除,所以可以使用清单 1 中所示的脚本来定期收集数据。

清单 1. 定期收集数据的 gather_event_stats.sh 脚本

#!/bin/sh

echo "Collecting the wait events statistics $1 times at an interval of $2"

# Creating the time stamps in Oracle acceptable format

curr_date=`date '+%d-%b-%y' | tr '[:lower:]' '[:upper:}'

curr_time=`date +%H.%M.%S`

start_time="$curr_date $curr_time"

outfile_name=Events_output_$curr_date $curr_time

# sleeping for given interval of time

sleep $2

# Running the iterations until given number of times

for((i=1;i<=$1;i++))

do

curr_date=`date '+%d-%b-%y' | tr '[:lower:]' '[:upper:}'

curr_time=`date +%H.%M.%S`

end_time="$curr_date $curr_time"

# Dynamically building the sql file to get the data in required format.

echo "">sql

echo "SET HEADING OFF;">>sql 2>/dev/null

echo "SET FEEDBACK OFF;">>sql 2>/dev/null

echo "SET PAGESIZE 0;">>sql 2>/dev/null

echo "SET LINESIZE 1500;">>sql 2>/dev/null

echo "SET ECHO OFF;">>sql 2>/dev/null

echo "SET VERIFY OFF;">>sql 2>/dev/null

echo "SET MARKUP HTML OFF;">>sql 2>/dev/null

# Set the column separator for each field to " ~ "

echo "SET CLOSEP '~';">>sql 2>/dev/null

# Build a query joining all 3 tables to get wait event, wait time and SQLID.

echo "SELECT TRIM(A.SAMPLE_TIME),TRIM(C.SQL_TEXT),TRIM(B.NAME),COUNT(*),

SUM(TIME_WAITED) FROM v\$ACTIVE_SESSION_HISTORY A,v\$EVENT_NAME B,

v\$SQLAREA C WHERE to_char(A.SAMPLE_TIME, 'DD-MON-YY HH24.MI.SS')BETWEEN '"$start_time",

AND '"$end_time"' AND A.EVENT=B.NAME AND A.SQL_ID = C.SQL_ID GROUP BY A.SAMPLE_TIME,

C.SQL_TEXT, B.NAME ORDER BE 1 ASC:" >>SQL

#Connecting to Oracle using sqlplus and executing the sql file. Appending the results to a filesqlplus ORACLEID/PASSWORD@ORADBNAME< sql >> $outfile_name

2>/dev/null

# Sleeping for $2 number of minutes/hours/days

sleep $2

start_time="$end_time"

# Clearing the sql file to build a fresh query with changed time stamps.

echo "">sql

done

波浪符号 (~) 用作列分隔符,让收集到文件中的数据可以使用电子表格应用程序(比如 Microsoft Excel)来进行解析,以便进一步分析它们。此脚本定期创建一个 SQL 文件,执行该 SQL 来从视图收集数据,将统计数据收集到文件 $outfile_name 中。

第 2 步. 启动脚本

将该脚本放在任何应用服务器上,运行该脚本来收集数据。在以下代码中,调用该脚本之前替换变量 ORADBNAME ORACLEID PASSWORD。

sqlplus ORACLEID/PASSWORD@ORADBNAME< sql >> $outfile_name 2>/dev/null

备注:也可以参数化这些值,在运行时将它们传递给脚本。

使用以下语法运行该脚本:

gather_event_stats.sh <No.of.Iterations> <Time Interval in m(in)/h(ours)/d(ays)>

gather_event_stats.sh 5 2h ---> would run for 10 hrs (5times*for every 2hours = 10Hrs)

在数据加载之前启动此脚本,在加载完成之前不要结束它。运行该脚本时精心选择 No.Of.Iterations ($1) 和 Interval ($2),以便 No.Of.Iterations x Intervals = Test Duration。

要确保该脚本已启动,可以运行以下命令:

ps -eaf | grep "gather_event_stats.sh"

第 3 步. 处理数据

注入数据,确保应用程序正在处理该数据。反复检查,确保数据已加载到数据库中。等待所有数据都已处理。定期列出 $outfile_name(接收来自查询的输出的文件名,在本例中输出为等待事件的统计数据),确保文件的大小在不断增加。

ls -ltr <$outfile_name>

第 4 步. 分析数据并调优数据库

1. 数据处理完成且 gather_event_stats.sh 脚本运行结束后,从 Unix 机器将输出文件 $outfile_name 下载到 Windows 机器。

2. 在文本编辑器中打开该文件。如果原始数据文件中存在任何制表符位置或额外的空白空间,那么应该首先将它们替换为单个空格,然后再在一个 Excel 电子表格中解析它们。图 3 显示了在记事本中显示的已下载数据的示例。

图 3. 收集到一个文件中的原始数据的屏幕截图

 

1. 单击 Data > Convert Text to Columns,将数据导入到一个 Excel 电子表格。使用波浪符号 (~) 作为分隔符,将数据拆分为不同的列,如图 4 所示。

图 4. 在 Excel 中使用分隔符 ~ 拆分后的等待事件数据的屏幕截图

 

点击查看大图

1. 依据该数据绘制一个数据透视图,以获取等待每个事件的时间总和。时间单位为 1 秒的 1/100;因此,将它除以 100 以将该值转换为秒。完成数据透视图后,对数据透视表排序,以获得等待时间最长的事件,如图 5 所示。

图 5. 数据透视图表的屏幕截图

如何监视性能和分析等待事件_sql_02

点击查看大图

1. 借助 Oracle 数据库管理员来分析等待事件,以便了解事件的根源。在此示例中,TX - index contention 是具有最长等待时间的事件。此情形表明,事务处理期间的索引存在问题。

2. 获取具有最长等待时间的子句的 SQLID,检查相应的 SQL 语句。C.SQL_TEXT 字段表示每个 SQLID 的 SQL 语句。咨询开发人员和数据库管理员,确定这些 SQL 语句能否通过调优来减少等待时间。

3. 对等待时间最长的 10 个活动中的每一个重复第 6 步。

4. 实现开发人员和管理员建议的解决方案,消除等待事件。

5. 使用相同的数据负载,重新运行同一个测试相同时间,确保等待时间已减少,或者完全消除等待事件。

回页首

结束语

本文解释了一种收集一个 Oracle 数据库的数据库等待事件统计数据的方式。该过程很简单,不需要特殊的工具。对于与 Oracle 后端数据库集成的 IBM 产品,可以采用此方法来分析数据库的性能问题并解决这些问题。

http://www.ibm.com/developerworks/cn/rational/performance-oracle-unix/