【问题标题】:Row too big to fit into CursorWindow requiredPos=0, totalRows=1;行太大,无法放入 CursorWindow requiredPos=0, totalRows=1;
【发布时间】:2021-06-09 02:01:49
【问题描述】:

我不断收到这条烦人的消息!

当数据完成插入本地数据库时,我看到了这条消息

JNI critical lock held for 30.083ms on Thread[27,tid=23883,Runnable,Thread*=0xce150a00,peer=0x12cc0190,"Sqflite"]

如果我从表中选择数据,我会得到

W/CursorWindow(23809): Window is full: requested allocation 3095146 bytes, free space 2096696 bytes, window size 2097152 bytes
E/SQLiteQuery(23809): exception: Row too big to fit into CursorWindow requiredPos=0, totalRows=1; query: SELECT * FROM description_table;
I/flutter (23809): DatabaseException(Row too big to fit into CursorWindow requiredPos=0, totalRows=1) sql 'SELECT * FROM defect_description_table;' args []}

我没有任何blob数据,都是String。那为什么会这样呢?

这里是json结构

[{ "id": 1, "name": "Descriptions","data": [{..},{...} ... ]},{....},{....}]

我认为问题出在数据列表上,因为它包含大量数据(它有 10298 个)?

解决办法是什么?

我的插入方法

Future insertData(
      BuildContext context, String urls, String accessToken) async {
    CategoryTableData categoryData = CategoryTableData();
    try {
      var desc = List<Desc>();
      var headers = {
        'authorization': "Bearer" + " " + accessToken,
        "Accept": "application/json"
      };
      var url = xxx;
      var response = await http.get(url, headers: headers);
      var res = json.decode(response.body);
      for (var i in res) {
        if (i['name'] == "Descriptions") {
          desc.add(Desc(
              id: i['id'], name: i['name'], data: i['data']));
        }
      }
      await dao.batch((b) {
        b.insertAll(_dao.descTable, desc);
      });
      categoryData = await _dao.selectAllCategories();
      return categoryData;
    } catch (e) {
      print(e);
      categoryData = await _dao.selectAllCategories();
      return categoryData;
    }
  }

描述

class Desc extends Table {
  IntColumn get id => integer().nullable()();
  TextColumn get name => text().named("name").nullable()();
  TextColumn get data => text().map(const ListConverter()).nullable()();
}

【问题讨论】:

    标签: flutter dart android-sqlite flutter-moor


    【解决方案1】:

    留言Window is full: requested allocation 3095146 bytes, free space 2096696 bytes, window size 2097152 bytes

    告诉您您正在尝试将 3095146 字节的行(* = ALL 列)放入具有 2096696 字节(不含 2097152 (2Mb) 可用字节)的光标窗口(缓冲区)中。

    简单地说,要提取的数据太多了。当您插入数据时,这不是问题,因为没有中间和相对有限的缓冲区(光标窗口)。

    当您尝试检索商店图像时,您经常会看到这种情况。

    有多种方法可以用来规避这个问题。

    • 对于如此大的行,大小方面,您可以将实际数据存储为 文件并在数据库中存储文件的路径(这是 推荐用于图片)。

    • 减少提取的列可能会带来一些运气。 即不使用 SELECT * 而是仅指定列 你需要的。

    • 如果问题是列数据的累积大小,您可能可以使用多个提取多个部分。

      • 您可以使用length(column_name) function 选择数据药水,也可以使用CASE WHEN THEN ELSE END 表达式/构造,然后在完成后构建完整数据 已取回。

      • 可能是您无意中存储了更多数据,例如 在循环中意外连接数据。

    您需要了解所存储的数据才能知道上述哪些数据可能有用。

    【讨论】:

      【解决方案2】:

      问题是您使用在 insertData 中调用的方法 selectAllCategories() 检索了太多数据。 处理与 sqlite 连接的原生插件实现是给出错误的那个。 您应该使用普通 SQL 来限制查询,例如

      SELECT * FROM defect_description_table limit 500;
      

      或者,如果您使用 Moor 或其他在 Dao 中生成此代码的包,请查看他们关于限制查询的文档。

      【讨论】:

      • 问题不在于行数,而在于行的大小。游标窗口是一个缓冲区/缓存,将保存 x 行。如果无法容纳 1 行,那么您将获得上述结果。
      猜你喜欢
      • 2019-01-28
      • 2020-02-07
      • 2019-11-28
      • 2019-11-22
      • 2014-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多