iMySQL(一)

1 如何在数据库中存储层级结构


(1) 邻接表模型


  • 求节点的路径
    举例来说,“Cherry”所在的路径为Food > Fruit > Red > Cherry。在这里,我们可以从Cherry开始查起,然后递归查询查询节点前的节点,直到某节点的父节点ID为0(Food)。

  • 优点
    简单易懂

  • 缺点
    执行起来效率低下。我们对于每个结果,期望只需要一次查询;可是当使用邻接表模型时嵌套的递归使用了多次查询,当树很大的时候,这种慢就会表现得尤为明显。

上帝是公平的,当在执行时效率低下,意味着可以增加预处理的程度。

(2)MPTT(修改过的前序遍历算法)

  • 原理
    现在我们把树“横”着放。如下图所示,我们首先从根节点(“Food”)开始,先在它左侧标记“1”,然后我们到“Fruit”,左侧标记“2”,接着按照前序遍历的顺序遍历完树,依次在每个节点的左右侧标记数字。
  • 实现
  • 打印树
    如果要想打印树,你只需要知道你要检索的节点。比如,想要打印“Fruit”的子树,可以查询左数大于2而小于11的节点。
SELECT * FROM tree WHERE lft BETWEEN 2 AND 11;
  • 求节点的路径
    对于某节点,我们只需求出左数值小于其左数值、右数大于其右数的所有节点。比如说“Cherry”这个节点(4-5)
SELECT title FROM tree WHERE lft < 4 AND rgt > 5 ORDER BY lft ASC;
  • 增加节点
    我们想添加“Strawberry“到”Red“节点下,那么“Red”节点的右数就得从6到8,而“Yellow”就得从7-10变成9-12,以此类推。更新Red节点就意味着大于5的左数和右数都要增加2。
UPDATE tree SET rgt=rgt+2 WHERE rgt>5;
UPDATE tree SET lft=lft+2 WHERE lft>5;

INSERT INTO tree SET lft=6, rgt=7, title='Strawberry';
  • 优点
    查询的时候只需要一条SQL语句

2 进入正题

  • Mysql架构
    • Parser
      将用户的查询语句进行解析,并创建一个内部的数据结构——分析树
    • Optimizer
      各种优化,例如重写查询、选择读取表的顺序,以及使用哪个索引等。
  • 类目表结构(是否可以改进?)
CREATE TABLE `itemcats` (
  `cid` int(11) NOT NULL,
  `parent_cid` int(11) DEFAULT NULL,
  `name` varchar(50) NOT NULL,
  `is_parent` tinyint(1) NOT NULL,
  `status` varchar(20) DEFAULT NULL,
  `sort_order` int(11) DEFAULT NULL,
  `lft` int(11) NOT NULL,
  `rght` int(11) NOT NULL,
  `level` int(11) NOT NULL,
  PRIMARY KEY (`cid`),
  KEY `parent_cid` (`parent_cid`),
  KEY `lft_rght` (`lft`,`rght`),
  KEY `level` (`level`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • 为什么InnoDB表要建议用自增列做主键?
    如果InnoDB表的数据写入顺序能和B+树索引的叶子节点顺序一致的话,这时候存取效率是最高的
    • 使用自增列(INT/BIGINT类型)做主键,这时候写入顺序是自增的,和B+数叶子节点分裂顺序一致;
    • 如果一个InnoDB表又没有显示主键,又有可以被选择为主键的唯一索引,但该唯一索引可能不是递增关系时(例如字符串、UUID、多字段联合唯一索引的情况),该表的存取效率就会比较差。
  • 数值类型
  • 字符串类型
    • char(n)和varchar(n)中括号中n代表字符的个数,并不代表字节个数,所以当使用了中文的时候(UTF8)意味着可以插入m个中文,但是实际会占用m*3个字节。
    • 同时char和varchar最大的区别就在于char不管实际value都会占用n个字符的空间,而varchar只会占用实际字符应该占用的空间+1,并且实际空间+1<=n。
    • 超过char和varchar的n设置后,字符串会被截断。
    • char在存储的时候会截断尾部的空格,varchar和text不会。
    • varchar会使用1-3个字节来存储长度,text不会。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容