如何在Android上使用ORMLite改进这种加载对象的方法?

时间:2012-03-19 11:28:26

标签: android performance android-emulator ormlite

我在Android上使用ormlite 4.35加载一组对象(及其外来对象)。对于getAllCragsWithLocation()方法中的时序,它(在模拟器中)需要16到19秒。

数据库中有590个Crags,40个没有位置。

记录了几行,例如

03-19 11:03:54.441: I/dalvikvm(1156): Jit: resizing JitTable from 1024 to 2048
03-19 11:03:55.531: D/dalvikvm(1156): GC_CONCURRENT freed 544K, 37% free 5174K/8199K, external 731K/1109K, paused 6ms+11ms

我应该以另一种方式加载对象吗?在sqlite3命令行运行查询大约需要100秒......

public List<Crag> getAllCragsWithLocation() {
        Log.i(TAG,"beginning db calls");
        long startQuery = System.currentTimeMillis();
        QueryBuilder<Crag,Integer> queryBuilder = helper.getCragDao().queryBuilder();
        List<Crag> results = new ArrayList<Crag>();
        try {
            queryBuilder.where().isNotNull("location_id");
            Log.i(TAG,queryBuilder.prepareStatementString());
            PreparedQuery<Crag> preparedQuery = queryBuilder.prepare();
            results = helper.getCragDao().query(preparedQuery);
        } catch (android.database.SQLException e) {
            Log.e(TAG,e.toString());
        } catch (SQLException e) {
            Log.e(TAG,e.toString());
        }
        Log.i(TAG,"ending query after "+((System.currentTimeMillis()-startQuery)/1000)+" seconds");
        return results;
    }

crag对象(简化)是:

@DatabaseTable
    public class Crag {
        public Crag() {
            //ormlite requires a no-arg constructor?
            guidebooks = new ArrayList<Guidebook>();
        }

        @DatabaseField(id=true) private int id;
        @ForeignCollectionField(eager = true)
        private Collection<Guidebook> guidebooks;
        @DatabaseField(foreign=true, foreignAutoRefresh = true, index=true)
        private uk.co.bmc.rad.models.Location location;
        @DatabaseField(foreign=true,foreignAutoRefresh=true)
        private SubRegion subRegion;
    }

外来对象比Crag更简单。出于显示的目的,仅在从数据库加载对象的位置处需要位置,但是在比较相等时我使用外来对象...

重复getAllCragsWithLocation()的回复以准备添加到MapOverlay。该过程的时间不到一秒钟。


更新: 我刚刚交换了DB4O进行比较,并且通过比较基本上立即加载了所有的碎片,所以我想我会接受它。


更新更新: 而不是快速交换DB4O,我花了更多的时间来比较这两者。

在JUnit 3 AndroidTestCase中,如果我将一条记录插入数据库然后直接查询,那么ORMLite和DB4O大约需要一秒钟(总计)插入并返回该对象。

如果我运行我的进程以插入590个对象,则ORMLite大约需要24秒,而DB40需要大约40秒。

在插入之后,如果我调用getAllCragsWithLocation()然后调用getAllCrags(),DB40需要7秒然后0秒才能返回一个Crags列表,所以我猜它有一个缓存可以加速第二个查询

虽然ORMLite在两个查询中花费大约7秒钟。

所以实际上它很少


更新更新: 今天抓住了Transformer Prime,只需运行应用程序就可以在1秒内加载峭壁,而模拟器上则为7秒。

因为我已经设法使用grok ormlite的查询语法;可以回退到原始sql并且sqlite表结构更可转移我将坚持使用ormlite而不是db4o。

2 个答案:

答案 0 :(得分:4)

我真的很惊讶它花了很长时间。

    @ForeignCollectionField(eager = true)
    private Collection<Guidebook> guidebooks;
    @DatabaseField(foreign=true, foreignAutoRefresh = true, index=true)
    private uk.co.bmc.rad.models.Location location;
    @DatabaseField(foreign=true,foreignAutoRefresh=true)
    private SubRegion subRegion;

这些字段中的每一个都会生成另一个需要时间的数据库查询,尽管我不希望秒。使用JOIN来满足渴望获取的远程对象时,ORMLite并不聪明。

尝试的一件事是在生成DAO实现时使用table-config进程来解决Android的dog,dog慢速反射实现。请参阅文档:

  

http://ormlite.com/docs/table-config

如果你弄清楚我会很好奇,虽然我明白你是否需要切换到其他一些包才能开始工作。

答案 1 :(得分:-1)

我认为您应该考虑使用ContentProvider。我已经创建了一个操作2k行的应用程序但是在模拟器上不到10秒就完成了查询和对象重新生成