没有合适的资源?快使用搜索试试~ 我知道了~
INSERT处理过程概述首先让我们快速地看看插入一行时的处理步骤。这些步骤中的每一步都有优化的潜力,对此我们在后面会一一讨论。在客户机准备语句。对于动态SQL,在语句执行前就要做这一步,此处的性能是很重要的;对于静态SQL,这一步的性能实际上关系不大,因为语句的准备是事先完成的。在客户机,将要插入的行的各个列值组装起来,发送到DB2服务器。DB2服务器确定将这一行插入到哪一页中。DB2在用于该页的缓冲池中预留一个位置。如果DB2选定的是一个已有的页,那么就需要读磁盘;如果使用一个新页,则要在表空间(如果是SMS,也就是系统管理存储的表空间)中为该页物理地分配空间。插入了新行的每一页最后都要从缓
资源推荐
资源详情
资源评论
在在DB2中提高中提高INSERT性能性能
INSERT 处理过程概述处理过程概述
首先让我们快速地看看插入一行时的处理步骤。这些步骤中的每一步都有优化的潜力,对此我们在后面会一
一讨论。
1. 在客户机准备 语句。对于动态 SQL,在语句执行前就要做这一步,此处的性能是很重要的;对于静态
SQL,这一步的性能实际上关系不大,因为语句的准备是事先完成的。
2. 在客户机,将要插入的行的各个 列值组装起来,发送到 DB2 服务器。
3. DB2 服务器确定将这一行插入到哪一页中。
4. DB2 在 用于该页的缓冲池中预留一个位置。如果 DB2 选定的是一个已有的页,那么就需要读磁盘;
如果使用一个新页,则要在表空间(如果是SMS,也就是系统管理存储的表空间)中为该页物理地分
配空间。插入了新行的每一页最后都要从缓冲池写入到磁盘。
5. 在目标页中对该行进行格式化,并获得该行上的一个X(exclusive,独占的) 行锁。
6. 将反映该 insert 的一条记录写入到日志缓冲区中。
7. 最后提交包含该 insert 的事务,如果这时日志缓冲区中的记录还没有被写入日志文件的话,则将这些
记录写到日志文件中。
此外,还可能发生很多类型的附加处理,这取决于数据库配置,例如,索引或触发器的存在。这种额外的处
理对于性能来说也是意义重大的,我们在后面会讨论到。
INSERT 的替代方案的替代方案
在详细讨论 insert 的优化之前,让我们先考虑一下 insert 的两种替代方案:load 和 import。import 实用程
序实际上是 SQL INSERT 的一个前端,但它的某些功能对于您来说也是有用的。load 也有一些有用的额外
功能,但是我们使用 load 而不使用 insert 的主要原因是可以提高性能。
load 直接格式化数据页,而避免了由于插入导致的对每一行进行处理的大部分开销(例如,日志记录在这里
实际上是消除了)。而且,load 可以更好地利用多处理器机器上的并行性。在 V8 load 中有两个新功能,它
们对于 load 成为 insert 的替代方案有着特别的功效,这两个功能是:从游标装载和从调用层接口(CLI)应
用程序装载。
从游标装载从游标装载
这种方法可用于应用程序的程序代码(通过 db2Load API),或用于 DB2 脚本。下面是后一种情况的一个
例子:
declare staffcursor cursor forselect * from staff;
load from staffcursor of cursor insert into myschema.new_staff;
这两行可以用下面一行替代:
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 模式对于批量插入是最快的一种方法,但是这种方法的效
果远不如我们这里讨论的很多其他方法那么成效显著。第二好的方法应该是采用缺省算法,但是,如果在最
剩余8页未读,继续阅读
资源评论
weixin_38712416
- 粉丝: 8
- 资源: 938
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功