【问题标题】:How to improve the Oracle insert performance如何提高 Oracle 插入性能
【发布时间】:2021-08-31 21:02:07
【问题描述】:

我有一个包含 25 个字段的表格。该表包含主键字段“id”和 5 NOT NULL CHECK。我得到的插入性能约为 11000 TPS,想知道是否有任何方法可以提高性能。

一些详细的背景:

  1. 由于某些原因,我们不能使用批量插入,即只能使用插入值。
  2. 提高线程数(从 12 到 20 到 100)没有任何帮助,并且 CPU 使用率非常低。该机拥有96核、755G内存和1T SSD。
  3. 表格中的行很小,每行大约 0.25KB。
  4. Oracle 版本为 19.3.0 企业版。

我做了一些尝试,但性能没有提高:

  1. 定义多个freelist。试过4个freelist,20个freelist,80个freelist。
  2. /*+ APPEND_VALUES */ 提示会使性能更差 (1100 TPS)。

提前致谢。

【问题讨论】:

  • 主键值是从序列派生的吗?如果是这样,我建议尝试scalable sequences。由于您无法批量写入,因此如果您的线程都获得序列号,它们将全部写入同一个块,从而导致争用。可扩展的序列在数字的前面添加了一些随机性以避免这种争用。
  • @JonHeller 可扩展序列主要用于 RAC。您插入的数据的来源是什么?例如,它是 CSV 文件吗?您的客户端应用程序是什么以及在哪里?
  • 如何删除旧数据?每秒插入 11k 条记录会在几天后填满 1TB SSD。
  • 比你的 bottleneck 可能是索引,而不是表。 Oracle 使用REVERSE Index 解决此争用。行的存储(在非聚集表中)独立于PK 的值。
  • @MarmiteBomber 嗨,你是对的。使用 REVERSE 索引可以解决问题。谢谢你。 :)

标签: oracle performance insert


【解决方案1】:

可扩展序列,或为每个会话构建自己的伪随机序列前缀,可以提高大规模并发插入的性能。 (提高 DML 性能的最佳方法通常是批量写入,但您说这种方法在您的场景中不可行。)

创建和使用可扩展的序列可以像以下命令一样简单。

JHELLER@orclpdb> create sequence test_seq scale;

Sequence created.

JHELLER@orclpdb> select to_char(test_seq.nextval) from dual;

TO_CHAR(TEST_SEQ.NEXTVAL)
----------------------------------------
1017160000000000000000000001

JHELLER@orclpdb> select to_char(test_seq.nextval) from dual;

TO_CHAR(TEST_SEQ.NEXTVAL)
----------------------------------------
1017160000000000000000000002

可伸缩序列正在解决的问题在数据库概念手册中关于reverse key indexes 的部分中得到了最好的描述:

反向键索引是一种物理反转的 B 树索引 每个索引键的字节,同时保持列顺序。

例如,如果索引键是 20,并且如果存储的两个字节为 十六进制的这个键是标准 B 树索引中的 C1,15,然后是 反向键索引将字节存储为 15,C1。

反转密钥解决了叶块争用问题 B树索引的右侧。这个问题可能特别严重 在 Oracle Real Application Clusters (Oracle RAC) 数据库中,其中 多个实例重复修改同一个块。例如,在 一个订单表,订单的主键是顺序的。一 集群中的实例添加订单 20,而另一个添加 21,与 每个实例将其密钥写入右侧的同一叶块 索引的一侧。

在反向键索引中,字节顺序的反转分布 插入索引中的所有叶键。例如,键如 在标准键索引中相邻的 20 和 21 是 现在存储在单独的块中。因此,用于插入的 I/O 顺序键分布更均匀。

因为索引中的数据不是按列键排序的 存储时,反向键排列消除了运行的能力 某些情况下的索引范围扫描查询。例如,如果用户 发出大于 20 的订单 ID 的查询,则数据库无法 从包含此 ID 的块开始并水平进行 穿过叶子块。

但是,反向键索引并不是解决它们旨在解决的问题的好方法。反转密钥确实可以更均匀地分配工作,但我们不希望完全均匀地分配工作。我们不希望不同的会话同时在同一个块上操作,但我们确实希望同一个会话在同一个块上多次操作,同时它仍然被锁定并在内存中。 p>

这是关于 scalable sequences 的数据库管理员指南部分:

可以通过在 CREATE SEQUENCE 或 ALTER SEQUENCE 语句。一个可扩展的序列是 当用于生成无序初级或 具有高水平的数据摄取工作负载的唯一键 并发。可扩展的序列显着减少了序列和 索引块争用并提供更好的数据负载可扩展性 相比配置超大序列缓存的方案 使用 CREATE SEQUENCE 或 ALTER SEQUENCE 语句的 CACHE 子句。

可扩展的序列提高了并发数据加载的性能 操作,尤其是当序列值用于 填充单个 Oracle 数据库中表的主键列 实例以及 Oracle RAC 数据库。

但我想再次强调,提高插入性能的最佳方法是尽可能对行集进行操作。我已经看到可扩展序列的性能翻了一番,但我看到批处理写入将性能提高了几个数量级。

【讨论】:

    【解决方案2】:

    我猜你使用绑定参数插入 - 如果不使用它。

    索引、触发器和约束会降低插入性能。尝试删除它们。

    您是否使用 SEQUENCE 作为主键?如果是,请使用@Jon Heller 建议的可扩展序列(到目前为止,我还不知道这个新功能)或尝试CACHE 100000 - 或者根本不使用序列。

    您是否能够并行运行多个插入作业?

    在没有任何索引、触发器、约束等的临时表中插入值。然后运行INSERT INTO final_table SELECT * FROM temp_table,例如每百万行。

    您有分区表吗?如果是,请尝试使用PARTIAL INDEX,即每小时/每天仅生成一次索引。而不是INSERT INTO final_table SELECT * FROM temp_table 考虑Exchange Partition

    我有一个类似的应用程序,即相当小的行但很多插入。我的插入限制也是每秒大约 10k 行(每个插入过程)。我并行运行 8 个插入进程,效果很好。我对APPEND 提示也有同样糟糕的经历。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-17
      • 1970-01-01
      • 2012-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-05
      • 2021-08-01
      相关资源
      最近更新 更多