如何提高db2日志文件系统高性能日志系统

db2中更改日志文件大小及其个数
db2中更改日志文件大小及其个数比较简单,只需要修改2个参数即可,比ORACLE方便的多。
默认日志文件放在SQLOGDIR目录下。
[huateng@db2server SQLOGDIR]$ pwd
/home/huateng/huateng/NODE0000/SQL00001/SQLOGDIR
[huateng@db2server SQLOGDIR]$ ls -lh
总计 53M & &
-rw------- 1 huateng huateng 4.1M 03-30 06:26 S0000011.LOG
-rw------- 1 huateng huateng 4.1M 03-30 06:26 S0000012.LOG
-rw------- 1 huateng huateng 4.1M 03-30 06:26 S0000013.LOG
-rw------- 1 huateng huateng 4.1M 03-30 06:26 S0000014.LOG
-rw------- 1 huateng huateng 4.1M 03-30 06:26 S0000015.LOG
-rw------- 1 huateng huateng 4.1M 03-30 06:26 S0000016.LOG
-rw------- 1 huateng huateng 4.1M 03-30 06:26 S0000017.LOG
-rw------- 1 huateng huateng 4.1M 03-30 06:26 S0000018.LOG
-rw------- 1 huateng huateng 4.1M 03-30 06:26 S0000019.LOG
-rw------- 1 huateng huateng 4.1M 03-30 06:26 S0000020.LOG
-rw------- 1 huateng huateng 4.1M 03-30 06:26 S0000021.LOG
-rw------- 1 huateng huateng 4.1M 03-30 06:26 S0000022.LOG
-rw------- 1 huateng huateng 4.1M 03-30 06:26 S0000023.LOG
[huateng@db2server SQLOGDIR]$ db2 connect to dbtest
& &Database Connection Information
&Database server & & & &= DB2/LINUX 9.7.0
&SQL authorization ID & = HUATENG
&Local database alias & = DBTEST
[huateng@db2server SQLOGDIR]$ db2 get db cfg | grep LOGPRIMARY
&Number of primary log files & & & & & & & &(LOGPRIMARY) = 13
[huateng@db2server SQLOGDIR]$ db2 get db cfg | grep LOGFILSIZ
&Log file size (4KB) & & & & & & & & & & & & (LOGFILSIZ) = 1024
当前日志文件数为13,大小大约为4M。
下面将日志文件数改为3个,大小为16M。
[huateng@db2server SQLOGDIR]$ db2 update db cfg using LOGPRIMARY 3
SQL5153N &The update cannot be completed because the following relationship&
would be violated: &softmax &= 100 * logprimary&. & &
[huateng@db2server SQLOGDIR]$ db2 get db cfg | grep -i softmax
&Percent log file reclaimed before soft chckpt (SOFTMAX) = 520
[huateng@db2server SQLOGDIR]$ db2 update db cfg using SOFTMAX 200
DB20000I &The UPDATE DATABASE CONFIGURATION command completed successfully.
SQL1363W &One or more of the parameters submitted for immediate modification&
were not changed dynamically. For these configuration parameters, all&
applications must disconnect from this database before the changes become&
effective.
[huateng@db2server SQLOGDIR]$ db2 update db cfg using LOGPRIMARY 3
DB20000I &The UPDATE DATABASE CONFIGURATION command completed successfully.
SQL1363W &One or more of the parameters submitted for immediate modification&
were not changed dynamically. For these configuration parameters, all&
applications must disconnect from this database before the changes become&
effective.
[huateng@db2server SQLOGDIR]$ db2 update db cfg using LOGFILSIZ 4096
DB20000I &The UPDATE DATABASE CONFIGURATION command completed successfully.
SQL1363W &One or more of the parameters submitted for immediate modification&
were not changed dynamically. For these configuration parameters, all&
applications must disconnect from this database before the changes become&
effective.
[huateng@db2server SQLOGDIR]$ db2 force applications all
DB20000I &The FORCE APPLICATION command completed successfully.
DB21024I &This command is asynchronous and may not be effective immediately.
[huateng@db2server SQLOGDIR]$ db2stop
06:34:01 & & 0 & 0 & SQL1064N &DB2STOP processing was successful.
SQL1064N &DB2STOP processing was successful.
[huateng@db2server SQLOGDIR]$ db2start
03/30/:32 & & 0 & 0 & SQL1063N &DB2START processing was successful.
SQL1063N &DB2START processing was successful.
[huateng@db2server SQLOGDIR]$ db2 connect to dbtest
& &Database Connection Information
&Database server & & & &= DB2/LINUX 9.7.0
&SQL authorization ID & = HUATENG
&Local database alias & = DBTEST & &&
[huateng@db2server SQLOGDIR]$ ls -lh
-rw------- 1 huateng huateng 17M 03-30 06:31 S0000011.LOG
-rw------- 1 huateng huateng 17M 03-30 06:31 S0000012.LOG
-rw------- 1 huateng huateng 17M 03-30 06:31 S0000013.LOG
-rw------- 1 huateng huateng 17M 03-30 06:31 S0000014.LOG
-rw------- 1 huateng huateng 17M 03-30 06:31 S0000015.LOG
-rw------- 1 huateng huateng 17M 03-30 06:31 S0000016.LOG
-rw------- 1 huateng huateng 17M 03-30 06:31 S0000017.LOG
-rw------- 1 huateng huateng 17M 03-30 06:31 S0000018.LOG
-rw------- 1 huateng huateng 17M 03-30 06:31 S0000019.LOG
-rw------- 1 huateng huateng 17M 03-30 06:31 S0000020.LOG
-rw------- 1 huateng huateng 17M 03-30 06:31 S0000021.LOG
-rw------- 1 huateng huateng 17M 03-30 06:31 S0000022.LOG
-rw------- 1 huateng huateng 17M 03-30 06:31 S0000023.LOG
-rw------- 1 huateng huateng 512 03-30 06:31 SQLLPATH.TAG
不过日志组数看起来没有改变,这是因为当前的配置在归档模式.
[huateng@db2server SQLOGDIR]$ db2 get db cfg | grep LOG
&Catalog cache size (4KB) & & & & & & &(CATALOGCACHE_SZ) = 190
&Log buffer size (4KB) & & & & & & & & & & & &(LOGBUFSZ) = 256
&Log file size (4KB) & & & & & & & & & & & & (LOGFILSIZ) = 4096
&Number of primary log files & & & & & & & &(LOGPRIMARY) = 3
&Number of secondary log files & & & & & & & (LOGSECOND) = 4
&Changed path to log files & & & & & & & & &(NEWLOGPATH) =&
&Path to log files & & & & & & & & & & & & & & & & & & & = /home/huateng/huateng/NODE0000/SQL00001/SQLOGDIR/
&Overflow log path & & & & & & & & & & (OVERFLOWLOGPATH) =&
&Mirror log path & & & & & & & & & & & & (MIRRORLOGPATH) =&
&First active log file & & & & & & & & & & & & & & & & & = S0000011.LOG
&Block log on disk full & & & & & & & &(BLK_LOG_DSK_FUL) = NO
&Block non logged operations & & & & & &(BLOCKNONLOGGED) = NO
&Percent max primary log space by transaction &(MAX_LOG) = 0
&Num. of active log files for 1 active UOW(NUM_LOG_SPAN) = 0
&Log retain for recovery enabled & & & & & & (LOGRETAIN) = RECOVERY
&First log archive method & & & & & & & & (LOGARCHMETH1) = DISK:/tmp/archivelog/
&Options for logarchmeth1 & & & & & & & & &(LOGARCHOPT1) =&
&Second log archive method & & & & & & & &(LOGARCHMETH2) = OFF
&Options for logarchmeth2 & & & & & & & & &(LOGARCHOPT2) = & &&
&Log pages during index build & & & & & &(LOGINDEXBUILD) = OFF
[huateng@db2server SQLOGDIR]$ db2 update db cfg using LOGARCHMETH1 off
0000I &The UPDATE DATABASE CONFIGURATION command completed successfully.
SQL1363W &One or more of the parameters submitted for immediate modification&
were not changed dynamically. For these configuration parameters, all&
applications must disconnect from this database before the changes become&
effective.
[huateng@db2server SQLOGDIR]$ db2 connect reset
DB20000I &The SQL command completed successfully.
[huateng@db2server SQLOGDIR]$ db2stop
06:36:36 & & 0 & 0 & SQL1064N &DB2STOP processing was successful.
SQL1064N &DB2STOP processing was successful.
[huateng@db2server SQLOGDIR]$ db2start
03/30/:40 & & 0 & 0 & SQL1063N &DB2START processing was successful.
SQL1063N &DB2START processing was successful.
[huateng@db2server SQLOGDIR]$ db2 connect to dbtest
& &Database Connection Information
&Database server & & & &= DB2/LINUX 9.7.0
&SQL authorization ID & = HUATENG
&Local database alias & = DBTEST
[huateng@db2server SQLOGDIR]$ ls -lh
-rw------- 1 huateng huateng 17M 03-30 06:36 S0000000.LOG
-rw------- 1 huateng huateng 17M 03-30 06:36 S0000001.LOG
-rw------- 1 huateng huateng 17M 03-30 06:36 S0000002.LOG
作者 TOMSYAN
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'DB2增加文件系统空间_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
DB2增加文件系统空间
上传于||文档简介
&&D​B增​加​文​件​系​统​空​间
大小:3.36KB
登录百度文库,专享文档复制特权,财富值每天免费拿!
你可能喜欢您所在的位置: &
在Windows上调优DB2数据库的八个简单步骤(3)
在Windows上调优DB2数据库的八个简单步骤(3)
Sandeep Sethia, Vaibhav Kulkarni
为了更好地诊断性能问题,本文讨论了一个有条理的过程,帮助确定数据库是否存在性能问题,并制定补救措施。当 DB2或电子商务应用程序的性能未达到预期目标时,整个组织和财务底线都可能受到影响。
选择正确的诊断工具
对于普通的监视,perfmon 是一个很好用的工具。还可以保存其日志,以便更轻松地比较系统在按预期工作时和系统有性能问题时的系统活动。这往往可以为手头上的问题提供有价值的线索。然而,快速查看任务管理器和资源监视器的数据有时也可以帮助实时查找系统中的瓶颈。一旦确定了瓶颈,就可以采取相应的措施来消除瓶颈。
步骤 2:I/O 瓶颈 & 详细研究
如果 perfmon 显示有一个或多个磁盘的磁盘时间在 80% 以上,或资源监视器显示有一个或多个磁盘上的活动时间在 80% 以上,那么这通常意味着系统中存在一个 I/O 瓶颈。可以从 perfmon 或资源监视器确定具有很高利用率的一个或多个磁盘。一旦确定了大量使用的磁盘,就可以找出放置在磁盘上的内容。
是否有任何 DB2 表空间容器放置在磁盘上?
&db2 list tablespace containers for &tbsid&
对数据库中的所有表空间重复此命令。
或者,DB2 日志文件是否被放置在大量使用的磁盘上?
&db2 get db cfg for &dbname&
搜索 newlogpath 数据库配置参数。
或者,这些磁盘是否包含实用程序文件,比如备份目标或加载文件?查看已执行的备份/负载命令。根据大量使用的磁盘上的内容,解决方案也会有所不同。
表空间容器上的磁盘瓶颈
如果将大量使用的磁盘分配到表空间容器,那么请找出表空间中的对象。如果表空间对应于某个数据表空间,那么请找出在表空间中创建的表。
&db2 select tabname from syscat.tables where tbspaceid = &hot tablespace id&
从 MON_GET_TABLE 表函数中找出最活跃的表。下面的查询将列出具有最多行读取的表。
清单 1. 表空间中最活跃的表
db2&&select&varchar(tabschema,20)&as&tabschema,&varchar(tabname,20)&as&tabname, &&&&&&table_scans,&sum(rows_read)&as&total_rows_read,& &&&&&&sum(rows_inserted)&as&total_rows_inserted,& &&&&&&sum(rows_updated)&as&total_rows_updated,& &&&&&&sum(rows_deleted)&as&total_rows_deleted& &FROM&TABLE(MON_GET_TABLE('','',-2))&AS&t& &WHERE&TBSP_ID&=&hot&tablespace&id &GROUP&BY&tabschema,&tabname& &ORDER&BY&total_rows_read&DESC&&
注意:MON_GET_TABLE 函数提供了许多有用的信息。它在表上跟踪表扫描的数量。如果表扫描较多,那么可能意味着该表没有适当的索引,或者查询没有使用表上现有的索引。
一旦确定了活跃的表,就可以使用 MON_GET_PKG_CACHE_STMT 表函数轻松找出表上执行的 SQL 语句。
清单 2. 找出给定表上的查询
db2&&select&section_type,&executable_id,&package_name,num_executions, &char(stmt_text,&100)& &from&table&(MON_GET_PKG_CACHE_STMT&(&'D',&NULL,&NULL,&-2))&as&T &where&stmt_text&like&'%hot&table&name%'&&&
通过这种方式,很容易找出活跃的表上导致大量读取/写入操作的 SQL 语句。使用 Design Advisor 确定 SQL 语句是否使用了表上正确的索引。如果表中有适当的指标,但没有用到这些指标,那么请检查表上的统计信息是否是最新信息。不正确或过时的统计信息可能会导致优化器选择一个次优的访问计划。
临时表空间上的磁盘瓶颈
如果将大量使用的磁盘分配到临时表空间,这表示数据库上有大量排序活动。高水平的临时表空间 I/O 活动往往与结果集较大或有大量排序的大查询一起出现。在这种情况下,需要确定是否有大量排序溢出到磁盘。 MON_GET_PKG_CACHE_STMT 可以提供造成排序溢出的 SQL 语句。
清单 3. 有大量排序活动的查询
db2&&select&section_type,&package_name,num_executions,&total_sorts,&sort_overflows, &char(stmt_text,&100)& &from&table&(MON_GET_PKG_CACHE_STMT&(&'D',&NULL,&NULL,&-2))&as&T &where&sort_overflows&&1& &order&by&sort_overflows&desc&&
如果有太多排序溢出,那么请检查 SORTHEAP 或 SHEAPTHRES 配置参数是否被设置为较低的值。如果排序的相关参数得到正确设置,那么请确定是否有可能通过创建索引来避免出现大量排序。对排序量较大的查询使用 Design Advisor,查看是否能够通过创建额外的索引来避免或减少排序。
事务日志上的磁盘瓶颈
在 OLTP 环境中,事务日志的性能是非常敏感的。MON_GET_TRANSACTION_LOG 表函数提供了有关事务日志的详细活动。
清单 4. 事务日志活动
db2&&select&log_reads,&log_read_time,&log_write,&log_write_time,&num_log_buffer_full, &num_log_data_found_in_buffer &from&table(MON_GET_TRANSACTION_LOG(-1))&as&T&&&
num_log_buffer_full 显示了在将新的日志写入缓冲区之前,日志缓冲区被充满并且必须刷新到磁盘的次数。如果这个数字在一段时间内一直在增加,则意味着日志缓冲区对于数据库上的工作负载而言过小。增大 LOGBUFSZ 数据库参数值有助于提高日志性能,并减少事务日志磁盘上的 I/O。
num_log_data_found_in_buffer 显示了代理从缓冲区中读取日志数据的次数。从缓冲区中读取日志数据优于从磁盘读取日志数据,因为后者较慢。可以结合使用此元素和 num_log_read_io element,以确定是否需要进一步增大 LOGBUFSZ 数据库配置参数。
步骤 3:CPU 瓶颈 & 详细研究
如果 perfmon 或资源监视器显示有一个或多个 CPU 的使用率超过 90%,那么这通常意味着系统存在 CPU 瓶颈。与 I/O 瓶颈一样,第一个步骤是识别消耗大量 CPU 的数据库操作。通常情况下,已知道有一些数据库操作会消耗大量的 CPU:
LOAD、BACKUP、runstats 等实用工具
大量排序活动
要确定在查询编译中是否花费了大量 CPU,请查询 MON_GET_WORKLOAD 表函数。
清单 5. 在不同活动中花费的 CPU 时间
db2&&select&varchar(workload_name,30)&as&workload_name, &sum(total_cpu_time),sum(total_compile_proc_time), &sum(act_rqsts_total),&sum(total_compilations), &sum(total_act_time),&sum(pkg_cache_inserts),& &sum(pkg_cache_lookups)& &from&TABLE(MON_GET_WORKLOAD('',-2))&as&T &group&by&workload_name&&
如果 compile_proc_time 高于 5-10% 的 total_cpu_time,并且 pkg_cache_inserts/pkg_cache_lookups 高于 4-5%,则数据库在语句编译上花费了太多的时间。这可能是因为查询被重复编译,或者是因为包缓存过小,查询必须迁离到其他地方,以便为新的查询腾出空间。如果应用程序使用字符串文本而不是参数标记符,则会重复编译 SQL 语句。在 DB2 9.7 和 10.1 中,DB2 提供了一个数据库配置参数 STMT_CONC(语句集中器)。当启用该参数时,语句集中器会修改动态语句,以便允许共享更多的包缓存条目,并减少语句编译。
要找出造成高 CPU 利用率的所有实用工具,请查询 MON_GET_WORKLOAD 表函数。返回的指标展示了用于已提交的请求的所有指标的汇总,这些请求是由映射到已识别工作负载对象的连接提交的。在请求的执行过程中,指标在工作单元边界上或定期被汇总到一个工作负载。由该表函数报告的值,反映系统在最近一次汇总时的当前状态。指标是严格递增的值。为了确定在某时间间隔花费在 LOAD 和 reorg 等实用工具中的时间,可以使用 MON_GET_WORKLOAD 查询在时间间隔的开始和结束时使用的指标,并计算其差异。
清单 6. 在 LOAD 和 runstat 实用工具中花费的 CPU 时间
db2&&select&varchar(workload_name,30)&as&workload_name, &sum(total_loads),&sum(total_load_proc_time), &sum(total_runstats),&sum(total_runstats_proc_time) &from&TABLE(MON_GET_WORKLOAD('',-2))&as&T& &group&by&workload_name&&
LOAD 等实用工具旨在充分利用可用资源,最大限度地提高性能。如果这些实用工具占用了比预期多的 CPU,那么可以通过设置 util_impact_limit 数据库配置参数对实用程序进行节流。另一个占用大量 CPU 的数据库操作是 sort。正如在 I/O 瓶颈部分所介绍的,找出执行最多排序活动的查询,并使用 Design Advisor 确定是否可通过创建额外的索引来避免排序。
步骤 4:内存瓶颈
内存瓶颈并不是很常见,主要是因为数据库的堆和参数可以根据可用内存进行设置。大多数 DB2?? 堆是自动的,并基于可用内存提供分配值。STMM 在利用可用内存和将内存分配给最需要内存的堆这两方面做得很好。但是,在不使用 STMM 的情况下,有可能存在内存使用不当的情况,如果内存分配得过多(也就是说,分配值高于可用内存),则有可能导致大量分页活动。如果 Perfmon 或资源监视器显示了许多分页活动,这通常是因为分配给不同堆的内存已超过实际内存。在这种情况下,最好是打开 STMM,让 DB2 调优缓冲池、排序堆和其他堆的内存。
步骤 5:网络瓶颈
出现网络瓶颈的原因通常是存在大量四处移动的数据(比如非常大的结果集和客户端负载等),或者操纵 LOB 的应用程序位于客户端-服务器架构中。MON_DB_SUMMARY 管理视图很好地说明了等待不同的资源所花费的时间。NETWORK_WAIT_TIME_PERCENT 字段提供了等待网络响应的时间百分比。通常情况下,等待网络所花费的时间应该小于 1%。如果该值高出几个百分点,并且 perfmon 和资源监视器显示网络带宽在大量被占用,那么系统可能遇到了网络瓶颈。在这种情况下,应用程序可以将一些应用程序逻辑以存储过程或者 UDF 的形式移动到服务器。在客户端负载的情况下,可以将负载拆分为更小的部分,在不同的时间执行它们,而不是一次全部加载它们,这样做可以减少网络流量。
步骤 6:锁定问题
如果系统没有任何资源瓶颈,但性能仍然较差,这可能是因为锁定问题。MON_DB_SUMMARY 管理视图中的 LOCK_WAIT_TIME_ PERCENT 字段提供一个高层次的视图,说明了在数据库级别的锁等待上花费的时间。为了获得在锁等待中花费了时间的工作负载的详细视图,请查询 MON_GET_WORKLOAD 监视器表函数。
清单 7. 在锁等待中花费的时间
db2&&SELECT&varchar(workload_name,30)&as&workload_name, &sum(lock_wait_time)&as&total_lock_wait_time, &sum(lock_waits)&as&total_lock_waits, &sum(lock_timeouts)&as&total_lock_timeouts,& &sum(lock_escals)&as&total_lock_escals& &FROM&TABLE(MON_GET_WORKLOAD('',-2))&AS&t &GROUP&BY&workload_name& &ORDER&BY&total_lock_wait_time&DESC&&
内容导航&第 1 页: &第 2 页: &第 3 页: &第 4 页:
关于&&的更多文章
10月17日,微软正式发布了Windows 8的首个重大升级――Windows 8
Linux界极具活力,面向不同的用户可以使用不同的Linux发行版,比如适合新手和游戏爱好者等。
Fedora 19(代号“薛定谔的猫”)最终正式版已经出炉
历经一年的开发与测试,Linux Deepin 12.12 正式版本
Windows 8.1关注度日益增高,最新的Aapps商店和应用程
本书是对《网管员必读―网络管理》第1版的全面重写,因为书中所涉及的两个主要网络操作系统都已升级。本书介绍的是Windows Serve
51CTO旗下网站天极传媒:天极网全国分站
您现在的位置:
& &&在DB2中提高Insert性能的技巧
在DB2中提高Insert性能的技巧论坛整理 09:24
  INSERT 处理过程概述
  首先让我们快速地看看一行时的处理步骤。这些步骤中的每一步都有优化的潜力,对此我们在后面会一一讨论。
  1、在客户机准备 语句。对于动态 SQL,在语句执行前就要做这一步,此处的性能是很重要的;对于静态 SQL,这一步的性能实际上关系不大,因为语句的准备是事先完成的。
  2、在客户机,将要插入的行的各个 列值组装起来,发送到 DB2。
  3、 服务器确定将这一行插入到哪一页中。
  4、DB2 在 用于该页的缓冲池中预留一个位置。如果 DB2 选定的是一个已有的页,那么就需要读磁盘;如果使用一个新页,则要在表空间(如果是SMS,也就是系统管理存储的表空间)中为该页物理地分配空间。插入了新行的每一页最后都要从缓冲池写入到磁盘。
  5、在目标页中对该行进行格式化,并获得该行上的一个X(exclusive,独占的) 行锁。
  6、将反映该 insert 的一条记录写入到日志缓冲区中。
  7、最后提交包含该 insert 的事务,如果这时日志缓冲区中的记录还没有被写入日志文件的话,则将这些记录写到日志文件中。
  此外,还可能发生很多类型的附加处理,这取决于数据库配置,例如,索引或触发器的存在。这种额外的处理对于性能来说也是意义重大的,我们在后面会讨论到。
  insert 的替代方案
  在详细讨论 insert 的优化之前,让我们先考虑一下 insert 的两种替代方案:load 和 import。import 实用程序实际上是 SQL INSERT 的一个前端,但它的某些功能对于您来说也是有用的。load 也有一些有用的额外功能,但是我们使用 load 而不使用 insert 的主要原因是可以提高性能。
  load 直接格式化数据页,而避免了由于插入导致的对每一行进行处理的大部分开销(例如,日志记录在这里实际上是消除了)。而且,load 可以更好地利用多处理器机器上的并行性。在 load 中有两个新功能,它们对于 load 成为 insert 的替代方案有着特别的功效,这两个功能是:从游标装载和从调用层接口(CLI)程序装载。
  从游标装载
  这种方法可用于应用程序的程序代码(通过 db2Load API),或用于 DB2 脚本。下面是后一种情况的一个例子:
  declare staffcursor cursor forselect *
  load from staffcursor of cursor insert into myschema.new_
  这两行可以用下面一行替代:
  insert into myschema.new_staff select * from staff
  同等效的 INSERT ... SELECT 语句相比,从游标装载几乎可以提高 20% 的性能。
  从 CLI 装载
  这种方法显然只限于调用层接口(CLI)应用程序,但是它非常快。这种技巧非常类似于数组插入,DB2 附带了这样的示例,使用 load 时的速度是使用经过完全优化的数组插入时的两倍,几乎要比未经优化的数组插入快 10 倍。
  所有 insert 可以改进的地方
  让我们看看插入处理的一些必要步骤,以及我们可以用来优化这些步骤的技巧。
  1. 语句准备
  作为一条 SQL 语句,INSERT 语句在执行之前必须由 DB2 进行编译。这一步骤可以自动发生(例如在 CLP 中,或者在一次 CLI SQLExecDirect 调用中),也可以显式地进行(例如,通过一条 SQL Prepare、CLI SQLPrepare 或 JDBC prepareStatement 语句)。该编译过程牵涉到授权检查、优化,以及将语句转化为可执行格式时所需的其他一些活动。在编译语句时,语句的访问计划被存储在包缓存中。
  如果重复地执行相同的 INSERT 语句,则该语句的访问计划(通常)会进入到包缓存中,这样就免除了编译的开销。然而,如果 insert 语句对于每一行有不同的值,那么每一条语句都将被看成是惟一的,必须单独地进行编译。因此,将像下面这样的重复语句:
  insert into mytable values (1, 'abc')
  insert into mytable values (2, 'def')
  等等,
  换成带有参数标记的语句,一次准备,重复执行,这样做是十分可取的:
  insert into mytable values (?, ?)
  使用参数标记可以让一系列的 insert 的运行速度提高数倍。(在静态 SQL 程序中使用主机变量也可以获得类似的好处。)
  2. 发送列值到服务器
  可以归为这一类的优化技巧有好几种。最重要的一种技巧是在每条 insert 语句中包括多行,这样就可以避免对于每一行都进行客户机-服务器通信,同时也减少了 DB2 开销。可用于多行插入的技巧有:
在 VALUES 子句中包含多行的内容。例如,下面的语句将插入三行:INSERT INTO mytable VALUES (1, 'abc'), (2, 'def'), (3, 'ghi')
在 CLI 中使用数组插入(array insert)。这需要准备一条带参数标记的 INSERT 语句,定义一个用于存储要插入的值的数组,将该数组绑定到参数标记,以及对于每个数组中的一组内容执行一次 insert。而且,示例程序 sqllib/samples/cli/tbload.c 提供了数组插入的基本框架(但是执行的是 CLI LOAD)。从不使用数组改为使用包含 100 行的数组,可以将时间缩短大约 2.5 倍。所以应该尽可能地使用包含至少 100 行的数组。
在 JDBC 中使用批处理操作。这跟 CLI 中的数组插入一样,基于相同的概念,但是实现细节有所不同。当通过 prepareStatement 方法准备了 insert 语句之后,剩下的步骤是针对每一列调用适当的 setXXXX 方法(例如,setString 或 setInt),然后是 addBatch。对于要插入的每一行,都要重复这些步骤,然后调用 executeBatch 来执行插入。要查看这方面的例子,请参阅“参考资料”一节中的 JDBC Tutorial。
使用 load 将数据快速地装入到一个 staging 表中,然后使用 INSERT ... SELECT 填充主表。(通过这种方法节省下来的代价源于 load 的速度非常快,再加上 INSERT ... SELECT 是在 DB2 内(在服务器上)传输数据的,从而消除了通信上的代价。一般情况下我们不会使用这种方法,除非在 INSERT ... SELECT 中还要另外做 load 无法完成的处理。
  如果不可能在一条 insert 语句中传递多行,那么最好是将多条 insert 语句组成一组,将它们一起从客户机传递到服务器。(不过,这意味着每条 insert 都包含不同的值,都需要准备,因而其性能实际上要比使用参数标记情况下的性能更差一些。)将多条语句组合成一条语句可以通过 Compound SQL 来实现:
在 SQL 中,复合语句是通过 BEGIN ATOMIC 或 BEGIN COMPOUND 语句创建的。
在 CLI 中,复合语句可以通过 SQLExecDirect 和 SQLExecute 调用来建立。对于 DB2 V8 FixPak 4,另一种生成复合语句的方法是在(对一条预处理语句)发出多个 SQLExecute 调用之前设置语句属性 SQL_ATTR_CHAINING_BEGIN,并在调用之后设置语句属性 SQL_ATTR_CHAINING_END。
  下面是关于该话题的其他一些建议:
如果可能的话,让客户机与要存取的数据库使用相同的代码页,以避免在服务器上的转换代价。数据库的代码页可以通过运行“get db cfg for ”来确定。
在某些情况下,CLI 会自动执行数据类型转换,但是这样同时也会带来看不见的(小小的)性能损耗。因此,尽量使插入值直接处于与相应列对应的格式。
将应用程序中与插入相关的设置开销最小化。例如,当在 CLI 中使用数组插入时,对于整个一组插入,应该尽量保证对于每一列只执行一次 SQLBindParameter,而不是对每一组数组内容都执行一次。对于个体来说,这些调用的代价并不高,但是这些代价是累积的。
  3. 找到存储行的地方
  DB2 使用三种算法中的一种来确定将行插入到哪里。(如果使用了多维群集(Multi-dimensional Clustering,MDC),则另当别论,我们在这里不予讨论。)
  缺省模式是,DB2 搜索散布在表的各页上的自由空间控制记录(Free Space Control Records,FSCR),以找到有足够自由空间存放新行的页。显然,如果每页上的自由空间都比较少的话,就要浪费很多的搜索时间。为了应付这一点, DB2 提供了 DB2MAXFSCRSEARCH 注册表变量,以便允许将搜索范围限制为少于缺省的 5 页。
  当表是通过 ALTER TABLE 以 APPEND 模式放置时,就要使用第二种算法。这样就完全避免了 FSCR 搜索,因为只需简单地将行直接放到表的末尾。
  当表有群集索引(clustering index)时,就要用到最后一种算法。在这种情况下,DB2 试图将每一行插入到有相似键值的一页中。如果那一页没有空间了,DB2 就会尝试附近的页,如果附近的页也没有空间,DB2 就进行 FSCR 搜索。
  如果只考虑插入时间的优化,那么使用 APPEND 模式对于批量插入是最快的一种方法,但是这种方法的效果远不如我们这里讨论的很多其他方法那么成效显著。第二好的方法应该是采用缺省算法,但是,如果在最佳环境中,更改 DB2MAXFSCRSEARCH 的值影响很小,而在一个 I/O 约束较少的环境中,这种更改所造成的影响就比较可观了。
  如果有群集索引,则对 insert 的性能会有很大的负面影响,这一点也不惊奇,因为使用群集索引的目的就是通过在插入时做额外的工作来提高查询(即 select)性能的。如果的确需要群集索引,那么可以通过确保有足够的自由空间来使其对插入的影响降至最小:使用 ALTER TABLE 增加 PCTFREE,然后使用 REORG 预留自由空间。不过,如果允许太多自由空间的存在,则可能导致查询时需要读取额外的页,这反而大大违反了使用群集索引的本意。另一种选择是,在批量插入之前先删除群集索引,而后再重新创建群集索引,也许这是最优的方法(创建群集索引的开销跟创建常规索引的开销差不多,都不是很大,只是在插入时有额外的开销)。
  4. 缓冲池、I/O 和页清除
  每一条 insert 在执行时,都是先将新行存储在一个页中,并最终将那个页写到磁盘上。一旦像前面讨论的那样指定了页,那么在将行添加到该页之前,该页必须已经在缓冲池中。对于批量插入,大部分页都是最新指派给表的,因此让我们关注一下对新页的处理。
  如果表在系统管理存储的(System Managed Storage,SMS)表空间中,当需要新页时,缺省情况下是从文件系统中分别为每一页分配空间。但是,如果对数据库运行了 db2empfa 命令,那么每个 SMS 表空间就会为新页一次性分配一个区段。我们建议运行 db2empfa 命令,并使用 32 页的区段。
  对于数据库管理的存储(Database Managed Storage,DMS)表空间,空间是在创建表空间时就预先分配的,但是页的区段则是在插入处理过程中指派给表的。与 SMS 相比,DMS 对空间的预分配可以提高大约 20% 的性能 -- 使用 DMS 时,更改区段大小并没有明显的效果。
  如果表上有索引,则对于每个插入的行,都要添加一个条目到每条索引。这要求在缓冲池中存在适当的索引页。晚些时候我们将讨论索引的维护,但是现在只需记住,插入时对缓冲池和 I/O 的考虑也类似地适用于索引页,对于数据页也是一样。
  随着插入的进行,越来越多的页中将填入被插入的行,但是,DB2 不要求在 insert 或 Commit 后将任何新插入的或更新后的数据或索引写入到磁盘。(这是由于 DB2 的 writeahead 日志记录算法。但是有一个例外,这将在关于日志记录的小节中论述到。)然而,这些页需要在某一时刻写到磁盘上,这个时刻可能会在数据库关闭时才会轮到。
  一般来说,对于批量插入,您会希望积极地进行 异步页清除(asynchronous page cleaning),这样在缓冲池中就总有可用于新页的空余位置。页清除率,或者说总缺页率,可能导致计时上的很大不同,使得性能比较容易产生误解。例如,如果使用 100,000 页的缓冲池,并且不存在页清除,则批量插入在结束前不会有任何新的或更改过的(“脏的”)页写到磁盘上,但是随后的操作(例如选择,甚至乎关闭数据库)都将被大大推迟,因为这时有至多 100,000 个在插入时产生的脏页要写到磁盘上。另一方面,如果在同一情况下进行了积极的页清除,则批量插入过程可能要花更长的时间,但是此后缓冲池中的脏页要少一些,从而使得随后的任务执行起来性能更佳。至于那些结果中到底哪个要更好些,我们并不是总能分得清,但是通常来说,将所有脏页都存储在缓冲池中是不可能的,所以为了取得最佳性能,采取有效的页清除是有必要的。
  为了尽可能好地进行页清除:
将 CHNGPGS_THRESH 数据库配置参数的值从缺省的 60 减少到 5 这么低。这个参数决定缓冲池中脏页的阈值百分比,当脏页达到这个百分比时,就会启动页清除。
尝试启用注册表变量 DB2_USE_ALTERNATE_PAGE_CLEANING(在 DB2 V8 FixPak 4 中最新提供)。通过将这个变量设置成 ON,可以为页清除提供一种比缺省方法(基于 CHNGPGS_THRESH 和 LSN 间隙触发器)更积极的方法。我没有评测过其效果。请参阅 FixPak 4 Release Notes 以了解这方面的信息。
确保 NUM_IOCLEANERS 数据库配置参数的值至少等于数据库中物理存储设备的数量。
  至于 I/O 本身,当需要建立索引时,可以通过使用尽可能大的缓冲池来将 I/O 活动减至最少。如果不存在索引,则使用较大的缓冲池帮助不大,而只是推迟了 I/O。也就是说,它允许所有新页暂时安放在缓冲池中,但是最终仍需要将这些页写到磁盘上。
  当发生将页写到磁盘的 I/O 时,通过一些常规的 I/O 调优步骤可以加快这一过程,例如:
将表空间分布在多个容器(这些容器映射到不同磁盘)。
尽可能使用最快的硬件和存储管理配置,这包括磁盘和通道速度、写缓存以及并行写等因素。
避免 RAID5(除非是与像 Shark 这样有效的存储设备一起使用)。
  缺省情况下,每一个插入的行之上都有一个 X 锁,这个锁是在该行创建时就开始有的,一直到 insert 被提交。有两个跟 insert 和锁相关的性能问题:
为获得和释放锁而产生的 开销。
可能由于锁冲突而导致的并发问题。
  对于经过良好优化的批量插入,由获得每一行之上的一个 X 锁以及后来释放该锁引起的 CPU 开销是比较可观的。对于每个新行之上的锁,惟一可以替代的是表锁(DB2 中没有页锁)。当使用表锁时,耗时减少了 3%。有 3 种情况可以导致表锁的使用,在讨论表锁的缺点之前,我们先用一点时间看看这 3 种情况:
运行 ALTER TABLE LOCKSIZE TABLE。这将导致 DB2 为随后使用该表的所有 SQL 语句使用一个表锁,直到 locksize 参数改回到 ROW。
运行 LOCK TABLE IN EXCLUSIVE MODE。这将导致表上立即上了一个 X 锁。注意,在下一次提交(或回滚)的时候,这个表将被释放,因此,如果您要运行一个测试,测试中每 N 行提交一次,那么就需要在每次提交之后重复执行 LOCK TABLE。
使用缺省锁,但是让 LOCKLIST 和 MAXLOCKS 数据库配置参数的值比较小。当获得少量的行锁时,行锁就会自动地逐渐升级为表锁。
  当然,所有这些的缺点就在于并发的影响:如果表上有一个 X 锁,那么其他应用程序除非使用了隔离级别 UR(未提交的读),否则都不能访问该表。如果知道独占访问不会导致问题,那么就应该尽量使用表锁。但是,即使您坚持使用行锁,也应记住,在批量插入期间,表中可能存在数千个有 X 锁的新行,所以就可能与其他使用该表的应用程序产生冲突。通过一些方法可以将这些冲突减至最少:
确保锁的升级不会无故发生。您可能需要加大 LOCKLIST 和/或 MAXLOCKS 的值,以允许插入应用程序有足够的锁。
对于其他的应用程序,使用隔离级别 UR。
对于 V8 FixPak 4,或许也可以通过 DB2_EVALUNCOMMITTED 注册表变量来减少锁冲突:如果将该变量设置为 YES,那么在很多情况下,只能获得那些符合某个谓词的行上的锁,而并不是获得被检查的所有行上的锁。
发出一个 COMMIT 命令以释放锁,因此如果更频繁地提交的话就足以减轻锁冲突的负担。
在 V7 中,存在涉及 insert 和键锁的并发问题,但是在 V8 中,由于提供了 type-2 索引,这些问题实际上已经不见了。如果要迁移到 V8 中来,那么应该确保使用带 CONVERT 关键字的 REORG INDEXES 命令,以便将索引从 type-1 转换为 type-2。
在 V7 中,插入过程中可能使用 W 或 NW 锁,但是在 V8 中只有在使用了 type-1 索引或者隔离级别为 RR 的情况下才会出现这两种锁。因此,应尽可能避免这两种情况。
一条 insert 所据有的锁(通常是一个 X 锁)通常不会受隔离级别的影响。例如,使用隔离级别 UR 不会阻止从插入的行上获得锁。然而,如果使用了 INSERT ... SELECT,则隔离级别将影响从 SELECT 获得的锁。
  6. 日志记录
  缺省情况下,每条 insert 都会被记录下来,以用于恢复。日志记录首先被写到中的日志缓冲池,然后再写到日志文件,通常是在日志缓冲池已满或者发生了一次提交时写到日志文件的。对批量插入的日志记录的优化实际上就是最小化日志记录写的次数,以及使写的速度尽可能快。
  这里首先考虑的是日志缓冲池的大小,这由数据库配置参数 LOGBUFSZ 来控制。该参数缺省值为 8 页或 32 K,这与大多数批量插入所需的理想日志缓冲池大小相比要小些。举个例子,对于一个批量插入,假设对于每一行的日志内容有 200 字节,则在插入了 160 行之后,日志缓冲池就将被填满。如果要插入 1000 行,因为日志缓冲池将被填满几次,再加上提交,所以大概有 6 次日志写。如果将 LOGBUFSZ 的值增加到 64 页(256K)或者更大,缓冲池就不会被填满,这样的话对于该批量插入就只有一次日志写(在提交时)。通过使用更大的 LOGBUFSZ 可以获得大约 13% 的性能提升。较大日志缓冲池的不利之处是,紧急事故恢复所花的时间可能要稍微长一点。
  减少日志写的另一种可能性是对新行要插入到的那个表使用“ALTER TABLE ACTIVATE NOT LOGGED INITIALLY”(NLI)。如果这样做了,那么在该工作单元内不会记录任何 insert 操作,但是这里存在两个与 NLI 有关的重要问题:
如果有一条语句失败,那么这个表将被标记为不可访问的,并且需要被删除掉。这与其他恢复问题(请参阅 SQL Reference 关于 Create Table 的讨论)一起使得 NLI 在很多情况下不能成为可行的方法。
在工作单元最后进行的提交,必须等到在此工作单元内涉及的所有脏页都被写到磁盘之后才能完成。这意味着这种提交要占用大量的时间。如果没有积极地进行页清除,那么在使用 NLI 的情况下,Insert 加上提交所耗费的总时间要更长一些。将 NLI 与积极的页清除一起使用的时候,可以大大减少耗时。如果使用 NLI,就要瞪大眼睛盯紧提交操作所耗费的时间。
  至于提高日志写的速度,有下面一些可能性:
将日志与新行所要插入到的表分别放在不同的磁盘上。
在层将日志分放到多个磁盘。
考虑为日志使用原始设备(raw device),但是要注意,这样管理起来要更困难些。
避免使用 RAID 5,因为它不适合于写密集型(write-intensive)活动。
  7. 提交
  提交迫使将日志记录写到磁盘上,以保证提交的插入肯定会存在于数据库中,并且释放新行上的锁。这些都是有价值的活动,但是因为 Commit 总是要牵涉到同步 I/O(对于日志),而 insert 则不会,所以 Commit 的开销很容易高于 insert 的开销。因此,在进行批量插入时,每一行都提交一次的做法对于性能来说是很糟糕的,所以应确保不使用自动提交(对于 CLI 和 CLP 来说缺省情况正是如此)。建议大约每 1000 行提交一次:当每 1000 行而不是一两行提交一次时,性能可以提高大概 10 倍。不过,一次提交多于 1000 行只能节省少量的时间,但是一旦出现失败,恢复起来所花的时间要更多。
  对上述方法的一种修正:如果 MINCOMMIT 数据库配置参数的值大于 1 (缺省值),则 DB2 就不必对每次 commit 都进行一次同步 I/O,而是等待,并试图与一组事件一起共享日志 I/O。对于某些环境来讲,这样做是有好处,但是对于批量插入常常没有作用,甚至有负作用,因此,如果要执行的关键任务是批量插入,就应该让 MINCOMMIT 的值保持为 1。
  可以选择性地进行改进的地方
  对于一次 insert,有几种类型的处理将自动发生。如果您的主要目标只是减少插入时间,那么最简单的方法是避免所有这些处理的开销,但是如果从总体上考虑的话,这样做未必值得。让我们依次进行讨论。
  索引维护
  对于插入的每一行,必须添加一个条目到表上的每个索引中(包括任何主键索引)。这一过程主要有两方面的代价:
遍历每个索引树,在树的每一层搜索一个页,以确定新条目必须存储在哪里(索引条目总是按键顺序存储的),这一过程所引起的 CPU 开销;
将所有搜索到的页读入缓冲池,并最终将每个更新后的页写到磁盘上的 I/O 开销。
  更坏的场景是,在索引维护期间有大量的随机 I/O。假设要插入 10,000 行,在索引的缓冲池中有 5000 页,并且要插入的各行的键值随机分布在整个键范围内。那么,有 10,000 个这么多的叶子页(可能还有些非叶子页)需要进入缓冲池,以便对它们进行搜索和/或更新,对于一个给定的叶子页,它预先已经在缓冲池中的概率只有 10%。对于每次的 insert,需要读磁盘的概率如此之高,使得这种场景往往性能很差。
  对于逐行插入,将新行添加到已有的索引中比起创建一个新索引来代价要高得多。如果是插入到一个空表,应该总是在进行了列插入之后创建索引。(注意,如果使用了 load,则应该 预先创建索引。)如果要插入到一个已经填充过的表,那么在列插入之前删除索引,并在列插入之后重新创建索引,这种方法可能是最快的,但是只有在要插入相当多的行 -- 大概大于表的 10-20% 的时候,才能这么说。如果为索引表空间使用较大的缓冲池,并且尽可能地将不同 insert 排序,以便键值是排好序的,而不是随机的,就可以帮助加快索引维护。
(作者:佚名责任编辑:方舟)
欢迎在新浪微博上关注我们
办公软件IT新闻整机}

我要回帖

更多关于 提高系统性能 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信