ResultSet:按索引检索列值与按标签检索

Ror*_*ick 50 java optimization maintenance jdbc resultset

使用JDBC时,我经常遇到类似的结构

ResultSet rs = ps.executeQuery();
while (rs.next()) {
    int id = rs.getInt(1);
    // Some other actions
}
Run Code Online (Sandbox Code Playgroud)

我问自己(以及代码的作者)为什么不使用标签来检索列值:

int id = rs.getInt("CUSTOMER_ID");
Run Code Online (Sandbox Code Playgroud)

我听过的最好的解释是关于表现的.但实际上,它是否会使处理速度极快?我不相信,尽管我从未进行过测量.即使按标签检索会慢一点,但在我看来,它提供了更好的可读性和灵活性.
那么有人可以给我很好的解释,避免通过列索引而不是列标签来检索列值吗?这两种方法的优点和缺点是什么(可能是关于某些DBMS)?

Cow*_*wan 56

警告:我会在这里夸夸其谈,因为这让我发疯.

99%*的时间,这是一个荒谬的微观优化,人们有一些模糊的想法让事情"变得更好".这完全忽略了,除非你在一个非常紧张,繁忙的循环超过百万次的SQL是导致事实上所有的时间,这是罕见的希望,你永远也不会注意到它.对于那些没有这样做的人来说,维护,更新和修复列索引中的错误的开发人员时间成本远远大于您的无限应用程序性能更差的硬件增量成本.

不要对这样的优化进行编码.维护它的人的代码.然后观察,测量,分析和优化.再次观察,再次测量,再次分析,再次优化.

优化几乎是开发的最后一步,而不是第一步.

*图组成.

  • 不,绝对不。我讨厌人们谈论预优化的方式。Java 是一种安全语言——这不是意大利面条代码的许可证。您仍然应该注意 Java 规范和语法,以及您正在使用的任何其他 API 或规范。当你正在编写一个 1000 行的微程序并且你可以做出这样的让步时,那么当然 - 去做吧。但任何比这更大的事情,以及在实际产品上工作,您最好 100% 了解您正在编写的代码的含义,并且您最好能够解释为什么这种性能损失是可以接受的。 (2认同)

Mar*_*nke 46

您应该默认使用字符串标签.

优点:

  • 列顺序的独立性
  • 更好的可读性/可维护性

缺点:

  • 您无法控制列名称(通过存储过程访问)

你更喜欢哪个?

整型?

int i = 1;
customerId = resultSet.getInt(i ++);
customerName = resultSet.getString(i ++);
customerAddress = resultSet.getString(i ++);

还是串?

customerId = resultSet.getInt("customer_id");
customerName = resultSet.getString("customer_name");
customerAddress = resultSet.getString("customer_address");

如果在第1位插入新列怎么办?您更喜欢哪种代码?或者,如果更改了列的顺序,您需要更改哪个代码版本?

这就是为什么你应该默认使用字符串标签.

  • 嗯,这甚至​​没有回答这个问题。这怎么能得到这么多票?如果你要扔这样的东西,那很好(在很多情况下我什至很感激),但至少回答最初的问题。 (2认同)

Kev*_*ock 6

答案已被接受,尽管如此,这里还有一些我尚未看到的其他信息和个人经验.

一般而言,如果可能,请使用列名(常量而不是文字).这更清晰,更易于维护,未来的更改不太可能破坏代码.

但是,列索引有一个用途.在某些情况下,这些更快,但不够充分,这应该覆盖名称*的上述原因.在开发处理ResultSets的工具和一般方法时,这些非常有价值.最后,可能需要索引,因为该列没有名称(例如未命名的聚合)或者存在重复的名称,因此没有简单的方法来引用它们.

*请注意,我已经编写了一些JDBC驱动程序并查看了一些开放源代码,并在内部使用列索引来引用结果列.在我使用的所有情况下,内部驱动程序首先将列名映射到索引.因此,您可以轻松地看到列名称在所有这些情况下总是需要更长时间.但是对于所有司机来说可能并非如此.


Jas*_*son 6

从java文档:

ResultSet接口提供getter方法(getBoolean,getLong等),用于从当前行检索列值.可以使用列的索引号或列的名称来检索值.通常,使用列索引会更有效.列从1开始编号.为了获得最大的可移植性,每行中的结果集列应按从左到右的顺序读取,每列应只读一次.

当然,每个方法(命名或索引)都有它的位置.我同意命名列应该是默认值.但是,在需要大量循环的情况下,以及在代码(或类)的同一部分中定义和维护SELECT语句的情况下,索引应该没问题 - 建议列出所选的列,而不仅仅是"SELECT*FROM ...",因为任何表更改都会破坏代码.