8

.Net と Java を使用して、Oracle DB から 100 万件のレコードを読み取っています。.Net では、Java ojdbc6 シン クライアントで ODP.Net を使用しています。.Net ではデータの読み取りに約 10 秒かかり、Java では約 2 分かかります。なぜそんなに大きな違いがあるのですか?

コードは次のとおりです。

。ネット:

      try
        {
            DateTime dt1 = DateTime.Now;

            OracleConnection con = new OracleConnection();
            con.ConnectionString = "Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=myHost)(PORT=myPort)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=myService)));User Id=myId;Password=myPass;";

            con.Open();
            string cmdQuery = "SELECT * FROM DROPME";

            OracleCommand cmd = new OracleCommand(cmdQuery);
            cmd.Connection = con;
            cmd.CommandType = CommandType.Text;

            int i = 0;
            OracleDataReader reader = cmd.ExecuteReader();
            while (reader.Read())
            {
                Object o1 = reader.GetValue(0);
                Object o2 = reader.GetValue(1);
                Object o3 = reader.GetValue(2);
                Object o4 = reader.GetValue(3);
                Object o5 = reader.GetValue(4);
                Object o6 = reader.GetValue(5);
                Object o7 = reader.GetValue(6);                    
                i++;
            }

            DateTime dt2 = DateTime.Now;

            double elapsed = (dt2 - dt1).TotalSeconds;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

ジャワ:

    try
    {
        long t0 = System.currentTimeMillis();
        oracleDataSource = new OracleDataSource();
        oracleDataSource.setURL("jdbc:oracle:thin:myId/myPass@myHost:myPort:myService");
        Connection connection = oracleDataSource.getConnection();
        PreparedStatement statement = connection.prepareStatement("SELECT * FROM DROPME");
        ResultSet result = statement.executeQuery();
        int i = 0;
        while (result.next())
        {
            result.getObject(1);
            result.getObject(2);
            result.getObject(3);
            result.getObject(4);
            result.getObject(5);
            result.getObject(6);
            result.getObject(7);
            i++;
        }
        long t1 = System.currentTimeMillis();
        long elapsed = (t1 - t0)/1000;
        int t = 0;
    }
    catch (Exception ex)
    {
        ex.printStackTrace();
    }

編集: setFetchSize() は仕事をしました、ありがとう。

4

2 に答える 2

8

Java では、デフォルトで ResultSet が完全に取得され、メモリに格納されます。これは、大きな ResultSet を持つクエリには適していません。ストリーミングされた結果を使用するには、次を使用する必要があります。

stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);

所要時間は比較していませんが、これははるかに高速になると思います。

于 2012-08-23T09:11:15.860 に答える
6

私の経験では、Oracle JDBC ドライバーは、一括転送用にすぐに使用できるように構成されていません。デフォルトでは、一度にネットワーク経由で 10 レコードのみを転送します。したがって、1,000,000 のレコードがある場合、ドライバーは 100,000 のネットワーク アクセスを発生させます。

ResultSet次のコードを使用して、一度に取得するレコード数を指定できます。

result.setFetchSize(1000);

さまざまなサイズを自由に試してみてください。私が取り組んだアプリケーションの少なくとも 1 つで、処理時間が劇的に (数分から数秒に) 短縮されました。

于 2012-08-23T09:46:55.240 に答える