2

Spring jdbcTemplate を使用して、Java アプリケーションで MySQL クエリを実行しています。これは私の機能です:

public static ArrayList<Map<String, Object>> query(String q) throws Exception {

    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

    @SuppressWarnings("unchecked")
    List<Map<String, Object>> result = jdbcTemplate.queryForList(q);

    return (ArrayList<Map<String, Object>>) result;

}

この特定のケースでは、関数に次のクエリを渡します。

"SELECT * FROM test WHERE name IN('string1', 'string2', 'string3', ...)";

テーブルtestには 6 列しかなく、文字列はIN数個から 100 個の記号までさまざまです。クエリの実行に280 ミリ秒jdbcTemplate.queryForList()かかります。注:関数全体ではなく、実行に280 ミリ秒かかります。MySQL クライアント (HeidiSQL) でまったく同じクエリを実行すると、わずか16 ミリ秒しかかかりません。更新:ハイジはオープンな接続を維持しているため、公平な比較ではありません。jdbcTemplate.queryForList()query

質問: jdbcTemplate.queryForList()MySQL クライアントで実行された同じクエリと比較して、なぜ非常に遅いのですか? 私は純粋に便利な理由で使用していArrayList<Map<String, Object>>ます。必要な結果を取得できます。それをスピードアップするためにできることはありますか、それとも一緒にドロップjdbcTemplateして別のものを使用する必要がありますか?

更新: OK、関数を jdbcTemplate からプレーンな jdbc を使用するように変更しました。これがその忌まわしき姿です。それが、そもそも jdbcTemplate を使用した理由です。同じクエリを実行するのに200 ミリ秒かかるようになりました。わずかな改善ですが、それでも遅すぎます...

public static ArrayList<Map<String,Object>> query(String Full_Command) {

    try {

        String URL = "jdbc:mysql://localhost/dbname";
        String USER = "root";
        String PASS = "";
        java.sql.Connection Con = DriverManager.getConnection(URL, USER, PASS);

        //create statement
        Statement Stm = null;
        //Stm = Con.createStatement();
        Stm = (Statement) Con.createStatement();

        //query
        ResultSet Result = null;
        boolean Returning_Rows = Stm.execute(Full_Command);
        if (Returning_Rows) {
            Result = Stm.getResultSet();
        } else {
            return new ArrayList<Map<String,Object>>();
        }

        //get metadata
        ResultSetMetaData Meta = null;
        Meta = Result.getMetaData();

        //get column names
        int Col_Count = Meta.getColumnCount();
        ArrayList<String> Cols = new ArrayList<String>();
        for (int Index=1; Index<=Col_Count; Index++) {
            Cols.add(Meta.getColumnName(Index));
        }

        //fetch out rows
        ArrayList<Map<String, Object>> Rows = new ArrayList<Map<String,Object>>();

        while (Result.next()) {
            HashMap<String,Object> Row = new HashMap<String,Object>();
            for (String Col_Name:Cols) {
                Object Val = Result.getObject(Col_Name);
                Row.put(Col_Name,Val);
            }
            Rows.add(Row);
        }

        //close statement
        Stm.close();

        //pass back rows
        return Rows;

    } catch (Exception Ex) {

        System.out.print(Ex.getMessage());
        return new ArrayList<Map<String,Object>>();

    }

}

更新 2: JDBC 関数を実行時間に分割していません。この 1 行がボトルネックであり、毎回約 190 ミリ秒かかります。

java.sql.Connection Con = DriverManager.getConnection(URL, USER, PASS);

コメントはありますか?

4

4 に答える 4

2

JdbcTemplate のせいではありません。理由は次のとおりです。

まず、接続を確立する際のオーバーヘッドを割り引く必要があります。このオーバーヘッドは 500 ミリ秒にもなる可能性があります。これは正常です。

次に、 MySQL クライアントでクエリを実行するとき、プログラムを実行した直後にクエリを実行していますか? クエリがキャッシュされるため... ディスク I/O のレベルでも。したがって、同じクエリを 2 回実行すると、2 回目はキャッシュにより高速に実行されます。

第三に、列にインデックスを付けていますnameか?

第 4 に、接続のオーバーヘッドが本当に重要な場合は、接続を節約するか、接続プーリングを検討することもできます。

于 2013-08-06T13:53:59.270 に答える
0

最初の DB 接続を確立するためのオーバーヘッドになる可能性があります。確実に接続が確立されたら、パフォーマンスのベンチマークを試してください。

このようなものは遅くあるべきではありません。ゲインはどこかにあります!

于 2013-08-06T12:06:18.257 に答える