52

JDBC を使用しているとき、次のような構造に出くわすことがよくあります。

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

私は自分自身 (およびコードの作成者) に、列の値を取得するためにラベルを使用しない理由を考えました。

int id = rs.getInt("CUSTOMER_ID");

私が聞いた最良の説明は、パフォーマンスに関するものです。しかし、実際には、それは処理を非常に高速にしますか? 私は測定を実行したことがありませんが、そうは思いません。ラベルによる検索は少し遅くなりますが、私の意見では、読みやすさと柔軟性が向上します。
では、列ラベルではなく列インデックスで列値を取得することを避けることについて、誰かが私に良い説明を与えることができますか? 両方のアプローチの長所と短所は何ですか (おそらく、特定の DBMS に関して)?

4

13 に答える 13

57

警告: 私はここで大げさになりそうです。

99%* の場合、物事を「より良く」する漠然とした考えを人々が持っているのはばかげたマイクロ最適化です。これは、何百万もの SQL の結果に対して非常にタイトでビジーなループに常に陥っている場合を除いて、まったく気付かないという事実を完全に無視しています。それを行っていない人にとっては、列のインデックス作成のバグを維持、更新、および修正するための開発者の時間コストは、パフォーマンスが非常に悪いアプリケーションのハードウェアの増分コストよりもはるかに大きくなります。

このような最適化をコーディングしないでください。それを維持する人のためのコード。次に、観察、測定、分析、および最適化を行います。もう一度観察し、もう一度測定し、もう一度分析し、もう一度最適化します。

最適化は、開発の最初のステップではなく、ほぼ最後のステップです。

※フィギュアは作り物です。

于 2008-10-09T11:26:27.550 に答える
49

デフォルトでは文字列ラベルを使用する必要があります。

長所:

  • 列の順序の独立性
  • 読みやすさ/保守性の向上

短所:

  • 列名を制御することはできません(ストアドプロシージャを介したアクセス)

どちらがいいですか?

ints?

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に新しい列が挿入された場合はどうなりますか?どのコードを好みますか?または、列の順序が変更された場合、どのコードバージョンを変更する必要がありますか?

そのため、デフォルトで文字列ラベルを使用する必要があります。

于 2008-10-09T14:07:06.493 に答える
7

それにもかかわらず、答えは受け入れられました。ここに、まだ提示されていない追加情報と個人的な経験がいくつかあります.

一般的に、可能であれば、列名 (リテラルではなく定数を使用することをお勧めします) を使用します。これにより、より明確になり、保守が容易になり、将来の変更によってコードが壊れる可能性が低くなります。

ただし、列インデックスの用途があります。場合によっては、これらの方が高速ですが、上記の名前の理由を上書きするほどではありません*。これらは、 を扱うツールや一般的な方法を開発する際に非常に役立ちますResultSet。最後に、列に名前がない (名前のない集計など) か、名前が重複していて両方を参照する簡単な方法がないため、インデックスが必要になる場合があります。

*いくつかの JDBC ドライバーを作成し、いくつかのオープン ソースを調べたところ、内部的にこれらは列インデックスを使用して結果列を参照していることに注意してください。私が扱ったすべてのケースで、内部ドライバーは最初に列名をインデックスにマップします。したがって、これらすべてのケースで、列名が常に長くかかることが容易にわかります。ただし、これはすべてのドライバーに当てはまるわけではありません。

于 2010-02-04T05:10:51.520 に答える
6

Java ドキュメントから:

ResultSet インターフェイスは、現在の行から列の値を取得するための getter メソッド (getBoolean、getLong など) を提供します。値は、列のインデックス番号または列の名前を使用して取得できます。一般に、列インデックスを使用する方が効率的です。列には 1 から番号が付けられます。移植性を最大限に高めるために、各行内の結果セットの列は左から右の順序で読み取られ、各列は 1 回だけ読み取られる必要があります。

もちろん、各メソッド (名前付きまたはインデックス付き) にはそれぞれの場所があります。名前付き列をデフォルトにすることに同意します。ただし、膨大な数のループが必要な場合、および SELECT ステートメントがコード (またはクラス) の同じセクションで定義および維持される場合、インデックスは問題ありません。テーブルを変更するとコードが壊れるため、「SELECT * FROM...」。

于 2013-06-26T06:27:26.633 に答える
4

もちろん、列名を使用すると読みやすさが向上し、メンテナンスが容易になります。ただし、列名の使用には裏返しがあります。ご存知のように、SQLでは同じ名前の複数の列名が許可されています。resultSetのgetterメソッドに入力した列名が、実際にアクセスする列名を指しているという保証はありません。理論的には、列名の代わりにインデックス番号を使用することをお勧めしますが、読みやすさが低下します。

于 2010-02-04T04:57:55.133 に答える
4

私は、Oracle データベースでこの正確なテーマについてパフォーマンス プロファイリングを行いました。私たちのコードには、多数の列と膨大な数の行を持つ ResultSet があります。リクエストがメソッド oracle.jdbc.driver.ScrollableResultSet.findColumn(String name) を実行するのにかかる 20 秒 (!) のうち、約 4 秒かかります。

明らかに全体的な設計に何か問題がありますが、列名の代わりにインデックスを使用すると、おそらくこの 4 秒かかります。

于 2008-12-31T09:06:00.647 に答える
3

あなたは両方の最高のものを持つことができます!列名を使用する保守性とセキュリティを備えたインデックスを使用する速度。

まず、結果セットをループしていない限り、列名を使用してください。

  1. アクセスする列ごとに 1 つずつ、一連​​の整数変数を定義します。変数の名前には、列の名前を含めることができます (例: iLast_Name)。

  2. 結果セット ループの前に、列のメタデータを繰り返し処理し、各整数変数の値を対応する列名の列インデックスに設定します。「Last_Name」列のインデックスが 3 の場合、「iLast_Name」の値を 3 に設定します。

  3. 結果セットのループでは、GET/SET メソッドで整数変数名を使用します。変数名は、アクセスされている実際の列名に関して、開発者/保守担当者にとって視覚的な手がかりですが、値は列インデックスであり、最高のパフォーマンスを提供します。

注: 最初のマッピング (つまり、列名からインデックスへのマッピング) は、ループ内のすべてのレコードと列ではなく、ループの前に 1 回だけ実行されます。

于 2010-11-28T21:00:09.327 に答える
2

ラベルを使用してもパフォーマンスに大きな影響はないと思います。しかし、s を使用しない別の理由がありますString。またはint、そのことについては。

定数の使用を検討してください。定数を使用するintと、コードが読みやすくなりますが、エラーが発生する可能性も低くなります。

より読みやすくなるだけでなく、定数はラベル名のタイプミスを防ぐことにもなります。タイプミスを犯すと、コンパイラはエラーをスローします。そして、どんな価値のあるIDEでもそれを拾います。Strings またはを使用する場合は、この限りではありませんints

于 2008-10-09T11:27:11.697 に答える
1

The JDBC driver takes care for the column to index look-up. So if you extract values by column name each time the driver makes a look-up (usually in hash map) to check the corresponding index for the column name.

于 2008-10-09T11:24:20.533 に答える
0

索引の使用は、最適化の試みです。

これによって節約された時間は、開発者が必要なデータを調べて、変更後にコードが適切に機能するかどうかを確認するために必要な余分な労力によって無駄になります。

テキストの代わりに数字を使用するのは、私たちの生まれつきの本能だと思います。

于 2008-10-09T12:29:17.687 に答える
0

Map でラベルを検索するだけでなく、追加の String の作成にもつながります。スタックで発生しますが、それでもコストがかかります。

それはすべて個々の選択に依存し、今日までインデックスのみを使用してきました:-)

于 2008-12-19T09:20:11.600 に答える
0

パフォーマンスは、どちらかのアプローチを選択するように強制できるものではないという以前の回答に同意します。代わりに、次のことを考慮するとよいでしょう。

  • コードの読みやすさ: コードを読むすべての開発者にとって、ラベルはインデックスよりもはるかに意味があります。
  • 保守: SQL クエリとその保守方法について考えてください。SQLクエリを修正/改善/リファクタリングした後、あなたのケースで起こりそうなこと:抽出された列の順序を変更するか、結果の列名を変更します。抽出された列の順序を変更すると(結果セットに新しい列を追加/削除した結果として)、発生する可能性が高くなるようです。
  • カプセル化: 選択した方法に関係なく、同じコンポーネントで SQL クエリを実行して結果セットを解析するコードを分離し、このコンポーネントのみが列名とインデックスへのマッピングを認識できるようにします (それらを使用することにした場合) )。
于 2008-10-09T12:20:59.110 に答える
0

他の投稿者が指摘しているように、特に強力な理由がない限り、私は列名に固執します。クエリの最適化などと比較すると、パフォーマンスへの影響はごくわずかです。この場合、メンテナンスは小さな最適化よりもはるかに重要です。

于 2019-04-15T14:47:59.693 に答える