小记:不明原因的解决了ORACLE慢的问题
小记:不明原因的解决了ORACLE慢的问题
近来发现ORACLE服务器超级慢,而且慢并不是由应用程序性能导致的,就连运行proc预编译程序都很慢,可见问题还是出在ORACLE服务器
本身。
首先查看了一下ORACLE的主要内存参数:
除了大池(large_pool_size)为16MB以外,每项内存都配置得不小。
于是怀疑是共享池满造成的,在网上找了篇文章查了查共享池的占用情况:
《如何计算oracle共享池的大小》 http://blog.sina.com.cn/s/blog_3ebdf8ad010006bk.html
执行了一下,共享池竟然占用了113%。居然溢出了!!!搞不懂!
于是尝试着修改参数:
1.在linux下:su - oracle
2. sqlplus "/as sysdba"
3. CREATE PFILE='ahfu.ora' FROM SPFILE;
4. 在LINUX下:cd /oracle/ora9/product/9.2/dbs/
5. vi ahfu.ora
6. 修改参数如下:
db_cache_size (数据缓存) 256MB -> 512MB
java_pool_size (java池) 84MB -> 0MB
large_pool_size (大池) 16MB -> 64MB
query_rewrite_enabled (查询重写) FALSE -> TRUE
7. 保存,关闭数据库:shutdown immediate;
8. 从新的pfile启动:startup pfile='/oracle/ora9/product/9.2/dbs/ahfu.ora';
9. 重新连接数据库,发现连接和查询都变得很快了。反复重启数据库多次,仍然很快。
猜测一方面是因为共享池满导致了数据库慢,另一方面是大池设置得过小。但是重启后变快并不能说明真正解决了问题,要多运行一段时间
才知道。
====================================================
附1:对共享池的分析
共享池缓存了系统中执行过的SQL。如果出现大量的不同的SQL,就可能导致共享池满。共享池满后,每次执行SQL都会扫描共享池,寻找相
同的SQL,找不到后又扫描整个共享池将长时间为执行的SQL设置为过期,为新的SQL分配空间。因此,哪怕是很简单的SQL,每次执行都会反复
扫描共享池,使得整个系统都很慢。共享池满的问题并不是立即发生的,需要一定的积累过程。所以数据库刚刚启动的时候,共享池是空的,
执行总是很快。数据库运行一段时间后,共享池满了,才会发现数据库很慢。大量不同的SQL会导致共享池问题:
比如:select user_name from webuser.user_info where user_id=:UserID;
与select user_name from webuser.user_info where user_id=1
上面两条SQL语句,第一条使用参数绑定,在共享池中会多次被命中,性能很高;而第二条,参数采用常量,很难被命中,每次都要重新解
析,并且会占用共享池的空间。
附2:对查询重写的分析
查询重写功能是指数据库引擎强制将所有SQL中的参数修改成参数绑定的格式。
例如,数据库强制将select user_name from webuser.user_info where user_id=1这条SQL
强制修改成select user_name from webuser.user_info where user_id=:UserID
查询重写能够有效避免共享池满的问题,但是会增加SQL的解析时间。
近来发现ORACLE服务器超级慢,而且慢并不是由应用程序性能导致的,就连运行proc预编译程序都很慢,可见问题还是出在ORACLE服务器
本身。
首先查看了一下ORACLE的主要内存参数:
SELECT "NUM","NAME","TYPE","VALUE"/1024 AS "KB",
"ISDEFAULT","ISSES_MODIFIABLE","ISSYS_MODIFIABLE",
"ISMODIFIED","ISADJUSTED","DESCRIPTION","UPDATE_COMMENT"
FROM v$parameter
WHERE NAME IN ('db_block_size', 'db_cache_size',
'java_pool_size', 'large_pool_size', 'pga_aggregate_target',
'shared_pool_size', 'sort_area_size')
"ISDEFAULT","ISSES_MODIFIABLE","ISSYS_MODIFIABLE",
"ISMODIFIED","ISADJUSTED","DESCRIPTION","UPDATE_COMMENT"
FROM v$parameter
WHERE NAME IN ('db_block_size', 'db_cache_size',
'java_pool_size', 'large_pool_size', 'pga_aggregate_target',
'shared_pool_size', 'sort_area_size')
除了大池(large_pool_size)为16MB以外,每项内存都配置得不小。
于是怀疑是共享池满造成的,在网上找了篇文章查了查共享池的占用情况:
《如何计算oracle共享池的大小》 http://blog.sina.com.cn/s/blog_3ebdf8ad010006bk.html
执行了一下,共享池竟然占用了113%。居然溢出了!!!搞不懂!
于是尝试着修改参数:
1.在linux下:su - oracle
2. sqlplus "/as sysdba"
3. CREATE PFILE='ahfu.ora' FROM SPFILE;
4. 在LINUX下:cd /oracle/ora9/product/9.2/dbs/
5. vi ahfu.ora
6. 修改参数如下:
db_cache_size (数据缓存) 256MB -> 512MB
java_pool_size (java池) 84MB -> 0MB
large_pool_size (大池) 16MB -> 64MB
query_rewrite_enabled (查询重写) FALSE -> TRUE
7. 保存,关闭数据库:shutdown immediate;
8. 从新的pfile启动:startup pfile='/oracle/ora9/product/9.2/dbs/ahfu.ora';
9. 重新连接数据库,发现连接和查询都变得很快了。反复重启数据库多次,仍然很快。
猜测一方面是因为共享池满导致了数据库慢,另一方面是大池设置得过小。但是重启后变快并不能说明真正解决了问题,要多运行一段时间
才知道。
====================================================
附1:对共享池的分析
共享池缓存了系统中执行过的SQL。如果出现大量的不同的SQL,就可能导致共享池满。共享池满后,每次执行SQL都会扫描共享池,寻找相
同的SQL,找不到后又扫描整个共享池将长时间为执行的SQL设置为过期,为新的SQL分配空间。因此,哪怕是很简单的SQL,每次执行都会反复
扫描共享池,使得整个系统都很慢。共享池满的问题并不是立即发生的,需要一定的积累过程。所以数据库刚刚启动的时候,共享池是空的,
执行总是很快。数据库运行一段时间后,共享池满了,才会发现数据库很慢。大量不同的SQL会导致共享池问题:
比如:select user_name from webuser.user_info where user_id=:UserID;
与select user_name from webuser.user_info where user_id=1
上面两条SQL语句,第一条使用参数绑定,在共享池中会多次被命中,性能很高;而第二条,参数采用常量,很难被命中,每次都要重新解
析,并且会占用共享池的空间。
附2:对查询重写的分析
查询重写功能是指数据库引擎强制将所有SQL中的参数修改成参数绑定的格式。
例如,数据库强制将select user_name from webuser.user_info where user_id=1这条SQL
强制修改成select user_name from webuser.user_info where user_id=:UserID
查询重写能够有效避免共享池满的问题,但是会增加SQL的解析时间。