3

我的问题很简单,在标题中。谷歌和堆栈溢出什么也没给我,所以我想是时候问一个问题了。

我目前正在为用户注册到我的网站时进行 sql 查询。我总是只使用准备好的语句 b/c 可调用语句中的额外编码,并且常规语句的性能影响都是关闭的。然而,这个查询让我想到了可能替代我之前的一种适合所有(准备好的语句)方式的方法。

此查询总共有 4 次到数据库的往返行程。步骤是

  1. 将用户插入数据库,在结果集中取回生成的密钥(他们的用户 ID)。
  2. 获取用户 ID 并在相册表中插入一行。取回生成的密钥(专辑 ID)
  3. 获取专辑 ID 并在图像表中插入一行。取回生成的密钥(图像 id)
  4. 获取图像 id 并使用图像 id 更新用户表的当前默认列

旁白:对于任何对我在插入后取回密钥的方式感兴趣的人Statement.RETURN_GENERATED_KEYS,您可以在此处阅读一篇很棒的文章 - IBM 文章

所以无论如何我想知道使用4个往返(但可缓存)准备好的语句是否可以,或者我是否应该使用批处理(但不可缓存)语句?

4

3 回答 3

2

JDBC 批处理语句允许您在插入或更新的行之间不存在数据依赖关系的情况下减少往返次数。您的方案不符合此条件,因为更改依赖于彼此的数据:语句 2 到 4 必须从之前的语句 1 到 3 中选择一个 ID。

另一方面,四次往返肯定不是最理想的。这就是为什么像您这样的场景需要存储过程:您可以将所有这些逻辑放入 acreate_user_proc中,并将用户 ID 返回给调用者。从 1 到 4 的所有插入都将发生在您的 SQL 代码中,让您可以管理 SQL 中的 ID 依赖关系。您将能够在一次往返中调用此存储过程,这肯定会更快,尤其是在您每分钟处理多个用户注册的情况下。

于 2013-03-13T04:33:25.823 回答
1

我建议编写一个存储过程来执行所有这四个操作,并一次将所有必需的参数从应用程序(到存储过程)传递到存储过程中,您可以获得结果集的生成键

于 2013-03-13T04:50:43.640 回答
1

为了提高性能并减少数据库往返,我同意 dasblinkenlight 和 ajduke - 存储过程将实现这一点。

但是,这真的是您应用程序的性能瓶颈吗?

  • 用户多久在您的网站上注册一次?
  • 将此与从这些表中读取信息的频率进行比较(每页访问一次?)

如果这些表中的信息被读取的次数比通过新注册写入的次数多数千倍,那么使用存储过程方法可能不值得。

为什么您可能不想使用存储过程并坚持使用准备好的语句:

  • 不像使用准备好的语句那样可移植(每个数据库都有不同的语法/语言,一些更简单的数据库甚至不支持它们)
  • 不适用于 JPA* 等 ORM 解决方案 - 您提到直接使用 PreparedStatements,因此这可能不适用于您,至少现在不适用,但如果您以后想在将来使用 ORM,它可能会限制您

*JPA 2.1 可能实际上支持存储过程,但在撰写本文时它还没有发布。

于 2013-03-13T05:15:28.723 回答