afc_db优化

针对SC参数入库导致的数据库查询缓慢问题,通过调整SGA_MAX_SIZE、SGA_TARGET参数及设置磁盘IO模式为DIRECTIO,成功将入库时间从20分钟缩短至2分钟,实现10倍性能提升。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

现象:

SC参数入库时,造成SCWS连接数据库查询数据缓慢,同时通过PLSQL登陆明显变慢,参数入库需要20分钟左右

分析:

SQL级分析
表空间大小、表索引、插入时SGA使用率,临时空间占用率
Hint:append 归档情况下,与普通insert产出同样的redo;非归档下,产生redo比普通insert少。
由于系统一直运行,并未在此方面做过更改,所以问题可能不在此方面。
SGA\PGA分析
高速缓冲区命中率,经过查询命中率在90%以上,没有问题。

1
2
3
selectname,valuefromv$sysstat
wherenamein(‘consistentgets’,'dbblockgets’,'physicalreads’);
select1-(physicalreads/(consistentgets+dbblockgets))fromdual;

如果命中率低于70%,则应该加大INITsid.ORA文件中的DB_BLOCK_BUFFERS(Oracle9i 参数名称为DB_CACHE_SIZE)参数值
磁盘数据写入分析
经检查,系统硬盘单文件写入可达10MB/s,使用率为37%(通过FTP上传100MB以上文件测试,通过iostat -xn 3监控)
但是当通过数据库,调用insert插入10W条以上数据时,磁盘写入大约为1MB/s,使用率100%,磁盘写入率低。
通过上述描述,排除磁盘问题,问题可能出在oracle进程往磁盘写入数据的途中,通过以下脚本测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
setserveroutputon;
DECLARE
latINTEGER;
iopsINTEGER;
mbpsINTEGER;
BEGIN
–DBMS_RESOURCE_MANAGER.CALIBRATE_IO(disk_count,max_latency,iops,mbps,lat);
DBMS_RESOURCE_MANAGER.CALIBRATE_IO(2,10,iops,mbps,lat);
DBMS_OUTPUT.PUT_LINE(‘max_iops=‘||iops);
DBMS_OUTPUT.PUT_LINE(‘latency=‘||lat);
dbms_output.put_line(‘max_mbps=‘||mbps);
end;
/
max_iops = 22886
latency = 0
max_mbps = 144

如何确保系统使用的是异步I/O呢?进行如下的查询操作就可以了:

1
2
3
4
5
6
7
8
9
10
11
12
13
SQL>COLNAMEFORMATA50
SQL>SELECTNAME,ASYNCH_IOFROMV$DATAFILEF,V$IOSTAT_FILEI
WHEREF.FILE#=I.FILE_NO
ANDFILETYPE_NAME=’DataFile’;/
NAMEASYNCH_IO
————————————————–———
+DATA/orcl/datafile/system.256.768274859ASYNC_ON
+DATA/orcl/datafile/sysaux.257.768274861ASYNC_ON
+DATA/orcl/datafile/undotbs1.258.768274861ASYNC_ON
+DATA/orcl/datafile/users.259.768274861ASYNC_ON
+DATA/orcl/datafile/example.267.768275071ASYNC_ON
+DATA/orcl/datafile/undotbs2.268.768275613ASYNC_ON
6rowsselected.

redo log大小对一次大数据量提交的影响

解决方案:

redo log 4组,每组两个文件,文件大小512MB
ps -ef|grep ora_ 查看ora_dbw0的PID
通过TOP命令查看相应PID的CPU使用率
使用IOSTAT工具检查IO状况 iostat -xn 3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
SQL>shutdownimmediate
Databaseclosed.
Databasedismounted.
ORACLEinstanceshutdown.
SQL>startuppfile=’/app/oracle/product/server_ee/11.2.0.3/dbs/initAFC010C1.ora’
ORACLEinstancestarted.
TotalSystemGlobalArea2137886720bytes
FixedSize2227704bytes
VariableSize1627390472bytes
DatabaseBuffers503316480bytes
RedoBuffers4952064bytes
Databasemounted.
Databaseopened.
SQL>selectstatusfromv$instance;
STATUS
————
OPEN
SQL>showparametersga
NAMETYPEVALUE
——————————————————————–
lock_sgabooleanFALSE
pre_page_sgabooleanTRUE
sga_max_sizebiginteger2G
sga_targetbiginteger768M
SQL>altersystemsetsga_target=2048M;
Systemaltered.
SQL>createspfilefrompfile;
Filecreated.
SQL>

 

增大SGA_MAX_SIZE由768M至2048M,SGA_TARGET由768M至2048M。
磁盘写入增加了大概100KB/s。
设置使用磁盘IO模式,默认oracle IO数据文件存储方式为ASYNCH_IO,修改为以下

1
altersystemsetsystemfileio_options=‘DIRECTIO’scope=spfile;

经测试,SC参数入库由20分钟缩减至2分钟,10倍提升。

``` @echo off setlocal enabledelayedexpansion REM 刷新文件时间戳 forfiles /p "D:\Akaoqin" /m "card_number.txt" /c "cmd /c echo @FILE" REM 创建日志文件 set "LOG_FILE=export_log.txt" echo [%date% %time%] [INFO] 导出开始 > %LOG_FILE% REM 配置参数 set "OUTPUT_DIR=D:\Akaoqin\export_script\output_csv" set "CARD_FILE=D:\Akaoqin\card_number.txt" set "ORACLE_USER=lc30db" set "ORACLE_PASSWORD=lc30db" set "ORACLE_DB=172.1.200.221:1521/afc" REM 检查必要文件是否存在 if not exist "%CARD_FILE%" ( echo [%date% %time%] [ERROR] 卡号文件 %CARD_FILE% 不存在! >> %LOG_FILE% echo 错误:卡号文件不存在,按任意键退出... pause exit /b 1 ) REM 创建输出目录 if not exist "%OUTPUT_DIR%" ( mkdir "%OUTPUT_DIR%" 2>> %LOG_FILE% || ( echo [%date% %time%] [ERROR] 无法创建目录 %OUTPUT_DIR% >> %LOG_FILE% echo 错误:创建输出目录失败,按任意键退出... pause exit /b 1 ) ) REM 数据库连接测试 echo [%date% %time%] [INFO] 正在测试数据库连接... >> %LOG_FILE% ( echo WHENEVER SQLERROR EXIT SQL.SQLCODE; echo SELECT 1 FROM DUAL; echo EXIT; ) > temp_query.sql sqlplus -L %ORACLE_USER%/%ORACLE_PASSWORD%@%ORACLE_DB% @temp_query.sql >> %LOG_FILE% 2>&1 set "SQLPLUS_ERRORLEVEL=%ERRORLEVEL%" del temp_query.sql if not "%SQLPLUS_ERRORLEVEL%"=="0" ( echo [%date% %time%] [ERROR] 数据库连接测试失败,错误代码: %SQLPLUS_ERRORLEVEL% >> %LOG_FILE% echo 错误:数据库连接失败,请检查连接参数... pause exit /b 1 ) REM 遍历卡号文件 for /f "usebackq delims=" %%a in ("%CARD_FILE%") do ( set "CARD=%%a" set "CARD=!CARD:'='''!" REM 转义单引号 if not "!CARD!"=="" ( echo [%date% %time%] [INFO] 正在处理卡号: !CARD! >> %LOG_FILE% REM 清理卡号中的非法字符 set "SAFE_CARD=!CARD:/=_!" set "SAFE_CARD=!SAFE_CARD:?=_!" set "SAFE_CARD=!SAFE_CARD: =_!" set "SAFE_CARD=!SAFE_CARD:*=!" set "SAFE_CARD=!SAFE_CARD:<=!" set "SAFE_CARD=!SAFE_CARD:>=!" set "SAFE_CARD=!SAFE_CARD::=!" set "SAFE_CARD=!SAFE_CARD:\=!" echo [%date% %time%] [INFO] 安全卡号: !SAFE_CARD! >> %LOG_FILE% REM 生成临时 SQL 脚本 ( echo SET PAGESIZE 0 echo SET FEEDBACK OFF echo SET HEADING ON echo SET COLSEP "," echo WHENEVER SQLERROR EXIT SQL.SQLCODE; echo SPOOL "%OUTPUT_DIR%\!SAFE_CARD!.csv" echo SELECT t.card_sn AS 卡号, s.station_cn_name AS 车站, t.tran_date AS 日期, t.tran_time AS 时间 echo FROM data_ykt_tran t, basi_station_info s echo WHERE t.card_sn='!CARD!' echo AND t.tran_date BETWEEN '20250301' AND '20250315‘ echo AND t.station_id = s.station_id echo ORDER BY t.tran_date; echo SPOOL OFF echo EXIT ) > tmp_query.sql 2>> %LOG_FILE% REM 检查临时脚本是否生成 if not exist "tmp_query.sql" ( echo [%date% %time%] [ERROR] 无法生成 tmp_query.sql >> %LOG_FILE% goto :NEXT_CARD ) REM 执行 SQL*Plus echo [%date% %time%] [INFO] 正在执行 SQL*Plus 查询... >> %LOG_FILE% sqlplus -L %ORACLE_USER%/%ORACLE_PASSWORD%@%ORACLE_DB% @tmp_query.sql >> %LOG_FILE% 2>&1 set "SQLPLUS_ERRORLEVEL=%ERRORLEVEL%" if not "!SQLPLUS_ERRORLEVEL!"=="0" ( echo [%date% %time%] [ERROR] SQL*Plus 执行失败,错误代码: !SQLPLUS_ERRORLEVEL! >> %LOG_FILE% ) REM 检查导出结果 if exist "%OUTPUT_DIR%\!SAFE_CARD!.csv" ( REM 检查文件是否为空 for %%F in ("%OUTPUT_DIR%\!SAFE_CARD!.csv") do ( if %%~zF EQU 0 ( echo [%date% %time%] [WARN] 文件为空: !SAFE_CARD!.csv >> %LOG_FILE% ) else ( echo [%date% %time%] [INFO] 导出成功: !SAFE_CARD!.csv >> %LOG_FILE% ) ) ) else ( echo [%date% %time%] [WARN] 卡号 !CARD! 导出失败 >> %LOG_FILE% ) :NEXT_CARD del /q tmp_query.sql >nul 2>&1 ) ) echo [%date% %time%] [INFO] 导出完成 >> %LOG_FILE% echo 操作已完成,请查看日志文件 %LOG_FILE% pause exit /b 0```能给我优化后的完整代码嘛。
03-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值