MySQL 记录、页、索引的数据结构简析( 二 )

其中:

  • block->buf_page_t , 数据页控制块指针,要求是 buf_block_t 的第一个成员,便于 buf_block_t 随时强制类型转换为 buf_page_t;
  • block->frame,数据页指针,指向页对应在缓冲池中的内存地址,保存页的真实内容;
  • block->lock,读写锁用于保护 page 的内容 。
buf_page_t 称为数据页控制体 。
/** The common buffer control block structurefor compressed and uncompressed frames */class buf_page_t {public:page_id_t id; // page idbuf_page_t* hash;/*!< node used in chAIning tobuf_pool->page_hash orbuf_pool->zip_hash */lsn_tnewest_modification; // 当前Page最新修改lsnlsn_toldest_modification; // 当前Page最老修改lsn,即第一条修改lsn};其中:
  • oldest_modification,最初修改该页 redo log record 的 end LSN(或者是 mtr end LSN),oldest_modification 不为 0 表示是脏页;
  • newest_modification,最近修改该页 redo log record 的 end LSN(或者是 mtr end LSN) 。
索引概念索引是基于以空间换时间的思想用于加速查询的数据结构 。
InnoDB 中索引基于 B+ 树实现,因此每个索引都是一棵 B+ 树 。索引用于组织页,页用于组织行记录 。
数据结构每个 B+ 树索引在内存中对应数据结构 dict_index_t 。
/** Data structure for an index.Most fields will beinitialized to 0, NULL or FALSE in dict_mem_index_create(). */struct dict_index_t{ index_id_t id; /*!< id of the index */ mem_heap_t* heap; /*!< memory heap */ id_name_t name; /*!< index name */ const char* table_name;/*!< table name */ dict_table_t* table; /*!< back pointer to table */unsigned space:32;/*!< space where the index tree is placed */ unsigned page:32;/*!< index tree root page number */unsigned allow_duplicates:1;/*!< if true, allow duplicate valueseven if index is created with uniqueconstraint */unsigned n_uniq:10;/*!< number of fields from the beginningwhich are enough to determine an indexentry uniquely */ unsigned n_def:10;/*!< number of fields defined so far */ unsigned n_fields:10;/*!< number of fields in the index */ unsigned n_nullable:10;/*!< number of nullable fields */dict_field_t* fields; /*!< array of field descriptions */};其中:
  • index->table,指向当前索引对应的表;
  • index->n_fields,表示当前索引中包含的列数;
  • index->page,表示当前索引 root 页的编号(偏移量);
  • index->fields,表示当前索引列的描述信息 。
通过 B+ 树索引进行查找(lookup)是最为常见的操作,具体通过游标实现 。
游标概念游标是一个逻辑概念,无论是写入还是查询,都需要在 B+ 树上遍历至某个位置,具体到某个 block 上的某个 record 。
InnoDB 中通过 cursor search 实现 B+ 树的查找,每个 open 一个 cursor 都会开启一个从 B+ 树 root 结点搜索到指定层级的 record 的搜索过程 。
cursor 分为以下两种:
  • B-tree cursor
  • page cursor,表示指向记录所在位置的游标 。
 
page cursor 在定位(lookup)到记录后,再通过查询模式(search mode)再进行向前或向后的记录扫描(scan) 。
比如对于一个主键的范围查询,首先需要定位第一条记录 , 然后进行记录的顺序扫描 。
InnoDB 中定义了四种查询模式:
  • PAGE_CUR_G: > 查询 , 查询第一个大于 dtuple 的 rec_t
  • PAGE_CUR_GE: >=,> 查询,查询第一个大于等于 dtuple 的 rec_t
  • PAGE_CUR_L: < 查询,查询最后一个小于 dtuple 的 rec_t
  • PAGE_CUR_LE: <= 查询,查询最后一个小于等于 dtuple 的 rec_t
插入操作的 search_mode 默认是 PAGE_CUR_LE,即插在最后一个小于等于该 dtuple 的 rec_t 后 。
 
为了提高查询效率,InnoDB 做了以下优化: