查询数千个结果时,android中的Ormlite DAO变得非常慢

Posted

技术标签:

【中文标题】查询数千个结果时,android中的Ormlite DAO变得非常慢【英文标题】:Ormlite DAO in android getting really slow when querying more than few thousand results 【发布时间】:2011-12-10 07:41:24 【问题描述】:

当有几千个结果时,通过 Ormlite DAO 查询数据时遇到问题。

代码:

List<Point> pl = db.getPointsDAO().queryBuilder().where().
            eq("route_id", croute).query();

当我想获得当前路线 croute 的大量点列表 List&lt;Point&gt; pl 时,我必须等待 40 秒才能获得 40.000 点。

Point.class 在哪里:

@DatabaseTable(tableName = "points")
public class Point extends BaseEntity 
    @DatabaseField(generatedId = true)
    private Integer point_id;
    @DatabaseField(canBeNull = false)
    ...
    @DatabaseField(canBeNull = false)
    private Double dose;
    @DatabaseField(dataType=DataType.DATE_STRING, format="yyyy-MM-dd HH:mm:ss")
    public Date date;
    @DatabaseField(canBeNull=true,foreign=true)
    private Route route;

public Point() 
    super();
;
... ...

Route.class 是:

@DatabaseTable(tableName = "routes")
public class Route extends BaseEntity 

    @DatabaseField(generatedId = true)
    private Integer route_id;

    @DatabaseField(canBeNull = true)
    private String name;

    @ForeignCollectionField(eager = false)
    ForeignCollection<Point> points;

    public Route() 
        super();
    
    ... ...

一些想法我做错了什么?

谢谢, 托尼

【问题讨论】:

【参考方案1】:

尝试@toni 的几件事。

    我会考虑将您的 Date 存储为 DATE_LONG 而不是一个字符串,这样可以节省 40k 字符串/日期转换。 @Selvin 是对的,如果有某种方法可以让您遍历数据库,这可能会降低您的内存需求并加快速度。请参阅 ORMLite 中的 dao.iterator()。 我会使用 intdouble 原语来降低每个对象的 GC,尽管我怀疑这会产生很大的不同。 尝试加载 1000 点,然后是 10000 点,然后是 20000 点,看看在某个时间点性能是否下降。这将告诉您您正在达到内存限制。 使用adb logcat 实用程序查看您是否可以查看GC 时间,看看您是否只是在破坏收集器。你可以做的任何事情来降低你的内存使用量都会有所帮助。寻找类似的行:
    GC_EXPLICIT freed 4140 objects / 216560 bytes in 114ms
    虽然我怀疑这是问题所在,但您会丢失索引吗?尝试在外部route 字段上添加index = true

【讨论】:

嗨@Gray。我实施了您的建议并且也使用了 dao.iterator() 但我仍然获得了 1k 点/秒的速度。我检查了对数刻度(100,1000,10000,...),差别不大。注释转换有问题吗?我应该使用原始查询吗?谢谢。 这不是注释转换,它只发生在 DAO 创建时。 GC 日志说了什么?在那里度过了很多时间?回到办公桌后,我会尝试进行批量测试,看看是否有任何发现...... 在加载 4.3k 点时,它显示一次 GC_EXPLICIT freed 10K, 50% free... 但它显示:GC_CONCURRENT freed 543K, 42% free 4439K/7559K, external 0K/512K, paused 3ms+11ms 一直...循环...谢谢@Gray! 这看起来你只是在创建太多对象@toni。在查看 ORMLite 时,它​​看起来只会创建 Point 对象——除了底层 android API 所做的那些之外,没有临时对象。我们还没有解决您的问题,对吧? 我不懂你。那么这个加载数据的速度是正常的吗?

以上是关于查询数千个结果时,android中的Ormlite DAO变得非常慢的主要内容,如果未能解决你的问题,请参考以下文章

在使用原始查询时选择比较 ormlite 中的两列值的行

在 CursorAdapter 中使用带有 ORMLite 的 Android 游标

查找雅典娜查询结果的来源

使用for循环生成条件时如何在ormlite中编写查询

android OrmLite 实际应用

android OrmLite 实际应用