JDBCに関するふとした疑問
JDBCについてちょっとした疑問がわきました。
大抵の方がご存じの通り、JDBCでResultSetから値を取得する場合、
- インデクス指定
- カラム名指定
の2通りの方法があります。
例えばこんな感じですね。
インデクス指定
ResultSet#getInt(int columnIndex)
カラム名指定
ResultSet#getInt(String columnName)
保守性からいえばカラム名指定の方が分かりやすいのは明白ですが、
カラム名 → インデクスの変換処理が必要になるのは確実です。
実際にPostgreSQLのJDBCドライバ(jdbc-8.3-604)では、
public int getInt(String columnName) throws SQLException
{
return getInt(findColumn(columnName));
}
と、カラム名指定の場合はインデクスへの変換処理をしていますね。
で、処理速度的にこの変換処理が無視できなくなるのか、気になったわけです。
変換処理を見てみましょう。
private int findColumnIndex(String columnName)
{
if (columnNameIndexMap == null)
{
columnNameIndexMap = new HashMap(fields.length * 2);
// The JDBC spec says when you have duplicate columns names,
// the first one should be returned. So load the map in
// reverse order so the first ones will overwrite later ones.
for (int i = fields.length - 1; i >= 0; i--)
{
columnNameIndexMap.put(fields[i].getColumnLabel().toLowerCase(Locale.US), new Integer(i + 1));
}
}Integer index = (Integer)columnNameIndexMap.get(columnName);
if (index != null)
{
return index.intValue();
}index = (Integer)columnNameIndexMap.get(columnName.toLowerCase(Locale.US));
if (index != null)
{
columnNameIndexMap.put(columnName, index);
return index.intValue();
}return 0;
}
予想通り、変換にはHashMapが使われています。
ほとんど、通常の処理では気にならないはずですね。
ただし、カラム数が多いとオーバヘッドが気になってくるかも知れません。
もう1点、気になるのは、ソースコード中に、
// The JDBC spec says when you have duplicate columns names,
// the first one should be returned. So load the map in
// reverse order so the first ones will overwrite later ones.
とのコメントがあるという事でしょうか。
「JDBCの仕様に従うために、逆順に配列を走査してますよ」と。
面白い工夫ですね。
そうすると、仕様を素直に守るために、
配列を先頭から舐めるJDBCドライバ(当然遅い)
の実装もありそうですね。
ここまでの調査からは、
- カラム数が多いと変換処理のオーバヘッドが無視できなくなるのでは無いか?
- 変換処理が配列の走査で実現されているドライバが無いか?
という感じです。
おいおい、検証してみようと思います。
ま、あまり気にするレベルでは無いのかも知れませんが。