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

2024-02-02

我正在 Android 上使用 ormlite 4.35 加载一组对象(及其外来对象)。 (在模拟器中)计时需要 16 到 19 秒getAllCragsWithLocation()方法如下。

数据库中有 590 个峭壁,其中 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 命令行运行查询大约需要百分之一秒......

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;
    }

峭壁对象(简化)是:

@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 秒。

因为我已经设法理解了 ormlite 的查询语法;可以依靠原始 sql 并且 sqlite 表结构更容易转移,我将坚持使用 ormlite 而不是 db4o。


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

    @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;

这些字段中的每一个都会生成另一个数据库查询,这将需要一些时间,尽管我预计不会有几秒钟。 ORMLite 使用起来并不聪明JOIN满足急切获取的远程对象。

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

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

我很好奇你是否能弄清楚,尽管我知道你是否需要切换到其他软件包才能工作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何改进在 Android 上使用 ORMLite 加载对象的方法? 的相关文章

随机推荐