如何提高Oracle插入性能

时间:2021-06-16 03:26:45

标签: oracle performance insert

我有一个包含 25 个字段的表格。该表包含主键字段“id”和 5 个 NOT NULL CHECK。我得到的插入性能是~11000 TPS,想知道有没有什么办法可以提高性能。

一些详细的背景:

  1. 由于某些原因,我们不能使用bulk-insert,即只能使用insert into values。
  2. 提高线程数(从 12 到 20 到 100)没有任何帮助,CPU 使用率非常低。机器96核,755G内存,1T SSD。
  3. 表中的行大小很小,每行大约 0.25KB。
  4. Oracle 版本为 19.3.0 企业版。

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

  1. 定义多个freelist。尝试了 4 个自由列表、20 个自由列表和 80 个自由列表。
  2. /*+ APPEND_VALUES */ 提示使性能更差(1100 TPS)。

提前致谢。

2 个答案:

答案 0 :(得分:2)

可扩展序列,或者为每个会话构建自己的伪随机序列前缀,可以提高大规模并发插入的性能。 (提高 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。

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

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

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

然而,反向键索引并不是解决它们要解决的问题的好方法。反转密钥确实更均匀地分配工作,但我们不希望完全均匀分配工作。我们不希望不同的会话同时对同一个块进行操作,但我们确实希望同一个会话在它仍处于锁定状态并在内存中时对同一个块进行多次操作。 >

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

<块引用>

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

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

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

答案 1 :(得分:1)

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

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

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

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

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

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

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