多个准备语句或批处理

时间:2013-03-13 04:20:29

标签: java mysql sql jdbc

我的问题很简单,在标题中。谷歌和堆栈溢出给我什么都没有,所以我认为是时候提问了。

我目前正在为用户注册我的网站时进行SQL查询。我总是只使用预处理语句b / c可调用语句中的额外编码,并且常规语句的性能命中都是关闭的。然而,这个查询让我想到了我以前的一个大小适合所有(预备语句)方式的可能替代方案。

此查询共有4次往返数据库。步骤是

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

    旁白:对于任何对我在插入后获取密钥的方式感兴趣的人都可以使用Statement.RETURN_GENERATED_KEYS,您可以在此处阅读有关此内容的精彩文章 - {{3} }

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

3 个答案:

答案 0 :(得分:2)

JDBC批处理语句允许您在插入或更新的行之间没有数据依赖性的情况下减少往返次数。您的方案在这种情况下失败,因为更改取决于彼此的数据:语句2到4必须从先前的语句1到3中选取一个ID。

另一方面,四次往返肯定不是最理想的。这就是像您这样的场景调用存储过程的原因:您可以将所有这些逻辑放入create_user_proc,并将用户ID返回给调用者。从1到4的所有插入都会在SQL代码中发生,让您可以在SQL中管理ID依赖项。您可以在单个往返中调用此存储过程,这肯定更快,特别是如果您每分钟处理多个用户注册。

答案 1 :(得分:1)

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

答案 2 :(得分:1)

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

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

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

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

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

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

* JPA 2.1实际上可能support stored procedures,但截至撰写时尚未发布。