【发布时间】:2019-06-01 05:53:08
【问题描述】:
不久前,我在使用jdbc 插入/更新数百万条记录时遇到了数据库性能问题。为了提高性能,我将代码更改为使用batch。然后我决定使用jprofiler 监控代码以了解性能提高了多少……但同时监控我发现了一个奇怪的事情!
从上面的截图可以看出,从序列中生成新的 id 非常慢。屏幕截图是如此具有描述性,我必须说第二行是对一个表的 inner join 查询,该表有大约 800 万条记录和一些计算(将其时间与第三个查询的时间进行比较!)。
我向我们的 dba 询问了这个问题,他说了一些关于缓存序列的 oracle 推荐,但是当我检查序列时,我发现它已经被缓存了。
CREATE SEQUENCE "XXXXXXXXXXXX_ID_SEQ" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE;
有什么想法吗?
附言我认为Hibenate 使用序列类似地插入记录,实际上我正在寻找使用序列来提高我们使用休眠的项目的性能的最佳实践。上述jdbc任务终止。
【问题讨论】:
-
Hibernate 的默认序列生成器每 50 次插入从数据库中获取下一个序列值,并在内存中保存一个计数器。因此,它(默认情况下)比您在那里看到的快 50 倍。
-
您是指此打印屏幕上倒数第三行吗?平均时间 = 396 μs。 μs = 微秒。 396μs = 0.4 ms(毫秒)。这是每秒 2500 次操作。你真的认为它很慢吗?我认为这种微优化是浪费时间,当你将时间减少 50% 时,每次操作最多将获得 0.2 毫秒。
-
如果您通常需要 200K 序列值来执行此过程,那么您可以考虑将缓存大小从 20 增加到数百。另外我不知道Hibernate(或Java),但如果您可以将生成的序列作为
insert的一部分而不是在单独的操作中获取它(例如调用执行所有数据库处理的过程和返回生成的 ID)。从 Oracle 12c 开始,您可以开始使用标识列,而忘记所有这些序列微管理。 -
不管有什么其他方法可以提高效率,看看效果 - 孤立 - 简单地将
CACHE值从 20 更改为 1000 会很有趣。如果你可以尝试很容易并报告回来,我相信我们中的许多人会发现这是有用的信息。 -
您说的是从序列中获取近 200K 个键需要 1 分钟以上的时间。您选择了可能是问题的 Hibernate。您必须管理批量插入行而不在数据库和客户端之间传递密钥。目前,您要求数据库分配新密钥,将其发送给客户端,插入行并再次循环 - 逐行 - 慢慢变慢!
标签: oracle hibernate oracle11g database-performance sql-tuning