2021SC@SDUSC SQLite源码分析(四)————sqlite中的cell概念


一、cell是什么?

sqlite数据库文件被分为固定大小的页,所有的页由B+树模块管理。每个页要么是树中的页(内部页或者叶子页),要么是溢出页,或者是自由页(自由页通过单链表组织起来)。
树中的页(内部页和叶子页)被分成许多cell,一个cell包括一个(或者一部分)负载。Cell是已分配或者已释放的磁盘空间集合。页的内容见往期分析。

每个页被分为4个部分:
1.页头
2.Cell指针数组
3.未分配空间
4.Cell内容

struct CellInfo {
   
   
  i64 nKey;      /* The key for INTKEY tables, or nPayload otherwise */
  u8 *pPayload;  /* Pointer to the start of payload */
  u32 nPayload;  /* Bytes of payload */
  u16 nLocal;    /* Amount of payload held locally, not on overflow */
  u16 nSize;     /* Size of the cell content on the main b-tree page */
};

Cell指针数组从上向下增长,cell内容从下向上增长。Cell指针数组作为页内的一种目录,帮助把cell组织起来。
页头只包含本页的管理信息,并且总是存储在页的开头。
Cell被保存在页的最底部,向页开头的方向增长。Cell指针数组从页头之后的第一个byte开始,包含0个或者多个cell指针。每个cell指针是一个2byte整数,该整数指示了实际cell内容相对于页开头的偏移量。Cell指针按照相应的键值排序,尽管cell本身的存储不是按照顺序的。Cell指针数组的大小被存储在页头处偏移量为3的地方。
Cell是变长的字节字符串。一个cell保存了一个负载。Cell的结构如下图所示,size列的单位是byte。

在这里插入图片描述

对应btreeInt.h中注释如下:

** The content of a cell looks like this:
**
**    SIZE    DESCRIPTION
**      4     Page number of the left child. Omitted if leaf flag is set.
**     var    Number of bytes of data. Omitted if the zerodata flag is set.
**     var    Number of bytes of key. Or the key itself if intkey flag is set.
**      *     Payload
**      4     First page of the overflow chain.  Omitted if no overflow
**
** Overflow pages form a linked list.  Each page except the last is completely
** filled with data (pagesize - 4 bytes).  The last page can have as little
** as 1 byte of data.
**
**    SIZE    DESCRIPTION
**      4     Page number of next overflow page
**      *     Data
**
** Freelist pages come in two subtypes: trunk pages and leaf pages.  The
** file header points to the first in a linked list of trunk page.  Each trunk
** page points to multiple leaf pages.  The content of a leaf page is
** unspecified.  A trunk page looks like this:
**
**    SIZE    DESCRIPTION
**      4     Page number of next trunk page
**      4     Number of leaf pointers on this page
**      *     zero or more pages numbers of leaves

对于内部节点,每个cell包含一个4byte的子节点指针;对于叶子节点,cell没有子节点指针。接下来是该cell存储的数据的大小(bytes)和存储的键值的大小(bytes)
(如果页头中的intkey为真,那么存储键值大小的地方就直接存储键值本身的整型值,如果zerodata为真,那么数据部分不存在)。

二、cell与溢出页结构

1.溢出页的意义

SQLite限制了每页中负载的数量。负载有可能不会把自身的全部存储在同一页中,尽管可能该页有足够大的空间。每页能够存储的最大单个负载由该页可用空间(可以被内部节点的单个cell使用)的总大小决定。
如果内部节点中的cell的负载大于最大负载限制,超出的部分就被分割并存储到溢出页链表中。一但分配了一个溢出页,要把尽可能多的字节转移到溢出页中,只要不导致cell的大小低于最小负载限制就行。对于叶子节点,最小负载限制存储在文件头内偏移量23处,但是最大负载限制总是100%,并且不会在文件头给出。

static int getOverflowPage(
  BtShared *pBt,               /* The database file */
  Pgno ovfl,                   /* Current overflow page number */
  MemPage **ppPage,            /* OUT: MemPage handle (may be NULL) */
  Pgno *pPgnoNext              /* OUT: Next overflow page number */
){
   
   
  Pgno next = 0;
  MemPage *pPage = 0;
  int rc = SQLITE_OK;

  assert( sqlite3_mutex_held(pBt->mutex) );
  assert(pPgnoNext);

#ifndef SQLITE_OMIT_AUTOVACUUM
  /* Try to find the next page in the overflow list using the
  ** autovacuum pointer-map pages. Guess that the next page in 
  ** the overflow list is page number (ovfl+1). If that guess turns 
  ** out to be wrong, fall back to loading the data of page 
  ** number ovfl to determine the next page number.
  */
  if( pBt->autoVacuum ){
   
   
    Pgno pgno;
    Pgno iGuess = ovfl+1;
    u8 eType;

    while
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值