Oracle 11. 更新 BLOB 字段。Db 文件顺序读取速度异常缓慢?

Oracle 11. 更新 BLOB 字段。Db 文件顺序读取速度异常缓慢?

我已经和 Oracle (11 Enterprise) 架构有一个表

 CREATE TABLE USER.WSP_BUNDLE ( 
    NODE_ID     RAW(16) NOT NULL,
    BUNDLE_DATA BLOB NOT NULL 
    );
CREATE UNIQUE INDEX USER.WSP_BUNDLE_IDX ON USER.WSP_BUNDLE(NODE_ID);

以及操作它的第三方库(Java 6,JDBC - 最新的 jdbc 驱动程序)。

Oracle 分析器(tkprof)显示大约 50% 的时间用于执行此类语句

update WSP_BUNDLE set BUNDLE_DATA = :1 where NODE_ID = :2

TKProf 数据

Plan Hash: 4085453680
update WSP_BUNDLE set BUNDLE_DATA = :1  where NODE_ID = :2 


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse      264      0.00       0.00          0          0          0           0
Execute    400     30.59     382.88     141451    1623163    3233827         400
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total      664     30.59     382.88     141451    1623163    3233827         400

Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 87  

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  UPDATE  WSP_BUNDLE (cr=8753 pr=707 pw=706 time=0 us)
      1   INDEX UNIQUE SCAN WSP_BUNDLE_IDX (cr=3 pr=0 pw=0 time=0 us cost=2 size=104 card=1)(object id 75730)


Elapsed times include waiting on following events:
  Event waited on                             Times   Max. Wait  Total Waited
  ----------------------------------------   Waited  ----------  ------------
  db file sequential read                    141251        5.53        328.04
  direct path write                             402        0.09          0.43
  SQL*Net more data from client              142158        1.04         11.89
  direct path read                              200        0.03          0.07
  Disk file operations I/O                        1        0.00          0.00
  SQL*Net message to client                     400        0.00          0.00
  SQL*Net message from client                   400        0.29          0.50
  log file switch (private strand flush incomplete)
                                                  5        0.05          0.23
  asynch descriptor resize                   139723        7.46          8.57
  buffer busy waits                               2        0.00          0.00
  log file switch (checkpoint incomplete)         3        0.18          0.27
  log file sync                                   2        0.00          0.00

有人能解释/提示我发生了什么吗?为什么更新这么慢?

表 WSP_BUNDLE 包含大约 200+k 行。同时,我在同一架构中还有其他包含 blob(更具体地说是 CLOB)的表,这些表包含 600+k 行,其中类似的更新可以正常工作。

答案1

在Oracle中,LOB(包括BLOB)存储为:

  • 表中的 LOB - 如果 LOB 小于 3900 字节,则可以将其存储在表行内;默认情况下启用此功能,除非您指定 DISABLE STORAGE IN ROW
  • 普通 LOB - 存储在表之外的单独段中,甚至可以将其放在另一个表空间中;例如:
    • 分配最少的 CHUNK 字节并完全重做日志(即使 LOB 只有 1 个字节)
    • LOB 列后面有一个内部中间索引,该索引在更新时会产生争议,并且实际上可能会序列化它们
    • 访问是多级的,因此相对较慢
    • 使用 NOCACHE 选项时,服务员是“直接路径读取” - 默认
    • 使用 CACHE 选项时,等待者是“数据库文件顺序读取”
      • 其中没有考虑 CACHE_SIZE_THRESHOLD,因此较大的 LOB 可能会浪费您的缓存

因此,如果您的 LOB 大于 4 kB,它们会变得相对较慢,这可能只是您的情况。我会检查大小。

我将检查 USER_LOBS(或 DBA_LOBS)以了解“好”和“慢”LOB 列在定义上有何不同。

Metalink 注释 ID 66431.1 对此进行了描述,如果您有权访问,您可能会感兴趣。

更新:我对看似无法解释的“数据库文件顺序读取”数量感到着迷,我做了一些搜索,发现大量删除后,lob 索引可能会发生奇怪的事情。只是猜测,但看起来和你的情况很相似。如果是这样的话,我会彻底重建 lob 列(移动 lob 列也可能会重建 lob 索引 - 我不确定)。

相关内容