![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?5a7ff87)
MySQL5.5.27, mysql-connector-java-5.1.12を用いて、DBにアクセスしています。
DBに登録されたテーブル名を取得しようと思い、以下の様なメソッドを作成しました(テーブル名は全て数字です)。
https://gist.github.com/4146754
しばらくは順調に動いていたのですが、DBに登録されたレコード数が25万を超えたあたりで、動かなくなってしまいました。
デバッグをして原因を調べたところ、
metadata.getTables(null, "%", "%", null);
の実行時に、メソッドを呼び出したまま固まってしまっていることが分かりました。
同じコードを、別のDBに対して作用させたところ、問題なく動いたため、レコード数が多いのが原因ではないのかと考えたのですが、何かよい対処法はありますでしょうか?
よろしくお願い致します。
No.2ベストアンサー
- 回答日時:
> getTablesに関しては、jdbcのDatabaseMetadataに元からあるメソッドで、javadocは↓の通りです。
これは失礼しました(汗)
デバッグできてなくてOKです…
> コネクションに関しましては、一度つないだあと、使いまわす形になっています(使い回しはやはりまずかったのでしょうか…?)
Class.forName("com.mysql.jdbc.Driver");
で使いまわしはあまり良くないです。
今Gistに上げられているソースは問題なさそうですねぇ。
では、問題を切り分けていきましょう!
まずはMySQLに「SHOW TABLES;」で
一覧が問題なく取得できるか確認します。
これで問題なく取得できればMySQL側は問題なしです。
次に、ソースを生のSQLではどうか試してみます。
以下のようなソースに書き換えてみてください。
(インデントがなくてすいません…)
public ArrayList<Long> getExistsTable() {
ArrayList<Long> existsTable = new ArrayList<Long>();
ResultSet rs = null;
Connection connection = null;
PreparedStatement ps = null;
try {
// ドライバクラスをロード
Class.forName("com.mysql.jdbc.Driver");
// データベースへ接続
connection = DriverManager.getConnection("jdbc:mysql://localhost/" + "databaseName","userName","password");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
try {
ps = connection.prepareStatement("SHOW TABLES");
rs = ps.executeQuery();
while(rs.next()){
try{
existsTable.add(rs.getLong(1));
}catch(NumberFormatException e){
// e.printStackTrace();
}
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if(rs != null){
rs.close();
}
if(ps != null){
ps.close();
}
if(connection != null){
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
System.out.println("size = " + existsTable.size());
return existsTable;
}
(本当はこんなチマチマ閉じなくていいのですが)
これで問題なければ
DatabaseMetaData metadata = connection.getMetaData();
がよくなかったということになります。
(たまにJavaでもバグはあるものです。)
あとは25万件との話ですが、HDDの容量は大丈夫ですか?
この回答への補足
ソースコードまでご提示いただきありがとうございます!
>> コネクションに関しましては、一度つないだあと、使いまわす形になっています(使い回しはやはりまずかったのでしょうか…?)
> Class.forName("com.mysql.jdbc.Driver");
> で使いまわしはあまり良くないです。
本筋から外れてしまってすみませんが、「Class.forName("com.mysql.jdbc.Driver");で使い回し」とはどういった意味でしょうか…?
また、コネクションはSQL文を一回発行するごとに確立し、実行が終わるたびに閉じるのがやはり理想的なのでしょうか?
> まずはMySQLに「SHOW TABLES;」で
> 一覧が問題なく取得できるか確認します。
時間はかかりましたが、問題なく取得できました!
ご提示頂いたソースコードも上手く動きました!
PreparedStatementを使うと「SHOW ...」のような文も実行できるんですね。勉強になりました。
HDDの容量は、まだ300GB以上余っているため、特に問題はないと思います。
となると、元のソースコードが動かなかったのはやはりjdbcの方のバグなんでしょうかね…
No.3
- 回答日時:
> 本筋から外れてしまってすみませんが、「Class.forName("com.mysql.jdbc.Driver");で使い回し」とはどういった意味でしょうか…?
そう言われると…どういう意味でしょうね(^^;
いや、使いまわしはよくないですよ…と言いたかったのです(汗)
> また、コネクションはSQL文を一回発行するごとに確立し、実行が終わるたびに閉じるのがやはり理想的なのでしょうか?
はい、理想的です。
ムダなメモリーも食いませんし、不必要なバグに怯える必要もなくなります。
また、コネクションの確立も今のPCであれば大した速度でもないでしょうし。
ただ、使いまわしも1処理内であればいいと思います。
例えばfor文で回してる間にいちいち閉じるのは非現実的なので、
for文が始まる前に確立させて使いまわす…は、アリかもしれません。
この辺りは人の感覚やソースにもよりますので、一概には言えません。
不安があるウチは、実行が終わるたびに閉じるようにした方がよいでしょう。
この辺の事情は難しいですよね。
自分で言ってても正しいのか不安です…。
なので、DataSourceを使用しないのであればかなり気を付けるようにしています。
> となると、元のソースコードが動かなかったのはやはりjdbcの方のバグなんでしょうかね…
全ソースを見てないので何ともですが、そうなのかもしれませんね。
今お使いのJDKは5以上とお見受けしますが、元のソースコードは
1.4.2なので、この辺りも関係しているかもしれません。
何はともあれ、動いて良かったですね!
>> 本筋から外れてしまってすみませんが、「Class.forName("com.mysql.jdbc.Driver");で使い回し」とはどういった意味でしょうか…?
> そう言われると…どういう意味でしょうね(^^;
> いや、使いまわしはよくないですよ…と言いたかったのです(汗)
揚げ足をとってしまったようですみません(汗)
何か他のコネクション確立方法があるのかと思ってしまいました
コネクションの確立タイミングにつきましても、細かく答えていただきましてありがとうございました。
今後の参考にさせていただきます。
Javaのバージョンは1.6.0_27なので、確かに参照していたjavadocのバージョンと異なっていましたね…
バージョン違いも細かくチェックする癖をつけていこうと思います。
細かい質問にも丁寧に答えていただき、本当にありがとうございました!
No.1
- 回答日時:
こんにちは!
getTablesの内容がないので何ともですが(^^;
getTablesメソッドの中まではデバッグしてないですか?
私の経験ではこういう場合、コネクションを閉じていなかったとか
辺に再利用したとか、Java側の凡ミスが多いです。
ResultSetやConnectionはドコで閉じてますか?
Githubのソースを端折らずに提示してもらえると
回答もしやすいかな~って感じです。
この回答への補足
ご回答頂きありがとうございます。
また、質問内容に不備がありすみませんでした。
getTablesに関しては、jdbcのDatabaseMetadataに元からあるメソッドで、javadocは↓の通りです。
中まではデバッグしきれていないです…
http://docs.oracle.com/javase/1.4.2/docs/api/jav … java.lang.String, java.lang.String, java.lang.String[])
コネクションに関しましては、一度つないだあと、使いまわす形になっています(使い回しはやはりまずかったのでしょうか…?)
ResultSetも閉じ忘れていますね…
とりあえず、頂いたアドバイスを元に、下記の通り修正しました(テーブル名、ユーザ名、パスワードは伏せさせて頂きました)。
ですが、まだ同様の現象が起きてしまいます。
https://gist.github.com/4146754
更に思い当たる解決法がありましたら、教えて頂ければと思います。
よろしくお願い致します。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- MySQL PHP 画像のアップロード Qiita 2 2022/11/28 04:44
- Access(アクセス) DoCmd.SearchForRecord が動かない時の解決方法 3 2022/07/22 15:31
- Access(アクセス) アクセス テーブルの空白を変数に置換するボタンが作りたい 4 2022/07/08 11:19
- SQL Server DBのテーブルの設計ができず困っています。 2 2023/06/29 16:43
- MySQL PHPとMySQLを使った掲示板の作り方 1 2022/06/02 13:00
- その他(データベース) pythonでsqlight勉強中、クエリー結果の利用法教えて下さい 1 2022/04/28 20:38
- PostgreSQL PostgressからMySQL(MariaDB)へ構造を変更する際のTimestamp等について 2 2023/04/04 12:09
- Visual Basic(VBA) ACCESS DAO で不要なテーブルのフィールド(列)の削除 4 2022/06/23 12:13
- PHP クエリObjectをforeachで回す時に、次のレコードへ移動せずに次のレコードを取得したい 2 2022/07/28 15:29
- MySQL my_itemsテーブルのIDにAUTO_INCREMENT を追加ができるかで 1 2023/01/03 09:09
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
#1062 - '0' は索引 'PRIMARY' ...
-
日本の全市区町村を人口密度が...
-
下の画像はSQLの4大命令の性質...
-
データベースの複製の仕方(mysql)
-
SQLでカラムを追加し、条件に合...
-
select *, `人口(男)`AND`人口(...
-
テーブル名が可変の場合のクエ...
-
SQLについて教えて下さい。 SEL...
-
テーブル作成です。どこかのス...
-
MAMPで80ポートが使用されている...
-
同一のユーザー、同一商品のと...
-
SQLです。こんな感じですか?あ...
-
書籍の内容はまともでしょうか?
-
SQLで日付別のIDを生成するには
-
mysql>status で
-
下記の問合せを行うクエリを、P...
-
下記の問合せを行うクエリを、P...
-
エラー 1068 (42000): 複数の主...
-
MySQLのテーブル作成でハイフン...
-
「重複を間引いた数」をcountし...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Null値が入れられない
-
NULLを含む列の足し算
-
MySQLの特定のカラムの内容を全...
-
nullと同じく空白をCountしない...
-
SQLでLIMIT句を入れるとエラー...
-
SQL文を入力したらエラー
-
テーブル作成時に、「`id` int(...
-
MySQLで関連したデータを横に並...
-
MySQLで項目の反復定義(COBOL...
-
3つのテーブルから、データが...
-
phpとSQLで複数条件で検索する...
-
SQL文でダブルクォートか
-
MySQLでのテーブル名取得に制限...
-
VIEWに対してWHERE句をつける
-
空白文字を含む文字列データの検索
-
SQL任意に並び替えをしたい
-
コマンドプロンプト 複数の実...
-
後でemailに追加でPRIMARY KEY...
-
sqlの中で、 例えば条件句で AN...
-
JOIN使ってないのに、JOIN操作...
おすすめ情報