1

私はこれを自分のコードで実行しましたが、ループの経過時間が非常に長い理由がわかりません。

2 つのループがあります。Invoices テーブルの最初のループと InvoicesLignes テーブルの 2 番目のループ。

InvoicesLignes テーブルには「Code」というインデックスがあり、これは Invoice の「外部キー」です。データベースアクセスで Invoices と InvoicesLines の関係があるのですが、外部キーが定義されておらず、Joiner クラスが使えません。データベースを変更できません。

import java.io.File;
import java.util.Date;
import java.io.IOException;

import com.healthmarketscience.jackcess.*;

class MultipleLoop {

  public static void main(String[] args) {

    File jfile = new File("/project/database.mdb");

    Date start_date= new Date("2013/01/01");
    Date end_date= new Date("2013/12/31");

    try {

        Database db = DatabaseBuilder.open(jfile);

        Table invoices = db.getTable("Invoices");
        Table invoices_lignes = db.getTable("InvoiceLignes");

        Cursor cursor = CursorBuilder.createCursor(invoices_lignes.getIndex("Code"));

        for(Row invoice : invoices) {

          if ((start_date.before((Date)invoice.get("Date")) 
                    || start_date.equals((Date)invoice.get("Date"))) 
              &&  
              (end_date.after((Date)invoice.get("Date")) 
                    || end_date.equals((Date)invoice.get("Date")) )) {

          System.out.println(String.format("Invoice id : '%s' time : '%s'", 
                             invoice.get("Code"),
                             System.currentTimeMillis( ) ));

          long start = System.currentTimeMillis( );

          for (Row invoice_ligne : cursor.newIterable().addMatchPattern("Code",
                                                           invoice.get("Code"))) 
          {
              System.out.println(String.format("Loop time : '%s'", 
                                 System.currentTimeMillis( )));
          }

          long end = System.currentTimeMillis( );

          System.out.println(String.format("\n\nEnd loop time : '%s'", 
                             System.currentTimeMillis( )));
          long diff = end - start;

          System.out.println(String.format("Loop elapsed time : '%s' ms\n\n", 
                             diff ));

          }

        }

       } catch (IOException e) {
      //} catch (Exception e) {

        System.out.println(e);
      }

    }
}

そして私のログは

Invoice id : '19901/79018' time : '1411043140236' 
Loop time : '1411043140237'
Loop time : '1411043140237'
Loop time : '1411043140237'
Loop time : '1411043140237'


End loop time : '1411043141335'
Loop elapsed time : '1098' ms


 Invoice id : '138901/909719' time : '1411043141335'
 Loop time : '1411043141336'
 Loop time : '1411043141336'


 End loop time : '1411043142418'
 Loop elapsed time : '1083' ms


 Invoice id : '1309091/729090' time : '1411043142419'
 Loop time : '1411043142419'
 Loop time : '1411043142419'


 End loop time : '1411043143515'
 Loop elapsed time : '1096' ms

ループの経過時間が非常に長い理由がわかりません

お手伝いありがとうございます

4

1 に答える 1

1

外側の [Invoices] ループの反復ごとに [InvoicesLignes] テーブル全体を効果的にスキャンしていると思われます。あなたのアプローチ...

Table invoices = db_opened.getTable("Invoices");
Table invoices_lignes = db_opened.getTable("InvoicesLignes");
Cursor cursor = CursorBuilder.createCursor(invoices_lignes.getIndex("Code"));

for (Row row : invoices) {
    long start = System.currentTimeMillis( );
    System.out.println(String.format("Invoice : '%s'", start));

    for (Row crow : cursor.newIterable().addMatchPattern("Code", row.get("Code"))) {
        System.out.println(String.format("Loop : '%s'", System.currentTimeMillis( )));
    }

    long end = System.currentTimeMillis( );
    System.out.println(String.format("End loop : '%s'", System.currentTimeMillis( )));
    long diff = end - start;
    System.out.println(String.format("Loop elapsed time : '%s' ms", diff ));
}

... を生成します:

Invoice : '1411041092492'
Loop : '1411041092527'
Loop : '1411041092528'
Loop : '1411041092529'
End loop : '1411041094440'
Loop elapsed time : '1948' ms
Invoice : '1411041094442'
Loop : '1411041094443'
Loop : '1411041094444'
End loop : '1411041095882'
Loop elapsed time : '1440' ms

しかし、このバリエーション...

Table invoices = db_opened.getTable("Invoices");
Table invoices_lignes = db_opened.getTable("InvoicesLignes");

for (Row row : invoices) {
    long start = System.currentTimeMillis( );
    System.out.println(String.format("Invoice : '%s'", start));

    IndexCursor cursor = new CursorBuilder(invoices_lignes)
            .setIndexByName("Code")
            .setSpecificEntry(row.get("Code"))
            .toIndexCursor();
    for (Row crow : cursor) {
        System.out.println(String.format("Loop : '%s'", System.currentTimeMillis( )));
    }

    long end = System.currentTimeMillis( );
    System.out.println(String.format("End loop : '%s'", System.currentTimeMillis( )));
    long diff = end - start;
    System.out.println(String.format("Loop elapsed time : '%s' ms", diff ));
}

... を生成します:

Invoice : '1411041030007'
Loop : '1411041030060'
Loop : '1411041030062'
Loop : '1411041030063'
End loop : '1411041030063'
Loop elapsed time : '56' ms
Invoice : '1411041030067'
Loop : '1411041030069'
Loop : '1411041030070'
End loop : '1411041030071'
Loop elapsed time : '4' ms

また、UCanAccess の使用を検討しましたか? 対応する UCanAccess コード ...

String dbFileSpec = "C:/Users/Gord/Desktop/InvoiceTest.mdb";
try (Connection conn=DriverManager.getConnection("jdbc:ucanaccess://" + dbFileSpec)) {
    PreparedStatement psLignes = conn.prepareStatement("SELECT * FROM InvoicesLignes WHERE Code=?");
    Statement sInv = conn.createStatement();
    ResultSet rsInv = sInv.executeQuery("SELECT Code FROM Invoices");
    while (rsInv.next()) {
        long start = System.currentTimeMillis( );
        System.out.println(String.format("Invoice : '%s'", start));

        psLignes.setString(1, rsInv.getString("Code"));
        ResultSet rsLignes = psLignes.executeQuery();
        while (rsLignes.next()) {
            System.out.println(String.format("Loop : '%s'", System.currentTimeMillis()));
        }
        long end = System.currentTimeMillis( );
        System.out.println(String.format("End loop : '%s'", System.currentTimeMillis( )));
        long diff = end - start;
        System.out.println(String.format("Loop elapsed time : '%s' ms", diff ));
    }
    conn.close();
} catch (Exception e) {
    e.printStackTrace(System.out);
}

... を生成します:

Invoice : '1411041417462'
Loop : '1411041417478'
Loop : '1411041417478'
Loop : '1411041417479'
End loop : '1411041417479'
Loop elapsed time : '17' ms
Invoice : '1411041417482'
Loop : '1411041417483'
Loop : '1411041417483'
End loop : '1411041417483'
Loop elapsed time : '1' ms

UCanAccess は、Access データを hsqldb の「ミラー」データベース (デフォルトではメモリ内) にコピーするため、Java アプリケーションの起動時間を長くする可能性がありますが、ロードされると非常に高速であり、直接操作する代わりに通常の SQL を使用できます。ジャックセス API。

UCanAccess の詳細については、次を参照してください。

ODBC を使用せずに Java から Access データベースを操作する

于 2014-09-18T12:12:35.757 に答える