【问题标题】:How to obtain the size of a BLOB without reading the BLOB's content如何在不读取 BLOB 内容的情况下获取 BLOB 的大小
【发布时间】:2011-08-01 13:49:01
【问题描述】:

我对 sqlite 中的 BLOB 有以下疑问:

  • sqlite 是否跟踪 BLOB 的大小?
  • 我猜是这样,但是长度函数是使用它,还是读取 BLOB 的内容?
  • 如果 sqlite 跟踪 BLOB 的大小并且长度不使用它,是否可以通过其他一些功能访问该大小?

我问这个是因为我想知道是否应该实现在附加列中设置 BLOB 大小的触发器,或者我是否可以动态获取大小而不会影响 sqlite 读取 BLOB 的性能。

【问题讨论】:

  • 我遇到了类似的问题(需要测试一个 blob 是否不为空),并且直接使用column_name is not null 进行测试确实比长度length(column_name) is not null 花费了很多时间。很明显,length() 不会读取 blob 的内容。 (恕我直言is not null 应该这样做,或者至少测试之前的长度。)

标签: sql triggers sqlite blob


【解决方案1】:

来源:

** In an SQLite index record, the serial type is stored directly before
** the blob of data that it corresponds to. In a table record, all serial
** types are stored at the start of the record, and the blobs of data at
** the end. Hence these functions allow the caller to handle the
** serial-type and data blob seperately.
**
** The following table describes the various storage classes for data:
**
**   serial type        bytes of data      type
**   --------------     ---------------    ---------------
**      0                     0            NULL
**      1                     1            signed integer
**      2                     2            signed integer
**      3                     3            signed integer
**      4                     4            signed integer
**      5                     6            signed integer
**      6                     8            signed integer
**      7                     8            IEEE float
**      8                     0            Integer constant 0
**      9                     0            Integer constant 1
**     10,11                               reserved for expansion
**    N>=12 and even       (N-12)/2        BLOB
**    N>=13 and odd        (N-13)/2        text

换句话说,blob 大小是串行的,它的长度就是“(serial_type-12)/2”。
此序列号存储在实际 blob 之前,因此您无需读取 blob 即可获取其大小。
调用 sqlite3_blob_open 然后调用 sqlite3_blob_bytes 来获取这个值。

【讨论】:

  • 我可以使用 SQL 调用这两个函数吗?
  • 取决于您使用的 SQLite3 版本。见:stackoverflow.com/questions/250940/…
  • AFAICT 该链接指向如何使用长度函数...除非我遗漏了什么...
  • arrite,那么,跟进您的回答,使用 length 函数不会导致读取整个 BLOB?
  • 没错。在我研究过的资料中,“length()”函数将按照我的答案计算。
【解决方案2】:

在测试数据库中写入一个 1 字节和 10 GB 的 blob。如果length() 对两个 blob 花费相同的时间,则可能会访问 blob 的长度。否则可能会读取 blob。

或者:下载源代码并通过它进行调试:http://www.sqlite.org/download.html。这些是一些相关的位:

/*
** Implementation of the length() function
*/
static void lengthFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  int len;

  assert( argc==1 );
  UNUSED_PARAMETER(argc);
  switch( sqlite3_value_type(argv[0]) ){
    case SQLITE_BLOB:
    case SQLITE_INTEGER:
    case SQLITE_FLOAT: {
      sqlite3_result_int(context, sqlite3_value_bytes(argv[0]));
      break;
    }
    case SQLITE_TEXT: {
      const unsigned char *z = sqlite3_value_text(argv[0]);
      if( z==0 ) return;
      len = 0;
      while( *z ){
        len++;
        SQLITE_SKIP_UTF8(z);
      }
      sqlite3_result_int(context, len);
      break;
    }
    default: {
      sqlite3_result_null(context);
      break;
    }
  }
}

然后

/*
** Return the number of bytes in the sqlite3_value object assuming
** that it uses the encoding "enc"
*/
SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){
  Mem *p = (Mem*)pVal;
  if( (p->flags & MEM_Blob)!=0 || sqlite3ValueText(pVal, enc) ){
    if( p->flags & MEM_Zero ){
      return p->n + p->u.nZero;
    }else{
      return p->n;
    }
  }
  return 0;
}

您可以看到文本数据的长度是动态计算的。 Blob 的意思...好吧,我的 C 语言不够流利... :-)

【讨论】:

  • 呵呵,是的,我总是可以阅读代码,但是我不确定为什么我会费心提出关于 SO 的问题......如果做得好,OTOH 性能测试可以提供有用的信息,但是不是很确定:换句话说,我希望对 sqlite BLOB 有专门知识的人可以启发我(和社区)这方面的知识。
  • 我想我自己的 C 语言不够流利,但您能否解释一下您如何能够得出结论,BLOB 的长度是根据您发布的代码动态计算的?
  • 我得出的结论是,文本数据(不是 blob 数据)长度是动态计算的。因为循环遍历case SQLITE_TEXT: 中的所有字符。在C 中,字符串以零结尾,因此while 将在达到零时中止。对于 blob,我怀疑 p->n 只被访问一次,没有加载整个 blob,但这可能不正确。
  • SQLITE_BLOB 调用第二种方法(我省略了通过sqlite3_value_bytes 的间接调用,而后者又调用了sqlite3ValueBytes
  • 是的,对于 SQLITE_TEXT,字符串上有一个循环,现在使用 SQLITE_BLOB(以及其他数字类型)调用 sqlite3_value_bytes,我假设最终调用 sqlite3ValueBytes,但话又说回来,我不确定这如何转化为阅读整个 BLOB...
【解决方案3】:

如果您有权访问原始 c api,sqlite3_blob_bytes 将为您完成这项工作。如果不是,请提供更多信息。

【讨论】:

    猜你喜欢
    • 2011-01-14
    • 2021-01-14
    • 2020-06-14
    • 2013-04-03
    • 2012-03-01
    • 2017-09-17
    • 1970-01-01
    • 1970-01-01
    • 2015-09-16
    相关资源
    最近更新 更多