Oracle 11g:插入的性能改进


8

我有一个5亿行的表格(并且还在不断增长)

我做了以下事情来提高插入的性能:

在数据库方面:

  • 删除所有索引和约束
  • 禁用日志记录

在应用程序方面:

  • 从JPA管理的实体切换到本机插入查询,向查询添加了APPEND Oracle提示
  • 尝试每1k / 2k / 3k行批量提交
  • 尝试并行写入(多线程,线程数=服务器上的核心数)到一张表

这使我每秒大约300行

另外尝试:

  • 批量并行写入多个表(使用UNION分组然后返回结果)

这使我每秒大约有1000行,但在空表上。但是,当我用虚拟数据(每个200百万个)填充表时,插入速度下降到每秒250-300个。

有人可以建议我做些什么来加快插入速度吗?基本上,我想首先了解瓶颈(可能是什么)。

UPD: 表格按插入日期进行分区,表格约有60列-大多数列为VARCHAR2(2000 BYTE)


您知道在禁用日志记录的情况下,加载与完成第一个后续备份之间的介质故障将导致整个表或在直接路径插入的情况下无法恢复整个表的部分,对吗?
David Aldridge

1
(1)一次只能在一个桌子上追加一个会话。(2)/*+APPEND*/在单行插入中,提示将被忽略(如果没有,则INSERT INTO ... SELECT不必对append进行打扰)。(3)您应该设置一个SQL * Loader示例,direct=true以按照@parsifal的建议建立基线。
Vincent Malgrat 2013年

您是在真实硬件还是虚拟机上运行?如果是VM,磁盘文件是否稀疏(即:未完全预先分配)?另外,请使用statspack或awr报告的输出(最热门的部分)来编辑您的问题。
Philᵀᴹ

通过插入日期进行分区可以解决/满足哪些问题/需求?
布莱恩

该表的数据源是什么?这是从ASCII文件批量加载还是用户生成的文件或其他东西。请具体说明。
RMAN Express

Answers:


5

刚刚看到了更新的60列表,其中大部分是VARCHAR(2k)字段-(可能)是一个怪物表。

首先要先 ...

您必须首先了解您的瓶颈。在应用程序方面,一路回到您的单线程批处理插入解决方案(一次为1/2 / 3k),并开始运行它并登录到DB计算机并运行一个“ top”(顶部)-查看多少数据库进程花费的时间以及计算机显示的时间(如果有)。

如果top向您显示了wa%的时间,则意味着您的数据库受I / O约束,您可能需要考虑使用多个DB计算机(分片)或考虑将SSD放入主机。

而已; 您的研究到此为止。数据库占用了多少CPU或您的应用程序客户端有多饱和都没有关系。如果您在主机DB上遇到I / O延迟问题,那将是您所需要的。

提示如果无法进行硬件更改,则根据所运行的文件系统(Linux),可以尝试禁用数据库的日志记录或元数据写入功能,以稍微提高文件系统级别的性能。您可以在NTFS上执行类似的操作,但这只会给您带来一点好处。这不会是2倍。

现在,第二件事……

假设您几乎没有时间,但是您的CPU完全被数据库进程占用。现在,您唯一的选择是引入更多的DB计算机(分片)并拆分工作。

同样,在这种情况下,您已经完成了研究。您无法调整CPU使其运行得更快。

最后,第三件事...第三...

假设数据库没有做任何事情。然后,转到运行批处理插入的客户端计算机并检查CPU负载-是否固定?如果是这样,请启动其他一些机器,它们执行完全相同的批处理插入,并查看是否可以得到线性斜坡。

如果未固定CPU,请在同一台计算机上启动更多线程,直到固定为止,然后查看数据库如何扩展。

我想您可能已经尝试过了,所以我猜测是您的客户端主机已经被挂住(更多线程不会产生影响)或数据库已经达到极限并且无法进一步扩展。

附录

在没有索引的无索引表上进行原始插入实质上是一项APPEND操作,其执行速度应与磁盘可以处理写入的速度一样快。

在同一台主机上创建更多表将无济于事,如果有什么话,它会增加磁盘寻道(到达要追加到磁盘上其他表的磁盘)并减慢运行速度。

首先要弄清楚该瓶颈,然后我们才能对其进行优化,这一点至关重要。

希望有帮助!保持联系。


2
您为什么没有提到awr或statspack?
Philᵀᴹ

带有附加提示,由于独占锁定,所有这些线程中只有一个线程将处于空闲状态。我认为这段代码并不是在需要进行系统级调整的高效阶段,而方法论本身就是有缺陷的。
David Aldridge

再想一想,我相信您的方法存在根本缺陷。如果Viktors尝试使用单线程批处理插入方法并具有I / O等待时间,则可能是由于效率低下的插入方法和过量使用(日志文件同步等待)引起的。最重要的步骤应该是了解Oracle机制并首先选择最合适的一种?
David Aldridge

@DavidAldridge Viktors阐明了他已禁用日志记录(和索引),因为我认为除了将插入的数据直接流到表文件,DB并没有做很多其他事情,这就是为什么我让他跳一下来看I / O等待。也许还有更多的Oracle正在/应该禁用此功能-这是一个很好的调查点,但我不知道Oracle的深度足以帮助那里。
里亚德·卡拉

4

通过附加提示调用直接路径插入会导致对整个表进行排他锁,因此让多个线程执行插入将无济于事。您将需要在每次插入时显式地寻址不同的分区。

insert /*+ append */ into my_table partition (partition_name_1) ...

...以获取分区级别的排他锁。您极有可能无法对按插入日期进行分区的表执行此操作,但可以使用复合分区(而非子分区)来在每个插入日期的唯一范围内获取多个分区。

不要在插入内容的中间提交,而要在结尾处提交。


我是否需要在查询中明确提及分区名称?我有专栏,有点事件类型。我将尝试按事件组进行分区,以使每个线程仅插入特定类型的行的批处理
漂流

为避免表级排他锁,可以。
David Aldridge 2013年

对于单行插入,Oracle应该忽略APPEND提示。OP对该过程的描述似乎暗示了批处理单行插入。我不确定这些如何处理。我猜没有APPEND,但是需要一些测试。
Vincent Malgrat 2013年

嗯,没有考虑-甚至更糟。
David Aldridge

值得尝试使用APPEND提示进行多行插入吗?那么每个多行插入应该发送多少个条目?
2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.