如果表具有大量记录(400K)而不是它是空的,则插入速度会慢4倍

时间:2009-02-26 03:58:40

标签: performance oracle insert oracle10g

(数据库:Oracle 10G R2)

将100,000条记录插入表中需要1分钟。但是如果表已经包含一些记录(400K),则需要4分12秒; CPU等待也会跳起来,“Free Buffer Waits”变得非常高(来自dbconsole)。

你知道在这里讨厌什么吗?这是因为频繁的表范围?这些表的范围大小为1,048,576字节。我有一种感觉DB正试图扩展表存储。

我对此感到很困惑。所以任何帮助都会很棒!


这是插入声明:

begin
  for i in 1 .. 100000 loop
    insert into customer
                (id, business_name, address1,
                 address2, city,
                 zip, state, country, fax,
                 phone, email
                )
         values (customer_seq.nextval, dbms_random.string ('A', 20), dbms_random.string ('A', 20),
                 dbms_random.string ('A', 20), dbms_random.string ('A', 20),
                 trunc (dbms_random.value (10000, 99999)), 'CA', 'US', '798-779-7987',
                 '798-779-7987', 'asdfasf@asfasf.com'
                );
  end loop;
end;

此处dstat输出(CPU,IO,MEMORY,NET):

  1. 空表插页:http://pastebin.com/f40f50dbb
  2. 包含400K记录的表:http://pastebin.com/f48d8ebc7

  3. v$buffer_pool_statistics

    的输出
    
    ID:                       3
    NAME:                     DEFAULT
    BLOCK_SIZE:               8192
    SET_MSIZE:                4446
    CNUM_REPL:                4446
    CNUM_WRITE:               0
    CNUM_SET:                 4446
    BUF_GOT:                  1407656
    SUM_WRITE:                1244533
    SUM_SCAN:                 0
    FREE_BUFFER_WAIT:         93314
    WRITE_COMPLETE_WAIT:      832
    BUFFER_BUSY_WAIT:         788
    FREE_BUFFER_INSPECTED:    2141883
    DIRTY_BUFFERS_INSPECTED:  1030570
    DB_BLOCK_CHANGE:          44445969
    DB_BLOCK_GETS:            44866836
    CONSISTENT_GETS:          8195371
    PHYSICAL_READS:           930646
    PHYSICAL_WRITES:          1244533
    
    

    更新

    我从这个表中删除了索引,即使将100K插入到600K记录表中(在没有CPU等待的情况下耗时47秒 - 请参阅dstat输出http://pastebin.com/fbaccb10),性能也得到了极大提升。

7 个答案:

答案 0 :(得分:5)

不确定在Oracle中是否相同,但在SQL Server中,我要检查的第一件事是你在表上有多少索引。如果这是很多的话,数据库必须做很多工作,在插入记录时重新索引表。重新索引500k行比100k更难。

答案 1 :(得分:1)

索引是某种形式的树,这意味着插入记录的时间将是O(log n),其中n是树的大小(≈标准唯一索引的行数)。 / p>

插入它们的最快方法是在插入过程中删除/禁用索引,然后重新创建它,就像你已经找到的那样。

答案 2 :(得分:1)

即使使用索引,插入100,000条记录的4分钟对我来说也是一个问题。

如果此数据库存在I / O问题,您尚未修复它们,它们将再次出现。我建议您确定根本原因。

如果您发布索引DDL,我会将其计时以进行比较。


我在id和business_name上添加了索引。在循环中进行10次迭代,每100,000行的平均时间为25秒。这是在我的家用PC /服务器上运行在一个磁盘上。

答案 3 :(得分:1)

提高性能的另一个技巧是在序列(customer_seq)上打开或设置更高的缓存。这将允许oracle将序列分配到内存中,而不是为每个插入命中对象。

虽然小心这个。在某些情况下,这会导致序列间隙在值之间产生间隙。

更多信息: Oracle/PLSQL: Sequences (Autonumber)

答案 4 :(得分:0)

排序的插入总是花费更长的时间表中的条目。

答案 5 :(得分:0)

您没有说明索引了哪些列。如果你有传真,电话或电子邮件的索引,你会有很多重复(即每一行)。 Oracle'假装'拥有非唯一索引。实际上,每个索引条目都是唯一的,实际表行的rowid是决定因素。 rowid由文件/块/记录组成。

有可能,一旦你达到一定数量的记录,新的记录就会得到rowid,这意味着必须在现有索引的中间进行大量的索引重写。

如果您提供完整的表格和索引创建语句,其他人将能够重现可以提供更多基于证据的响应的体验。

答案 6 :(得分:-1)

我认为它与扩展文件的内部结构有关,以及为添加的信息构建数据库索引 - 我相信数据库以非线性方式排列数据,有助于加快数据检索选择