【问题标题】:Cursor size limit in Android SQLiteDatabaseAndroid SQLiteDatabase 中的光标大小限制
【发布时间】:2011-03-23 14:04:06
【问题描述】:

我从互联网上下载了一个数据库。我将它保存在我的数据文件夹中并打开它。 数据库内有一个包含 6 个字段的“广告”表。其中 2 个字段是 BLOB。当我想从这个表中读取时......我有一些问题......我注意到当我读取一个大于 1 兆字节的 blob 字段的行时,这会导致异常......“从行获取字段槽0 列 0 失败”。如果它是一个小斑点,一切都很好......提前谢谢:)

【问题讨论】:

    标签: android blob size limit database-cursor


    【解决方案1】:

    由于动态解压,内部资产有 1MB 的限制; 1MB 的限制似乎也适用于光标 blob,但这似乎没有记录在任何地方。

    通常你应该避免在 SQLite 中使用 blob,因为它们的性能很差;而是将 blob 数据保存为文件并将文件的位置存储在数据库中。

    【讨论】:

    • 通常你应该避免在 SQLite 中使用 blob,因为它们表现不佳;而是将 blob 数据保存为文件并将文件的位置存储在数据库中。 --- > 非常感谢..
    • AndroidKid 已开启。我确信存在 BLOB 的用例,但是我想不出一个。 :)
    【解决方案2】:

    从 SQLite 数据库中读取小于 100KB 的 BLOB 比从文件系统中读取要快。但是,任何大于此值的内容最好保存在磁盘上,并在 db.xml 中提供参考。 更多信息:http://www.sqlite.org/intern-v-extern-blob.html

    【讨论】:

    • 感谢您的参考。
    • @frederick nyawaya :什么是最好的?将图像/音频作为 Blob 存储在数据库中还是仅存储文件系统的路径?
    • @Ajay 作为文件系统的一部分
    【解决方案3】:

    每个操作有 1MB 的限制。 (在 SQLite 查询的情况下,我不确定这是每行还是每列)。该限制是由于 SQLite API 通过 Binder/Parcel IPC 系统与进程外的 sqlite 交互。同样的限制也适用于 Bundle 中的值(例如 Intent extras)。

    Binder 事务缓冲区有一个有限的固定大小,目前为 1Mb, 该进程的所有正在进行的事务共享。

    见:http://developer.android.com/reference/android/os/TransactionTooLargeException.html

    【讨论】:

    • 1 MB 限制是光标窗口的最大大小。这是用于存储 IPC 传输结果行的内存缓冲区。窗口大小会动态增长到此限制。
    【解决方案4】:

    Android 中的 BLOB 支持似乎尚未实现...

    http://www.basic4ppc.com/forum/basic4android-updates-questions/6648-support-sqlite-blob.html

    哪些数据存储在 BLOB 字段中?我猜是图片。

    我建议不要使用 BLOB。文件系统是二进制数据更好的选择。

    您能详细解释一下您想用数据库完成什么吗?

    【讨论】:

    • 更好的答案:不要在 any 数据库中使用 BLOB。 RDBM 并不是特别适合存储大量未格式化的数据——这就是文件系统的用途。
    • @David Souther 感谢您的评论,您说得对。我想认为 BLOB 对某些东西有用,这就是为什么我不太确定。但是,我想不出一个好的用例。存储蓝光电影? (开玩笑)
    • 那篇文章是 2007 年发布的。BLOB 绝对受支持,并且至少从 1.6 版本开始就支持(又名 API 级别 4,又名甜甜圈)。正如 OP 所指出的,问题在于 BLOB 值超过 1MB。
    • 现代文件系统也是数据库,那么DB怎么不是存放二进制数据的好地方呢?
    【解决方案5】:

    您使用的查询是“选择”表示 blob 吗?可以省略吗?如果不能,您是否在使用:

     blob = rs.getBlob(column) ;
     InputStream in = blob.getBinaryStream();
    

     blob.getBytes(1, lengthOblob) ;
    

    第一种方法可以让您分块读取 blob。第二个是一次性加载所有 blob。

    【讨论】:

    • 我不确定您所说的“一次全部加载”是什么意思。鉴于getBlob() 返回一个byte[],数据已经在堆上...
    • 假设您的 rs 是一个光标,由于光标窗口大小,第一次调用 getBlob() 将在大数据上失败。
    猜你喜欢
    • 1970-01-01
    • 2012-04-10
    • 1970-01-01
    • 2015-01-03
    • 2013-04-05
    • 1970-01-01
    • 2012-08-02
    • 2014-06-17
    • 2014-06-12
    相关资源
    最近更新 更多