• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:MySQLでのテーブル名取得に制限はありますか?)

MySQLテーブル名取得に制限はある?

このQ&Aのポイント
  • MySQL5.5.27, mysql-connector-java-5.1.12を使用してDBにアクセスしています。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の容量は大丈夫ですか?

amer1
質問者

補足

ソースコードまでご提示いただきありがとうございます! >> コネクションに関しましては、一度つないだあと、使いまわす形になっています(使い回しはやはりまずかったのでしょうか…?) > Class.forName("com.mysql.jdbc.Driver"); > で使いまわしはあまり良くないです。 本筋から外れてしまってすみませんが、「Class.forName("com.mysql.jdbc.Driver");で使い回し」とはどういった意味でしょうか…? また、コネクションはSQL文を一回発行するごとに確立し、実行が終わるたびに閉じるのがやはり理想的なのでしょうか? > まずはMySQLに「SHOW TABLES;」で > 一覧が問題なく取得できるか確認します。 時間はかかりましたが、問題なく取得できました! ご提示頂いたソースコードも上手く動きました! PreparedStatementを使うと「SHOW ...」のような文も実行できるんですね。勉強になりました。 HDDの容量は、まだ300GB以上余っているため、特に問題はないと思います。 となると、元のソースコードが動かなかったのはやはりjdbcの方のバグなんでしょうかね…

その他の回答 (2)

回答No.3

> 本筋から外れてしまってすみませんが、「Class.forName("com.mysql.jdbc.Driver");で使い回し」とはどういった意味でしょうか…? そう言われると…どういう意味でしょうね(^^; いや、使いまわしはよくないですよ…と言いたかったのです(汗) > また、コネクションはSQL文を一回発行するごとに確立し、実行が終わるたびに閉じるのがやはり理想的なのでしょうか? はい、理想的です。 ムダなメモリーも食いませんし、不必要なバグに怯える必要もなくなります。 また、コネクションの確立も今のPCであれば大した速度でもないでしょうし。 ただ、使いまわしも1処理内であればいいと思います。 例えばfor文で回してる間にいちいち閉じるのは非現実的なので、 for文が始まる前に確立させて使いまわす…は、アリかもしれません。 この辺りは人の感覚やソースにもよりますので、一概には言えません。 不安があるウチは、実行が終わるたびに閉じるようにした方がよいでしょう。 この辺の事情は難しいですよね。 自分で言ってても正しいのか不安です…。 なので、DataSourceを使用しないのであればかなり気を付けるようにしています。 > となると、元のソースコードが動かなかったのはやはりjdbcの方のバグなんでしょうかね… 全ソースを見てないので何ともですが、そうなのかもしれませんね。 今お使いのJDKは5以上とお見受けしますが、元のソースコードは 1.4.2なので、この辺りも関係しているかもしれません。 何はともあれ、動いて良かったですね!

amer1
質問者

お礼

>> 本筋から外れてしまってすみませんが、「Class.forName("com.mysql.jdbc.Driver");で使い回し」とはどういった意味でしょうか…? > そう言われると…どういう意味でしょうね(^^; > いや、使いまわしはよくないですよ…と言いたかったのです(汗) 揚げ足をとってしまったようですみません(汗) 何か他のコネクション確立方法があるのかと思ってしまいました コネクションの確立タイミングにつきましても、細かく答えていただきましてありがとうございました。 今後の参考にさせていただきます。 Javaのバージョンは1.6.0_27なので、確かに参照していたjavadocのバージョンと異なっていましたね… バージョン違いも細かくチェックする癖をつけていこうと思います。 細かい質問にも丁寧に答えていただき、本当にありがとうございました!

回答No.1

こんにちは! getTablesの内容がないので何ともですが(^^; getTablesメソッドの中まではデバッグしてないですか? 私の経験ではこういう場合、コネクションを閉じていなかったとか 辺に再利用したとか、Java側の凡ミスが多いです。 ResultSetやConnectionはドコで閉じてますか? Githubのソースを端折らずに提示してもらえると 回答もしやすいかな~って感じです。

amer1
質問者

補足

ご回答頂きありがとうございます。 また、質問内容に不備がありすみませんでした。 getTablesに関しては、jdbcのDatabaseMetadataに元からあるメソッドで、javadocは↓の通りです。 中まではデバッグしきれていないです… http://docs.oracle.com/javase/1.4.2/docs/api/java/sql/DatabaseMetaData.html#getTables(java.lang.String, java.lang.String, java.lang.String, java.lang.String[]) コネクションに関しましては、一度つないだあと、使いまわす形になっています(使い回しはやはりまずかったのでしょうか…?) ResultSetも閉じ忘れていますね… とりあえず、頂いたアドバイスを元に、下記の通り修正しました(テーブル名、ユーザ名、パスワードは伏せさせて頂きました)。 ですが、まだ同様の現象が起きてしまいます。 https://gist.github.com/4146754 更に思い当たる解決法がありましたら、教えて頂ければと思います。 よろしくお願い致します。

関連するQ&A