the elapsed cpu time字面意思是:经过的cpu时间。造句:System and user CPU time: The elapsed CPU time consumed invoking a method 系统和用户CPU时间:调用某方法占用的CPU时间。
前提参数设置
// 默认值是3,这个是session级别的,无需恢复
gbase> set gcluster_log_level=7;
Query OK, 0 rows affected (Elapsed: 00:00:0000)
// 默认值是0,建议先show一下原始值,排查完了记得改回去。
gbase> set global gbase_sql_trace_level=15;
Query OK, 0 rows affected (Elapsed: 00:00:0012)
// 默认值是0,这个是session级别,无需恢复
gbase> set gbase_sql_trace=1;
Query OK, 0 rows affected (Elapsed: 00:00:0001)
执行语句
gbase> load data infile ‘ftp://gbase:gbase1234@192168163100/t1txt’ into table testdbt1;
Query OK, 4 rows affected (Elapsed: 00:00:0035)
Task 394392 finished, Loaded 4 records, Skipped 0 records
查看日志
/opt/gbase/gcluster/log/gcluster/expresslog
# SQL处于check permission状态
# 获得表的锁
# 如果长时间无法拿到锁,通过gcadmin showlock 看看对应的表的锁在哪个节点哪个ID持有
2019-07-03 15:02:41352 [LOCK][INFO ][S:2108][Q:13221]:acquired WRITE lock: testdbt1580D5F90-B287-4199-B057-E6FBD44B5BFA, lwp:35693
2019-07-03 15:02:41352 [LOCK][INFO ][S:2108][Q:13221]:acquired READ lock: testdbt1, lwp:35693
2019-07-03 15:02:41353 [LOCK][INFO ][S:2108][Q:13221]:acquired READ lock: testdbt1rsync, lwp:35693
# 读取数据源ftp文件信息
# 检查数据库和FTP之间的性能问题,包括网络和FTP服务器的设置
2019-07-03 15:02:41354 [LOAD][INFO ][S:2108][Q:13221]:Start cluster load
2019-07-03 15:02:41358 == Information : Trying 192168163100
2019-07-03 15:02:41362 == Information : Connected to 192168163100 (192168163100) port 21 (#0)
2019-07-03 15:02:41370 <= Recv header : 220 (vsFTPd 302)
2019-07-03 15:02:41371 => Send header : USER gbase
2019-07-03 15:02:41371 <= Recv header : 331 Please specify the password
2019-07-03 15:02:41371 => Send header : PASS gbase1234
2019-07-03 15:02:41419 <= Recv header : 230 Login successful
2019-07-03 15:02:41419 => Send header : PWD
2019-07-03 15:02:41419 <= Recv header : 257 "/home/gbase"
2019-07-03 15:02:41419 == Information : Entry path is '/home/gbase'
2019-07-03 15:02:41419 => Send header : TYPE I
2019-07-03 15:02:41419 == Information : ftp_perform ends with SECONDARY: 0
2019-07-03 15:02:41420 <= Recv header : 200 Switching to Binary mode
2019-07-03 15:02:41420 => Send header : SIZE t1txt
2019-07-03 15:02:41420 <= Recv header : 213 8
2019-07-03 15:02:41420 => Send header : REST 0
2019-07-03 15:02:41420 <= Recv header : 350 Restart position accepted (0)
2019-07-03 15:02:41421 == Information : Remembering we are in dir ""
2019-07-03 15:02:41421 == Information : Connection #0 to host 192168163100 left intact
2019-07-03 15:02:41422 == Information : Trying 192168163100
2019-07-03 15:02:41422 == Information : Connected to 192168163100 (192168163100) port 21 (#0)
2019-07-03 15:02:41424 <= Recv header : 220 (vsFTPd 302)
2019-07-03 15:02:41424 => Send header : USER gbase
2019-07-03 15:02:41425 <= Recv header : 331 Please specify the password
2019-07-03 15:02:41425 => Send header : PASS gbase1234
2019-07-03 15:02:41465 <= Recv header : 230 Login successful
2019-07-03 15:02:41465 => Send header : PWD
2019-07-03 15:02:41465 <= Recv header : 257 "/home/gbase"
2019-07-03 15:02:41465 == Information : Entry path is '/home/gbase'
2019-07-03 15:02:41465 => Send header : TYPE I
2019-07-03 15:02:41465 == Information : ftp_perform ends with SECONDARY: 0
2019-07-03 15:02:41465 <= Recv header : 200 Switching to Binary mode
2019-07-03 15:02:41465 => Send header : SIZE t1_2txt
2019-07-03 15:02:41466 <= Recv header : 213 8
2019-07-03 15:02:41466 => Send header : REST 0
2019-07-03 15:02:41466 <= Recv header : 350 Restart position accepted (0)
2019-07-03 15:02:41466 == Information : Remembering we are in dir ""
2019-07-03 15:02:41466 == Information : Connection #0 to host 192168163100 left intact
#准备分派任务
2019-07-03 15:02:41467 [LOAD][INFO ][S:2108][Q:13221]:AddNodeLoadFileNum host[::ffff:192168163101]add num [1]
2019-07-03 15:02:41474 [LOCK][INFO ][S:2108][Q:13221]:unlocked: testdbt1
2019-07-03 15:02:41474 [LOCK][INFO ][S:2108][Q:13221]:acquired WRITE lock: testdbt16ef6f8a9-87f0-4d6c-8043-899367d02df3, lwp:35693
2019-07-03 15:02:41475 [LOAD][INFO ][S:2108][Q:13221]:AddNodeLoadFileNum cur node state:[ip:::ffff:192168163100:num:0][ip:::ffff:192168163101:num:1]
# 此时SQL已经在loading状态,
# 开始下发任务。一般是某个节点性能导致,或者数据非常倾斜。
# a) 可以测试从每个数据库的数据节点,用ftp直接获取数据文件的性能
# 比如 curl ftp://XXXXX/XXcsv > 1txt
# 多跑几次,看看哪个节点比较慢
# b) 排查机器的内存是否出现SWAP, *** 作系统/var/log/messages是否有磁盘报错
# c) 查看CPUINFO是否有异常降频
# d) 用top、iotop、nmon等工具观察一段时间系统资源,是否有资源紧张
#
2019-07-03 15:02:41476 [SQLDISP][INFO ][S:2108][Q:13221]:Target:::ffff:192168163101, SQL:set scn = 395447
2019-07-03 15:02:41521 [SQLDISP][INFO ][S:2108][Q:13221]:Target:::ffff:192168163101, SQL:LOAD DATA INFILE 'ftp://gbase:@192168163100/t1txt#offset=0&length=8&firstblock&ffsize=8,ftp://gbase:@192168163100/t1_2txt#offset=0&length=8&firstblock&ffsize=8' INTO TABLE `testdb``t1_n1` DATA_FORMAT 3 FILE_FORMAT UNDEFINED HOST '::ffff:192168163101' CURRENT_TIMESTAMP 1562137361 SCN_NUMBER 395447 GCLUSTER_PORT 5258 INTO SERVER (HOST '::ffff:192168163100, ::ffff:192168163101', PORT '5050', USER 'root', DATABASE 'testdb', TABLE 't1_n1, t1_n2', COMMENT 'table_host 0 1 0 # 1 0 1, scn 395447, group -1')
2019-07-03 15:02:42004 [LOAD][INFO ][S:2108][Q:13221]:ReduceNodeLoadFileNum host[::ffff:192168163100] reduce num [0]
2019-07-03 15:02:42004 [LOAD][INFO ][S:2108][Q:13221]:ReduceNodeLoadFileNum host[::ffff:192168163101] reduce num [1]
2019-07-03 15:02:42004 [LOAD][INFO ][S:2108][Q:13221]:ReduceNodeLoadFileNum cur node state:[ip:::ffff:192168163100:num:0][ip:::ffff:192168163101:num:0]
2019-07-03 15:02:42004 [LOAD][INFO ][S:2108][Q:13221]:Task 395447 finished, Loaded 8 records, Skipped 0 records
# 拿到排它锁,要切换版本了。
2019-07-03 15:02:42008 [LOCK][INFO ][S:2108][Q:13221]:acquired WRITE lock: testdbt109B5BEEC-1EF7-4FA6-9850-C4217A781E0F, lwp:35693
# 设置SCN
2019-07-03 15:02:42008 [SQLDISP][INFO ][S:2108][Q:13221]:Target:::ffff:192168163101, SQL:SET SELF SCN = 395447
2019-07-03 15:02:42009 [SQLDISP][INFO ][S:2108][Q:13221]:Target:::ffff:192168163100, SQL:SET SELF SCN = 395447
2019-07-03 15:02:42009 [SQLDISP][INFO ][S:2108][Q:13221]:Target:::ffff:192168163100, SQL:SET SELF SCN = 395447
2019-07-03 15:02:42009 [SQLDISP][INFO ][S:2108][Q:13221]:Target:::ffff:192168163101, SQL:SET SELF SCN = 395447
# 以指定的SCN来刷新数据
2019-07-03 15:02:42011 [SQLDISP][INFO ][S:2108][Q:13221]:Target:::ffff:192168163100, SQL:flush commit "testdb""t1_n1" scn_number 395447
2019-07-03 15:02:42011 [SQLDISP][INFO ][S:2108][Q:13221]:Target:::ffff:192168163100, SQL:flush commit "testdb""t1_n2" scn_number 395447
2019-07-03 15:02:42019 [SQLDISP][INFO ][S:2108][Q:13221]:Target:::ffff:192168163101, SQL:flush commit "testdb""t1_n2" scn_number 395447
2019-07-03 15:02:42055 [SQLDISP][INFO ][S:2108][Q:13221]:Target:::ffff:192168163101, SQL:flush commit "testdb""t1_n1" scn_number 395447
# 验证SCN
2019-07-03 15:02:42060 [SQLDISP][INFO ][S:2108][Q:13221]:Target:::ffff:192168163101, SQL:select scn from information_schematables where table_schema = 'testdb' and table_name = 't1_n1'
2019-07-03 15:02:42061 [SQLDISP][INFO ][S:2108][Q:13221]:Target:::ffff:192168163100, SQL:select scn from information_schematables where table_schema = 'testdb' and table_name = 't1_n1'
2019-07-03 15:02:42061 [SQLDISP][INFO ][S:2108][Q:13221]:Target:::ffff:192168163100, SQL:select scn from information_schematables where table_schema = 'testdb' and table_name = 't1_n2'
2019-07-03 15:02:42061 [SQLDISP][INFO ][S:2108][Q:13221]:Target:::ffff:192168163101, SQL:select scn from information_schematables where table_schema = 'testdb' and table_name = 't1_n2'
2019-07-03 15:02:42063 [SQLDISP][INFO ][S:2108][Q:13221]:Target:::ffff:192168163101, SQL:set autocommit=1
2019-07-03 15:02:42063 [SQLDISP][INFO ][S:2108][Q:13221]:Target:::ffff:192168163100, SQL:set autocommit=1
2019-07-03 15:02:42063 [SQLDISP][INFO ][S:2108][Q:13221]:Target:::ffff:192168163100, SQL:set autocommit=1
2019-07-03 15:02:42063 [SQLDISP][INFO ][S:2108][Q:13221]:Target:::ffff:192168163101, SQL:set autocommit=1
# SQL处于commit阶段 或者 rollback阶段
# 提交commit成功
2019-07-03 15:02:42067 [COMMIT][INFO ][S:2108][Q:13221]:commit table(testdbt1) success for scn:395447
2019-07-03 15:02:42068 [LOAD][INFO ][S:2108][Q:13221]:successful to cluster load
# 释放锁
2019-07-03 15:02:42068 [LOCK][INFO ][S:2108][Q:13221]:unlocked: testdb
2019-07-03 15:02:42069 [LOCK][INFO ][S:2108][Q:13221]:unlocked: testdbt109B5BEEC-1EF7-4FA6-9850-C4217A781E0F
2019-07-03 15:02:42070 [LOCK][INFO ][S:2108][Q:13221]:unlocked: testdbt1rsync
2019-07-03 15:02:42071 [LOCK][INFO ][S:2108][Q:13221]:unlocked: testdbt1580D5F90-B287-4199-B057-E6FBD44B5BFA
2019-07-03 15:02:42072 [LOCK][INFO ][S:2108][Q:13221]:unlocked: testdbt16ef6f8a9-87f0-4d6c-8043-899367d02df3
参考一下看看
PHP的日期时间函数date()
1,年-月-日
echo date('Y-m-j');
2007-02-6
echo date('y-n-j');
07-2-6
大写Y表示年四位数字,而小写y表示年的两位数字;
小写m表示月份的数字(带前导),而小写n则表示不带前导的月份数字。
echo date('Y-M-j');
2007-Feb-6
echo date('Y-m-d');
2007-02-06
大写M表示月份的3个缩写字符,而小写m则表示月份的数字(带前导0);
没有大写的J,只有小写j表示月份的日期,无前导o;若需要月份带前导则使用小写d。
echo date('Y-M-j');
2007-Feb-6
echo date('Y-F-jS');
2007-February-6th
大写M表示月份的3个缩写字符,而大写F表示月份的英文全写。(没有小写f)
大写S表示日期的后缀,比如“st”、“nd”、“rd”和“th”,具体看日期数字为何。
小结:
表示年可以用大写的Y和小写y;
表示月可以用大写F、大写M、小写m和小写n(分别表示字符和数字的两种方式);
表示日可以用小写d和小写j,大写S表示日期的后缀。
2,时:分:秒
默认情况下,PHP解释显示的时间为“格林威治标准时间”,与我们本地的时间相差8个小时。
echo date('g:i:s a');
5:56:57 am
echo date('h:i:s A');
05:56:57 AM
小写g表示12小时制,无前导0,而小写h则表示有前导0的12小时制。
当使用12小时制时需要表明上下午,小写a表示小写的“am”和“pm”,大写A表示大写的“AM”和“PM”。
echo date('G:i:s');
14:02:26
大写G表示24小时制的小时数,但是不带前导的;使用大写的H表示带前导的24小时制小时数
小结:
字母g表示小时不带前导,字母h表示小时带前导;
小写g、h表示12小时制,大写G、H表示24小时制。
3,闰年、星期、天
echo date('L');
今年是否闰年:0
echo date('l');
今天是:Tuesday
echo date('D');
今天是:Tue
大写L表示判断今年是否闰年,布尔值,为真返回1,否则为0;
小写l表示当天是星期几的英文全写(Tuesday);
而使用大写D表示星期几的3个字符缩写(Tue)。
echo date('w');
今天星期:2
echo date('W');
本周是全年中的第 06 周
小写w表示星期几,数字形式表示
大写W表示一年中的星期数
echo date('t');
本月是 28 天
echo date('z');
今天是今年的第 36 天
小写t表示当前月份又多少天
小写z表示今天是本年中第几天
4,其他
echo date('T');
UTC
大写T表示服务器的时间区域设置
echo date('I');
0
大写I表示判断当前是否为夏令时,为真返回1,否则为0
echo date('U');
1170769424
大写U表示从1970年1月1日到现在的总秒数,就是Unix时间纪元的UNIX时间戳。
echo date('c');
2007-02-06T14:24:43+00:00
小写c表示ISO8601日期,日期格式为YYYY-MM-DD,用字母T来间隔日期和时间,时间格式为HH:MM:SS,时区使用格林威治标准时间(GMT)的偏差来表示。
echo date('r');
Tue, 06 Feb 2007 14:25:52 +0000
小写r表示RFC822日期。
小小的date()函数就显示出了PHP的强大功能和迷人魅力,再比较下ASP,呵呵。
checkdate($month,$date,$year)
如果应用的值构成一个有效日期,则该函数返回为真。例如,对于错误日期2005年2月31日,此函数返回为假。
在日期用于计算或保存在数据库中之前,可用此函数检查日期并使日期生效。
<php
// returns false
echo checkdate(2,30,2005) "valid" : "invalid";
// returns true
echo checkdate(4,6,2010) "valid" : "invalid";
>
getdate($ts)
在没有自变量的情况下,该函数以结合数组的方式返回当前日期与时间。数组中的每个元素代表日期/时间值中的一个特定组成部分。可向函数提交可选的时间标签自变量,以获得与时间标签对应的日期/时间值。
应用此函数来获得一系列离散的,容易分离的日期/时间值。
<php
// get date as associative array
$arr = getdate();
echo "Date is " $arr['mday'] " " $arr['weekday'] " " $arr['year'];
echo "Time is " $arr['hours'] ":" $arr['minutes'];
>
mktime($hour, $minute, $second, $month, $day, $year)
此函数的作用与getdate()的作用相反:它由一系列的日期与时间值生成一个UNIX时间标签(GMT时间1970年1月1日到现在消逝的秒数)。不用自变量时,它生成当前时间的UNIX时间标签。
用此函数获得即时时间的UNIX时间标签。这种时间标签通常用于许多数据库与程序语言中。
<php
// returns timestamp for 13:15:23 7-Jun-2006
echo mktime(13,15,23,6,7,2006);
>
date($format, $ts)
此函数将UNIX时间标签格式化成一个可人为阅读的日期字符串。它是PHP日期/时间API中功能最为强大的函数,可用在一系列的修正值中,将整数时间标签转变为所需的字符串格式。
为显示格式化时间或日期时,应用此函数。
<php
// format current date
// returns "13-Sep-2005 01:16 PM"
echo date("d-M-Y h:i A", mktime());
>
strtotime($str)
此函数将可人为阅读的英文日期/时间字符串转换成UNIX时间标签。
应用此函数将非标准化的日期/时间字符串转换成标准、兼容的UNIX时间标签。
<php
// returns 13-Sep-05
echo date("d-M-y", strtotime("today"));
// returns 14-Sep-05
echo date("d-M-y", strtotime("tomorrow"));
// returns 16-Sep-05
echo date("d-M-y", strtotime("today +3 days"));
>
strftime($format,$ts)
如前面的setlocale()函数定义的那样,此函数将UNIX时间标签格式化成适用于当前环境的日期字符串。
应用此函数建立与当前环境兼容的日期字符串。
<php
// set locale to France (on Windows)
setlocale(LC_TIME, "fra_fra");
// format month/day names
// as per locale setting
// returns "septembre" and "mardi"
echo strftime("Month: %B ");
echo strftime("Day: %A ");
>
microtime()
如前面的setlocale()函数定义的那样,此函数将UNIX时间标签格式化成适用于当前环境的日期字符串。
应用此函数建立与当前环境兼容的日期字符串。
<php
// get starting value
$start = microtime();
// run some code
for ($x=0; $x<1000; $x++) {
$null = $x $x;
}
// get ending value
$end = microtime();
// calculate time taken for code execution
echo "Elapsed time: " ($end - $start) " sec";
>
gmmktime($hour, $minute, $second, $month, $day, $year)
此函数由一系列用GMT时间表示的日期与时间值生成一个UNIX时间标签。不用自变量时,它生成一个当前GMT即时时间的UNIX时间标签。
用此函数来获得GMT即时时间的UNIX时间标签。
<php
// returns timestamp for 12:25:23 9-Jul-2006
echo gmmktime(12,25,23,7,9,2006);
>
gmdate($format, $ts)
此函数将UNIX时间标签格式化成可人为阅读的日期字符串。此日期字符串以GMT(非当地时间)表示。
用GMT表示时间标签时应用此函数。
<php
// format current date into GMT
// returns "13-Sep-2005 08:32 AM"
echo gmdate("d-M-Y h:i A", mktime());
>
date_default_timezone_set($tz)、date_default_timezone_get()
此函数此后所有的日期/时间函数调用设定并恢复默认的时区。
注:此函数仅在PHP 51+中有效。
此函数是一个方便的捷径,可为以后的时间 *** 作设定时区。
<php
// set timezone to UTC
date_default_timezone_set('UTC');
>
<php
//今天
$today = date("Y-m-d");
//昨天
$yesterday = date("Y-m-d", strtotime(date("Y-m-d"))-86400);
//上周
$lastweek_start = date("Y-m-d H:i:s",mktime(0, 0 , 0,date("m"),date("d")-date("w")+1-7,date("Y")));
$lastweek_end = date("Y-m-d H:i:s",mktime(23,59,59,date("m"),date("d")-date("w")+7-7,date("Y")));
//本周
$thisweek_start = date("Y-m-d H:i:s",mktime(0, 0 , 0,date("m"),date("d")-date("w")+1,date("Y")));
$thisweek_end = date("Y-m-d H:i:s",mktime(23,59,59,date("m"),date("d")-date("w")+7,date("Y")));
//上月
$lastmonth_start = date("Y-m-d H:i:s",mktime(0, 0 , 0,date("m")-1,1,date("Y")));
$lastmonth_end = date("Y-m-d H:i:s",mktime(23,59,59,date("m") ,0,date("Y")));
//本月
$thismonth_start = date("Y-m-d H:i:s",mktime(0, 0 , 0,date("m"),1,date("Y")));
$thismonth_end = date("Y-m-d H:i:s",mktime(23,59,59,date("m"),date("t"),date("Y")));
//本季度未最后一月天数
$getMonthDays = date("t",mktime(0, 0 , 0,date('n')+(date('n')-1)%3,1,date("Y")));
//本季度/
$thisquarter_start = date('Y-m-d H:i:s', mktime(0, 0, 0,date('n')-(date('n')-1)%3,1,date('Y')));
$thisquarter_end = date('Y-m-d H:i:s', mktime(23,59,59,date('n')+(date('n')-1)%3,$getMonthDays,date('Y')));
>
一般来说,当检测到性能问题时,我们会收集覆盖了发生问题的时间段的AWR报告-但是最好只收集覆盖1个小时时间段的AWR报告-如果时间过长,那么AWR报告就不能很好的反映出问题所在。还应该收集一份没有性能问题的时间段的AWR报告,作为一个参照物来对比有问题的时间段的AWR报告。这两个AWR报告的时间段应该是一致的,比如都是半个小时的,或者都是一个小时的。
Interpretation
在处理性能问题时,我们最关注的是数据库正在等待什么。
当进程因为某些原因不能进行 *** 作时,它需要等待。花费时间最多的等待事件是我们最需要关注的,因为降低它,我们能够获得最大的好处。
AWR报告中的"Top 5 Timed Events"部分就提供了这样的信息,可以让我们只关注主要的问题。
Top 5 Timed Events
正如前面提到的,"Top 5 Timed Events"是AWR报告中最重要的部分。它指出了数据库的sessions花费时间最多的等待事件,如下:
Top 5 Timed Events Avg %Total
~~~~~~~~~~~~~~~~~~ wait Call
Event Waits Time (s) (ms) Time Wait Class
------------------------------ ------------ ----------- ------ ------ ----------
db file scattered read 10,152,564 81,327 8 296 User I/O
db file sequential read 10,327,231 75,878 7 276 User I/O
CPU time 56,207 205
read by other session 4,397,330 33,455 8 122 User I/O
PX Deq Credit: send blkd 31,398 26,576 846 97 Other
-------------------------------------------------------------
Top 5 Events部分包含了一些跟Events(事件)相关的信息。它记录了这期间遇到的等待的总次数,等待所花费的总时间,每次等待的平均时间;这一部分是按照每个Event占总体call time的百分比来进行排序的。
根 据Top 5 Events部分的信息的不同,接下来我们需要检查AWR报告的其他部分,来验证发现的问题或者做定量分析。等待事件需要根据报告期的持续时间和当时数据 库中的并发用户数进行评估。如:10分钟内1000万次的等待事件比10个小时内的1000万等待更有问题;10个用户引起的1000万次的等待事件比 10,000个用户引起的相同的等待要更有问题。
就像上面的例子,将近60%的时间是在等待IO相关的事件。
其他20%的时间是花在使用或等待CPU time上。过高的CPU使用经常是性能不佳的SQL引起的(或者这些SQL有可能用更少的资源完成同样的 *** 作);对于这样的SQL,过多的IO *** 作也是一个症状。关于CPU使用方面,我们会在之后讨论。
在以上基础上,我们将调查是否这个等待事件是有问题的。若有问题,解决它;若是正常的,检查下个等待事件。
过多的IO相关的等待一般会有两个主要的原因:
Top 5 Events部分的显示的信息会帮助我们检查:
需要注意,接下来的分析步骤取决于我们在TOP 5部分的发现。在上面的例子里,3个top wait event表明问题可能与SQL语句执行计划不好有关,所以接下来我们要去分析"SQL Statistics"部分。
同样的,因为我们并没有看到latch相关的等待,latch在我们这个例子里并没有引发严重的性能问题;那么我们接下来就完全不需要分析latch相关的信息。
一 般来讲,如果数据库性能很慢,TOP 5等待事件里"CPU", "db file sequential read" 和"db file scattered read" 比较明显(不管它们之间的顺序如何),我们总是需要检查Top SQL (by logical and physical reads)部分;调用SQL Tuning Advisor或者手工调优这些SQL来确保它们是有效率的运行。
是否数据库做了大量的读 *** 作:
上面的图显示了在这段时间里两类读 *** 作都分别大于1000万,这些 *** 作是否过多取决于报告的时间是1小时或1分钟。我们可以检查AWR报告的elapsed time如果这些读 *** 作确实是太多了,接下来我们需要检查AWR报告中 SQL Statistics 部分的信息,因为读 *** 作都是由SQL语句发起的。
是否是每次的IO读 *** 作都很慢:
上面的图显示了在这段时间里两类读 *** 作平均的等待时间是小于8ms的
至于8ms是快还是慢取决于底层的硬件设备;一般来讲小于20ms的都可以认为是可以接受的。
我们还可以在AWR报告"Tablespace IO Stats"部分得到更详细的信息
Tablespace IO Stats DB/Inst: VMWREP/VMWREP Snaps: 1-15
-> ordered by IOs (Reads + Writes) desc
Tablespace
------------------------------
Av Av Av Av Buffer Av Buf
Reads Reads/s Rd(ms) Blks/Rd Writes Writes/s Waits Wt(ms)
-------------- ------- ------ ------- ------------ -------- ---------- ------
TS_TX_DATA
14,246,367 283 76 46 145,263,880 2,883 3,844,161 83
USER
204,834 4 107 10 17,849,021 354 15,249 98
UNDOTS1
19,725 0 30 10 10,064,086 200 1,964 49
AE_TS
4,287,567 85 54 67 932 0 465,793 37
TEMP
2,022,883 40 00 58 878,049 17 0 00
UNDOTS3
1,310,493 26 46 10 941,675 19 43 00
TS_TX_IDX
1,884,478 37 73 10 23,695 0 73,703 83
>SYSAUX
346,094 7 56 39 112,744 2 0 00
SYSTEM
101,771 2 79 35 25,098 0 653 27
如上图,我们关心Av Rd(ms)的指标。如果它高于20ms并且同时有很多读 *** 作的,我们可能要开始从OS的角度调查是否有潜在的IO问题。
注:对于一些比较空闲的tablespace/files,我们可能会得到一个比较大的Av Rd(ms)值;对于这样的情况,我们应该忽略这样的tablespace/files;因为这个很大的值可能是由于硬盘自旋(spin)引起的,没有太大的参考意义。比如对
于一个有1000万次读 *** 作而且很慢的系统,引起问题的基本不可能是一个只有10次read的tablespace/file
虽 然高"db file scattered read"和"db file sequential read"等待可以是I / O相关的问题,但是很多时候这些等待也可能是正常的;实际上,对一个已经性能很好的数据库系统,这些等待事件往往在top 5等待事件里,因为这意味着您的数据库没有那些真正的“问题”。
诀窍是能够评估引起这些等待的语句是否使用了最优的访问路径。如果"db file scattered read"比较高,那么相关的SQL语句可能使用了全表扫描而没有使用索引(也许是没有创建索引,也许是没有合适的索引);相应的,如果"db file sequential read"过多,则表明也许是这些SQL语句使用了selectivity不高的索引从而导致访问了过多不必要的索引块或者使用了错误的索引。这些等待可 能说明SQL语句的执行计划不是最优的。
接下来就需要通过AWR来检查这些top SQL是否可以进一步的调优,我们可以查看AWR报告中 SQL Statistics 的部分
上面的例子显示了20%的时间花在了等待或者使用CPU上,我们也需要检查 SQL statistics 部分来进一步的分析。
数据库做了太多的读 *** 作
每次的IO读 *** 作都很慢
事件"db file scattered read"一般表明正在做由全表扫描或者index fast full scan引起的多块读。
事件"db file sequential read"一般是由不能做多块读的 *** 作引起的单块读(如读索引)
SQL Statistics
AWR包含了一些不同的SQL统计值:
根据Top 5 部分的Top Wait Event不同,我们需要检查不同的SQL statistic。
在我们这个例子里,Top Wait Event是"db file scattered read","db file sequential read"和CPU;我们最需要关心的是SQL ordered by CPU Time, Gets and Reads。
我们会从"SQL ordered by gets"入手,因为引起高buffer gets的SQL语句一般是需要调优的对象。
SQL ordered by Gets
-> Resources reported for PL/SQL code includes the resources used by all SQL
statements called by the code
-> Total Buffer Gets: 4,745,943,815
-> Captured SQL account for 1222% of Total
Gets CPU Elapsed
Buffer Gets Executions per Exec %Total Time (s) Time (s) SQL Id
-------------- ------------ ------------ ------ -------- --------- -------------
1,228,753,877 168 7,314,0112 259 802246 840473 5t1y1nvmwp2
SELECT ADDRESSID",CURRENT$"ADDRESSTYPEID",CURRENT$URRENT$"ADDRESS3",
CURRENT$"CITY",CURRENT$"ZIP",CURRENT$"STATE",CURRENT$"PHONECOUNTRYCODE",
CURRENT$"PHONENUMBER",CURRENT$"PHONEEXTENSION",CURRENT$"FAXCOU
1,039,875,759 62,959,363 165 219 532027 561896 grr4mg7ms81
Module: DBMS_SCHEDULER
INSERT INTO "ADDRESS_RDONLY" ("ADDRESSID","ADDRESSTYPEID","CUSTOMERID","
ADDRESS1","ADDRESS2","ADDRESS3","CITY","ZIP","STATE","PHONECOUNTRYCODE","PHONENU
854,035,223 168 5,083,5430 180 571350 745895 4at7cbx8hnz
SELECT "CUSTOMERID",CURRENT$"ISACTIVE",CURRENT$"FIRSTNAME",CURRENT$"LASTNAME",CU<
RRENT$"ORGANIZATION",CURRENT$"DATEREGISTERED",CURRENT$"CUSTOMERSTATUSID",CURR
ENT$"LASTMODIFIEDDATE",CURRENT$"SOURCE",CURRENT$"EMPLOYEEDEPT",CURRENT$
对这些Top SQL,可以手工调优,也可以调用SQL Tuning Advisor。
分析:
Other SQL Statistic Sections
就像之前提到的那样,AWR报告中有很多不同的部分用来分析各种不同的问题。如果特定的问题并没有出现,那么分析AWR报告的这些部分并不能有很大的帮助。
下面提到了一些可能的问题:
Waits for 'Cursor: mutex/pin' 如 果发现了一些像"Cursor: pin S wait on X" 或"Cursor: mutex X" 类的mutex等待,那么可能是由于parsing引起的问题。检查"SQL ordered by Parse Calls" 和"SQL ordered by Version Count"部分的Top SQL,这些SQL可能引起这类的问题。
单次执行buffer gets过多
SQL_ID为'5t1y1nvmwp2'和'4at7cbx8hnz'的SQL语句总共被执行了168次,但是每次执行引起的buffer gets超过500万。这两个SQL应该是主要的需要调优的候选者。
执行次数过多
SQL_ID 'grr4mg7ms81' 每次执行只是引起16次buffer gets,减少这条SQL每次执行的buffer get可能并不能显著减少总共的buffer gets。这条语句的问题是它执行的太频繁了,6500万次。
改变这条SQL的执行次数可能会更有意义。这个SQL看起来是在一个循环里面被调用,如果可以让它一次处理的数据更多也许可以减少它执行的次数。
-> Total Buffer Gets: 4,745,943,815
假设这是一个一个小时的AWR报告,4,745,943,815是一个很大的值;所以需要进一步分析这个SQL是否使用了最优的执行计划
Individual Buffer Gets
上面的例子里单个的SQL的buffer get非常多,最少的那个都是8亿5千万。这三个SQL指向了两个不同的引起过多buffers的原因:
注意:对于某些非常繁忙的系统来讲,以上的数字可能都是正常的。这时候我们需要把这些数字跟正常时段的数字作对比,如果没有什么太大差别,那么这些SQL并不是引起问题的元凶(虽然通过调优这些SQL我们仍然可以受益)
Load Profile
根据Top 5等待事件的不同,"Load Profile"可以提供一些有用的背景资料或潜在问题的细节信息。
Load Profile
~~~~~~~~~~~~ Per Second Per Transaction
--------------- ---------------
Redo size: 4,585,41480 3,165,88314
Logical reads: 94,18563 65,02807
Block changes: 40,02857 27,63671
Physical reads: 2,20612 1,52316
Physical writes: 3,93997 2,72025
User calls: 5008 3458
Parses: 2696 1861
Hard parses: 149 103
Sorts: 1836 1268
Logons: 013 009
Executes: 4,92589 3,40096
Transactions: 145
% Blocks changed per Read: 4250 Recursive Call %: 9919
Rollback per transaction %: 5969 Rows per Sort: 192264
在这个例子里,Top 5 Events部分显示问题可能跟SQL的执行有关,那么我们接下来检查load profile部分。
如果您检查AWR report是为了一般性的性能调优,那么可以看到有比较多的redo activity和比较高的physical writes Physical writes比physical read要高,并且有42%的块被更改了
此外,hard parse的次数要少于soft parse
如果mutex等待事件比较严重,如"library cache: mutex X",那么查看所有parse的比率会更有用。
当然,如果把Load Profile部分跟正常时候的AWR报告做比较会更有用,比如,比较redo size, users calls, 和 parsing这些性能指标。
Instance Efficiency
Instance Efficiency部分更适用于一般性的调优,而不是解决某个具体问题(除非等待事件直接指向这些指标)。
Instance Efficiency Percentages (Target 100%)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Buffer Nowait %: 9991 Redo NoWait %: 10000
Buffer Hit %: 9814 In-memory Sort %: 9998
Library Hit %: 9991 Soft Parse %: 9448
Execute to Parse %: 9945 Latch Hit %: 9997
Parse CPU to Parse Elapsd %: 7123 % Non-Parse CPU: 9900
从我们的这个例子来看,最有用的信息是%Non-Parse CPU,它表明几乎所有的CPU都消耗在了Execution而不是Parse上,所以调优SQL会对性能有改善。
——日期计算 算第n周的第一天及最后一天是几号 by keynes
================================================
—— ww的算法为每年 月 日为第一周开始 date+ 为每一周结尾
—— 例如 为第一周的第一天 而第一周的最后一天为 + =
—— 公式 每周第一天 date + 周
—— 每周最后一天 date + 周
你会发现怎么编排格式都会跑掉
=========================================================================
——日期计算 算第n周的第一天及最后一天是几号 by keynes
=========================================================================
—— ww的算法为每年 月 日为第一周开始 date+ 为每一周结尾
—— 例如 为第一周的第一天 而第一周的最后一天为 + =
—— 公式 每周第一天 date + 周
—— 每周最后一天 date + 周
—— 如果以ww格式为主 第 周的起迄如下
asdb WF>select to_date( yyyymmdd ) + to_date( yyyymmdd ) + from dual
TO_DATE( TO_DATE(
JAN JAN
asdb WF>select to_date( yyyymmdd ) + to_date( yyyymmdd ) + from dual
TO_DATE( TO_DATE(
APR APR
Elapsed
—— 验证如下
asdb WF>select to_char(to_date( yyyymmdd ) ww ) as weekn to_char(to_date( yyyymmdd ) ww ) as week to_char(to_date( yyyymmdd ) ww ) as week to_char(to_date( yyyymmdd ) ww ) as weekn from dual
WEEK WEEK WEEK WEEK
Elapsed
asdb WF>
—— iw的算法为星期一至星期日算一周 且每年的第一个星期一为第一周
—— 例如 为星期六 所以用iw的算法是前年的 周 而 之后才是第一周的开始
—— 公式 每周第一天 next_day(date) + 周
—— 每周最后一天 next_day(date) + 周
—— 如果以iw格式为主 第 周的起迄如下
asdb WF>select next_day(to_date( yyyymmdd ) MONDAY )+ as first_day next_day(to_date( yyyymmdd ) MONDAY )+ as last_day from dual
FIRST_DAY LAST_DAY
JAN JAN
Elapsed
asdb WF>
asdb WF>select next_day(to_date( yyyymmdd ) MONDAY )+ as first_day next_day(to_date( yyyymmdd ) MONDAY )+ as last_day from dual
FIRST_DAY LAST_DAY
APR MAY
Elapsed
asdb WF>
—— 验证如下
asdb WF>select to_char(to_date( yyyymmdd ) iw ) as weekn to_char(to_date( yyyymmdd ) iw ) as week to_char(to_date( yyyymmdd ) iw ) as week to_char(to_date( yyyymmdd ) iw ) as weekn from dual
WEEK WEEK WEEK WEEK
Elapsed
其它
——== 查今天是 本月 的第几周
SELECT TO_CHAR(SYSDATE WW ) TO_CHAR(TRUNC(SYSDATE MM ) WW ) + AS weekOfMon from dual
或
SELECT TO_CHAR(SYSDATE W ) AS weekOfMon from dual
——== 查今天是 今年 的第几周
select to_char(sysdate ww ) from dual
或
select to_char(sysdate iw ) from dual
附注
上文所提之iw及ww格式在doc内解释如下
IW = Week of year ( or ) based on the ISO standard
WW = Week of year ( ) where week starts on the first day of the year and continues to the seventh day of the year
lishixinzhi/Article/program/Oracle/201311/18798
pt-archiver原理解析
作为MySQL DBA,可以说应该没有不知道pt-archiver了,作为pt-toolkit套件中的重要成员,往往能够轻松帮助DBA解决数据归档的问题。例如线上一个流水表,业务仅仅只需要存放最近3个月的流水数据,三个月前的数据做归档即可,那么pt-archiver就可以轻松帮你完成这件事情,甚至你可以配置成自动任务,无需人工干预。
作为DBA,我们应该知其然更应该知其所以然,这样我们也能够放心地使用pt工具。相信很多DBA都研究过pt-online-schema-change的原理,那么今天我们深入刨一刨pt-archiver的工作原理。
一、原理观察
土人有土办法,我们直接开启general log来观察pt-archiver是如何完成归档的。
命令
pt-archiver --source h=127001,u=xucl,p=xuclxucl,P=3306,D=xucl,t=t1 --dest h=127001,P=3306,u=xucl,p=xuclxucl,D=xucl_archive,t=t1 --progress 5000 \
--statistics --charset=utf8mb4 --limit=10000 --txn-size 1000 --sleep 30
常用选项
--analyze
指定工具完成数据归档后对表执行'ANALYZE TABLE' *** 作。指定方法如'--analyze=ds',s代表源端表,d代表目标端表,也可以单独指定。
--ask-pass
命令行提示密码输入,保护密码安全,前提需安装模块perl-TermReadKey。
--buffer
指定缓冲区数据刷新到选项'--file'指定的文件并且在提交时刷新。
只有当事务提交时禁用自动刷新到'--file'指定的文件和刷新文件到磁盘,这意味着文件是被 *** 作系统块进行刷新,因此在事务进行提交之前有一些数据隐式刷新到磁盘。默认是每一行 *** 作后进行文件刷新到磁盘。
--bulk-delete
指定单个语句删除chunk的方式来批量删除行,会隐式执行选项'--commit-each'。
使用单个DELETE语句删除每个chunk对应的表行,通常的做法是通过主键进行逐行的删除,批量删除在速度上会有很大的提升,但如果有复杂的'WHERE'条件就可能会更慢。
--[no]bulk-delete-limit
默认值:yes
指定添加选项'--bulk-delete'和'--limit'到进行归档的语句中。
--bulk-insert
使用LOAD DATA LOCAL INFILE的方法,通过批量插入chunk的方式来插入行(隐式指定选项'--bulk-delete'和'--commit-each')
而不是通过逐行单独插入的方式进行,它比单行执行INSERT语句插入的速度要快。通过隐式创建临时表来存储需要批量插入的行(chunk),而不是直接进行批量插入 *** 作,当临时表中完成每个chunk之后再进行统一数据加载。为了保证数据的安全性,该选项会强制使用选项'--bulk-delete',这样能够有效保证删除是在插入完全成功之后进行的。
--channel
指定当主从复制环境是多源复制时需要进行归档哪个主库的数据,适用于多源复制中多个主库对应一个从库的情形。
--charset,-A
指定连接字符集。
--[no]check-charset
默认值:yes
指定检查确保数据库连接时字符集和表字符集相同。
--[no]check-columns
默认值:yes
指定检查确保选项'--source'指定的源端表和'--dest'指定的目标表具有相同的字段。
不检查字段在表的排序和字段类型,只检查字段是否在源端表和目标表当中都存在,如果有不相同的字段差异,则工具报错退出。如果需要禁用该检查,则指定'--no-check-columns'。
--check-slave-lag
指定主从复制延迟大于选项'--max-lag'指定的值之后暂停归档 *** 作。默认情况下,工具会检查所有的从库,但该选项只作用于指定的从库(通过DSN连接方式)。
--check-interval
默认值:1s
如果同时指定了选项'--check-slave-lag',则该选项指定的时间为工具发现主从复制延迟时暂停的时间。每进行 *** 作100行时进行一次检查。
--columns,-c
指定需要归档的表字段,如有多个则用','(逗号)隔开。
--commit-each
指定按每次获取和归档的行数进行提交,该选项会禁用选项'--txn-size'。
在每次获取表数据并进行归档之后,在获取下一次数据和选项'--sleep'指定的休眠时间之前,进行事务提交和刷新选项'--file'指定的文件,通过选项'--limit'控制事务的大小。
--host,-h
指定连接的数据库IP地址。
--port,-P
指定连接的数据库Port端口。
--user,-u
指定连接的数据库用户。
--password,-p
指定连接的数据库用户密码。
--socket,-S
指定使用SOCKET文件连接。
--databases,-d
指定连接的数据库
--source
指定需要进行归档 *** 作的表,该选项是必须指定的选项,使用DSN方式表示。
--dest
指定要归档到的目标端表,使用DSN方式表示。
如果该选项没有指定的话,则默认与选项'--source'指定源端表为相同表。
--where
指定通过WHERE条件语句指定需要归档的数据,该选项是必须指定的选项。不需要加上'WHERE'关键字,如果确实不需要WHERE条件进行限制,则指定'--where 1=1'。
--file
指定表数据需要归档到的文件。使用类似MySQL DATE_FORMAT()格式化命名方式。
文件内容与MySQL中SELECT INTO OUTFILE语句使用相同的格式,文件命名选项如下所示:
%Y:年,4位数(Year, numeric, four digits)
%m:月,2位数(Month, numeric (0112))
%d:日,2位数(Day of the month, numeric (0131))
%H:小时(Hour (0023))
%i:分钟(Minutes, numeric (0059))
%s:秒(Seconds (0059))
%D:数据库名(Database name)
%t:表名(Table name)
例如:--file '/var/log/archive/%Y-%m-%d-%D%t'
--output-format
指定选项'--file'文件内容输出的格式。
默认不指定该选项是以制表符进行字段的分隔符,如果指定该选项,则使用','(逗号)作为字段分隔符,使用'"'(双引号)将字段括起。用法示例:'--output-format=dump'。
--for-update
指定为每次归档执行的SELECT语句添加FOR UPDATE子句。--share-lock
指定为每次归档执行的SELECT语句添加LOCK IN SHARE MODE子句。
--header
指定在文件中第一行写入字段名称作为标题。
--ignore
指定为INSERT语句添加IGNORE选项。
--limit
默认值:1
指定每条语句获取表和归档表的行数。
--local
指定不将OPTIMIZE和ANALYZE语句写入binlog。
--max-lag
默认值:1s
指定允许主从复制延迟时长的最大值,单位秒。如果在每次获取行数据之后主从延迟超过指定的值,则归档 *** 作将暂停执行,暂停休眠时间为选项'--check-interval'指定的值。待休眠时间结束之后再次检查主从延迟时长,检查方法是通过从库查询的'Seconds_Behind_Master'值来确定。如果主从复制延迟一直大于该参数指定值或者从库停止复制,则 *** 作将一直等待直到从库重新启动并且延迟小于该参数指定值。
--no-delete
指定不删除已被归档的表数据。
--optimize
指定工具完成数据归档后对表执行'OPTIMIZE TABLE' *** 作。指定方法如'--analyze=ds',s代表源端表,d代表目标端表,也可以单独指定。
--primary-key-only
指定只归档主键字段,是选项'--columns=主键'的简写。
如果工具归档的 *** 作是进行DELETE清除时最有效,因为只需读取主键一个字段而无需读取行所有字段。
--progress
指定每多少行打印进度信息,打印当前时间,已用时间以及多少行进行归档。
--purge
指定执行的清除 *** 作而不是归档 *** 作。允许忽略选项'--dest'和'--file'进行 *** 作,如果只是清除 *** 作可以结合选项'--primary-key-only'会更高效。
--quiet,-q
指定工具静默执行,不输出任何的执行信息。
--replace
指定写入选项'--dest'指定目标端表时改写INSERT语句为REPLACE语句。
--retries
默认值:1
指定归档 *** 作遇到死锁或超时的重试次数。当重试次数超过该选项指定的值时,工具将报错退出。
--run-time
指定工具归档 *** 作在退出之前需要运行的时间。允许的时间后缀名为s=秒,m=分,h=小时,d=天,如果没指定,默认为s。
--[no]safe-auto-increment
默认值:yes
指定不使用自增列(AUTO_INCREMENT)最大值对应的行进行归档。
该选项在进行归档清除时会额外添加一条WHERE子句以防止工具删除单列升序字段具有的具有AUTO_INCREMENT属性最大值的数据行,为了在数据库重启之后还能使用到AUTO_INCREMENT对应的值,但这会引起无法归档或清除字段对应最大值的行。
--set-vars
默认:
wait_timeout=10000
innodb_lock_wait_timeout=1
lock_wait_timeout=60
工具归档时指定参数值,如有多个用','(逗号)分隔。如'--set-vars=wait_timeout=5000'。
--skip-foreign-key-checks
指定使用语句SET FOREIGN_KEY_CHECKS = 0禁用外键检查。
--sleep
指定工具在通过SELECT语句获取归档数据需要休眠的时间,默认值是不进行休眠。在休眠之前事务并不会提交,并且选项'--file'指定的文件不会被刷新。如果指定选项'--commit-each',则在休眠之前会进行事务提交和文件刷新。
--statistics
指定工具收集并打印 *** 作的时间统计信息。
统计信息示例如下:
'
Started at 2008-07-18T07:18:53, ended at 2008-07-18T07:18:53
Source: D=db,t=table
SELECT 4
INSERT 4
DELETE 4
Action Count Time Pct
commit 10 01079 8827
select 5 00047 387
deleting 4 00028 229
inserting 4 00028 228
other 0 00040 329
--txn-size
默认:1
指定每个事务处理的行数。如果是0则禁用事务功能。
--version
显示工具的版本并退出。
--[no]version-check
默认值:yes
检查Percona Toolkit、MySQL和其他程序的最新版本。
--why-quit
指定工具打印当非因完成归档行数退出的原因。
在执行一个自动归档任务时该选项与选项'--run-time'一起使用非常方便,这样可以确定归档任务是否在指定的时间内完成。如果同时指定了选项'--statistics',则会打印所有退出的原因。
二、原理解析
根据general log的输出,我们整理出时序表格如下
三、其他说明
咋一看这个过程貌似也没有什么问题,但是,假如在原表扫描出数据,插入到新表的过程中,旧数据发生了变化怎么办?
带着这个疑问,我们进行了源码的跟踪,我们在pt-archiver的6839行打上了断点
然后我分别在几个session窗口做了如下动作
最后pt-archiver输出如下:
# A software update is available:
TIME ELAPSED COUNT
2020-04-08T09:13:21 0 0
2020-04-08T09:13:21 0 1
Started at 2020-04-08T09:13:21, ended at 2020-04-08T09:13:51
Source: A=utf8mb4,D=xucl,P=3306,h=127001,p=,t=t1,u=xucl
Dest: A=utf8mb4,D=xucl_archive,P=3306,h=127001,p=,t=t1,u=xucl
SELECT 1
INSERT 1
DELETE 1
Action Count Time Pct
sleep 1 300002 9989
inserting 1 00213 007
commit 2 00080 003
select 2 00017 001
deleting 1 00005 000
other 0 00008 000
很明显,id=3这条记录并没有进行归档(我们这里是改了条件列,实际生产中可能是更改了其他列,造成归档数据不准确)
那么如何来解决这种情况的发生呢?
显然,数据库在数据库中可以通过加排它锁来防止其他程序修改对应的数据,pt-archiver其实早就已经帮我们考虑到了这样的情况,pt-archiver提供了两种选择
--for-update:Adds the FOR UPDATE modifier to SELECT statements
--share-lock:Adds the LOCK IN SHARE MODE modifier to SELECT statements
四、总结
pt-archiver作为归档工具无疑是MySQL DBA日常运维的大利器之一,在使用过程中在知道如何使用的基础上也能够知晓其原理
归档过程中最好能对归档记录进行加锁 *** 作,以免造成归档数据不准确
在主从环境中,归档过程最好控制速度,以免造成主从延迟
尽量控制好chunk的大小,不要过大,造成大事务
如果是在数据库里本身测试。那
declare @sd datetime
declare @ed datetime
set @sd =getdate()
insert into 大数据处理
set @ed=getdate()
上面二个时间一减就知道多少时间了。
如果是C#里
Stopwatch stopWatch = new Stopwatch();
stopWatchStart();
插入数据处理
stopWatchStop();
// Get the elapsed time as a TimeSpan value
TimeSpan ts = stopWatchElapsed;
// Format and display the TimeSpan value
string elapsedTime = StringFormat("{0:00}:{1:00}:{2:00}{3:00}",
tsHours, tsMinutes, tsSeconds,
tsMilliseconds / 10);
ConsoleWriteLine("RunTime " + elapsedTime);
1、调整数据结构的设计
这一部分在开发信息系统之前完成,程序员需要考虑是否使用ORACLE数据库的分区功能,对于经常访问的数据库表是否需要建立索引等。
2、调整应用程序结构设计
这一部分也是在开发信息系统之前完成,程序员在这一步需要考虑应用程序使用什么样的体系结构,是使用传统的Client/Server两层体系结构,还是使用Browser/Web/Database的三层体系结构。不同的应用程序体系结构要求的数据库资源是不同的。
3、调整数据库SQL语句
应用程序的执行最终将归结为数据库中的SQL语句执行,因此SQL语句的执行效率最终决定了ORACLE数据库的性能。ORACLE公司推荐使用ORACLE语句优化器(OracleOptimizer)和行锁管理器(row-levelmanager)来调整优化SQL语句。
4、调整服务器内存分配
内存分配是在信息系统运行过程中优化配置的,数据库管理员可以根据数据库运行状况调整数据库系统全局区(SGA区)的数据缓冲区、日志缓冲区和共享池的大小;还可以调整程序全局区(PGA区)的大小。需要注意的是,SGA区不是越大越好,SGA区过大会占用 *** 作系统使用的内存而引起虚拟内存的页面交换,这样反而会降低系统。
5、调整硬盘I/O
这一步是在信息系统开发之前完成的。数据库管理员可以将组成同一个表空间的数据文件放在不同的硬盘上,做到硬盘之间I/O负载均衡。
6、调整 *** 作系统参数
例如:运行在UNIX *** 作系统上的ORACLE数据库,可以调整UNIX数据缓冲池的大小,每个进程所能使用的内存大小等参数。
实际上,上述数据库优化措施之间是相互联系的。ORACLE数据库性能恶化表现基本上都是用户响应时间比较长,需要用户长时间的等待。但性能恶化的原因却是多种多样的,有时是多个因素共同造成了性能恶化的结果,这就需要数据库管理员有比较全面的计算机知识,能够敏感地察觉到影响数据库性能的主要原因所在。另外,良好的数据库管理工具对于优化数据库性能也是很重要的。
一、ORACLE数据库性能优化工具
常用的数据库性能优化工具有:
ORACLE数据库在线数据字典,ORACLE在线数据字典能够反映出ORACLE动态运行情况,对于调整数据库性能是很有帮助的。
*** 作系统工具,例如UNIX *** 作系统的vmstat,iostat等命令可以查看到系统系统级内存和硬盘I/O的使用情况,这些工具对于管理员弄清出系统瓶颈出现在什么地方有时候很有用。
SQL语言跟踪工具(SQLTRACEFACILITY),SQL语言跟踪工具可以记录SQL语句的执行情况,管理员可以使用虚拟表来调整实例,使用SQL语句跟踪文件调整应用程序性能。SQL语言跟踪工具将结果输出成一个 *** 作系统的文件,管理员可以使用TKPROF工具查看这些文件。
ORACLEEnterpriseManager(OEM),这是一个图形的用户管理界面,用户可以使用它方便地进行数据库管理而不必记住复杂的ORACLE数据库管理的命令。
EXPLAINPLAN——SQL语言优化命令,使用这个命令可以帮助程序员写出高效的SQL语言。
二、ORACLE数据库的系统性能评估
信息系统的类型不同,需要关注的数据库参数也是不同的。数据库管理员需要根据自己的信息系统的类型着重考虑不同的数据库参数。
1、在线事务处理信息系统(OLTP),这种类型的信息系统一般需要有大量的Insert、Update *** 作,典型的系统包括民航机票发售系统、银行储蓄系统等。OLTP系统需要保证数据库的并发性、可靠性和最终用户的速度,这类系统使用的ORACLE数据库需要主要考虑下述参数:
数据库回滚段是否足够
是否需要建立ORACLE数据库索引、聚集、散列
系统全局区(SGA)大小是否足够
SQL语句是否高效
2、数据仓库系统(DataWarehousing),这种信息系统的主要任务是从ORACLE的海量数据中进行查询,得到数据之间的某些规律。数据库管理员需要为这种类型的ORACLE数据库着重考虑下述参数:
是否采用B-索引或者bitmap索引
是否采用并行SQL查询以提高查询效率
是否采用PL/SQL函数编写存储过程
有必要的话,需要建立并行数据库提高数据库的查询效率
三、SQL语句的调整原则
SQL语言是一种灵活的语言,相同的功能可以使用不同的语句来实现,但是语句的执行效率是很不相同的。程序员可以使用EXPLAINPLAN语句来比较各种实现方案,并选出最优的实现方案。总得来讲,程序员写SQL语句需要满足考虑如下规则:
1、尽量使用索引。试比较下面两条SQL语句:
语句A:SELECTdname,deptnoFROMdeptWHEREdeptnoNOTIN
(SELECTdeptnoFROMemp);
语句B:SELECTdname,deptnoFROMdeptWHERENOTEXISTS
(SELECTdeptnoFROMempWHEREdeptdeptno=empdeptno);
这两条查询语句实现的结果是相同的,但是执行语句A的时候,ORACLE会对整个emp表进行扫描,没有使用建立在emp表上的deptno索引,执行语句B的时候,由于在子查询中使用了联合查询,ORACLE只是对emp表进行的部分数据扫描,并利用了deptno列的索引,所以语句B的效率要比语句A的效率高一些。
2、选择联合查询的联合次序。考虑下面的例子:
SELECTstuffFROMtabaa,tabbb,tabcc
WHEREaacolbetween:alowand:ahigh
ANDbbcolbetween:blowand:bhigh
ANDcccolbetween:clowand:chigh
ANDakey1=bkey1
AMDakey2=ckey2;
这个SQL例子中,程序员首先需要选择要查询的主表,因为主表要进行整个表数据的扫描,所以主表应该数据量最小,所以例子中表A的acol列的范围应该比表B和表C相应列的范围小。
3、在子查询中慎重使用IN或者NOTIN语句,使用where(NOT)exists的效果要好的多。
4、慎重使用视图的联合查询,尤其是比较复杂的视图之间的联合查询。一般对视图的查询最好都分解为对数据表的直接查询效果要好一些。
5、可以在参数文件中设置SHARED_POOL_RESERVED_SIZE参数,这个参数在SGA共享池中保留一个连续的内存空间,连续的内存空间有益于存放大的SQL程序包。
6、ORACLE公司提供的DBMS_SHARED_POOL程序可以帮助程序员将某些经常使用的存储过程“钉”在SQL区中而不被换出内存,程序员对于经常使用并且占用内存很多的存储过程“钉”到内存中有利于提高最终用户的响应时间。
四、CPU参数的调整
CPU是服务器的一项重要资源,服务器良好的工作状态是在工作高峰时CPU的使用率在90%以上。如果空闲时间CPU使用率就在90%以上,说明服务器缺乏CPU资源,如果工作高峰时CPU使用率仍然很低,说明服务器CPU资源还比较富余。
使用 *** 作相同命令可以看到CPU的使用情况,一般UNIX *** 作系统的服务器,可以使用sar_u命令查看CPU的使用率,NT *** 作系统的服务器,可以使用NT的性能管理器来查看CPU的使用率。
数据库管理员可以通过查看v$sysstat数据字典中“CPUusedbythissession”统计项得知ORACLE数据库使用的CPU时间,查看“OSUserlevelCPUtime”统计项得知 *** 作系统用户态下的CPU时间,查看“OSSystemcallCPUtime”统计项得知 *** 作系统系统态下的CPU时间, *** 作系统总的CPU时间就是用户态和系统态时间之和,如果ORACLE数据库使用的CPU时间占 *** 作系统总的CPU时间90%以上,说明服务器CPU基本上被ORACLE数据库使用着,这是合理,反之,说明服务器CPU被其它程序占用过多,ORACLE数据库无法得到更多的CPU时间。
数据库管理员还可以通过查看v$sesstat数据字典来获得当前连接ORACLE数据库各个会话占用的CPU时间,从而得知什么会话耗用服务器CPU比较多。
出现CPU资源不足的情况是很多的:SQL语句的重解析、低效率的SQL语句、锁冲突都会引起CPU资源不足。
1、数据库管理员可以执行下述语句来查看SQL语句的解析情况:
SELECTFROMV$SYSSTATWHERENAMEIN
('parsetimecpu','parsetimeelapsed','parsecount(hard)');
这里parsetimecpu是系统服务时间,parsetimeelapsed是响应时间,用户等待时间,waitetime=parsetimeelapsed_parsetimecpu
由此可以得到用户SQL语句平均解析等待时间=waitetime/parsecount。这个平均等待时间应该接近于0,如果平均解析等待时间过长,数据库管理员可以通过下述语句
SELECTSQL_TEXT,PARSE_CALLS,EXECUTIONSFROMV$SQLAREA
ORDERBYPARSE_CALLS;
来发现是什么SQL语句解析效率比较低。程序员可以优化这些语句,或者增加ORACLE参数SESSION_CACHED_CURSORS的值。
2、数据库管理员还可以通过下述语句:
SELECTBUFFER_GETS,EXECUTIONS,SQL_TEXTFROMV$SQLAREA;
查看低效率的SQL语句,优化这些语句也有助于提高CPU的利用率。
3、数据库管理员可以通过v$system_event数据字典中的“latchfree”统计项查看ORACLE数据库的冲突情况,如果没有冲突的话,latchfree查询出来没有结果。如果冲突太大的话,数据库管理员可以降低spin_count参数值,来消除高的CPU使用率。
五、内存参数的调整
内存参数的调整主要是指ORACLE数据库的系统全局区(SGA)的调整。SGA主要由三部分构成:共享池、数据缓冲区、日志缓冲区。
1、共享池由两部分构成:共享SQL区和数据字典缓冲区,共享SQL区是存放用户SQL命令的区域,数据字典缓冲区存放数据库运行的动态信息。数据库管理员通过执行下述语句:
select(sum(pins-reloads))/sum(pins)"LibCache"fromv$librarycache;
来查看共享SQL区的使用率。这个使用率应该在90%以上,否则需要增加共享池的大小。数据库管理员还可以执行下述语句:
select(sum(gets-getmisses-usage-fixed))/sum(gets)"RowCache"fromv$rowcache;
查看数据字典缓冲区的使用率,这个使用率也应该在90%以上,否则需要增加共享池的大小。
2、数据缓冲区。数据库管理员可以通过下述语句:
SELECTname,valueFROMv$sysstatWHEREnameIN('dbblockgets','consistentgets','physicalreads');
来查看数据库数据缓冲区的使用情况。查询出来的结果可以计算出来数据缓冲区的使用命中率=1-(physicalreads/(dbblockgets+consistentgets))。
这个命中率应该在90%以上,否则需要增加数据缓冲区的大小。
3、日志缓冲区。数据库管理员可以通过执行下述语句:
selectname,valuefromv$sysstatwherenamein('redoentries','redologspacerequests');
查看日志缓冲区的使用情况。查询出的结果可以计算出日志缓冲区的申请失败率:
申请失败率=requests/entries,申请失败率应该接近于0,否则说明日志缓冲区开设太小,需要增加ORACLE数据库的日志缓冲区。
昌平北大青鸟java培训班转载自网络如有侵权请联系我们感谢您的关注谢谢支持
以上就是关于英语the elapsed cpu time怎么翻译全部的内容,包括:英语the elapsed cpu time怎么翻译、GBase 8a数据库通过LOAD方式加载时,如果出现功能报错,如何排查、php时间问题mysql数据库的时间格式(Y-M-D H:I:S) 在PHP页面想这样显示(Y-M-D) ('.$rows['ndate'].')等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)