1.1数据库架构:
如何设计一个关系型数据库?
存储模块(文件系统)用块或者页作为存储单位
程序实例:
存储管理
缓存机制 不宜过大,要有淘汰机制
SQL解析
日志管理
权限划分
容灾机制
索引管理
锁管理
1.2 索引
为什么要使用索引?
全表扫描:
数据库存储用块或者页存储,全表扫描时,需要将整个表加载到缓存中,当数据量很小的时候,缓存可以一次加载所有数据量,全表扫描就会比较快,而当数据量很大需要缓存多次加载,就会很慢,这个时候就要用到索引。
索引来源于字典,将关键信息集中起来,快速查找数据
因为索引能够避免全表扫描查找数据,提升检索效率
什么样的信息能成为索引?
能把该记录限定在一定查找范围中的字段
主键,唯一键以及普通键 能够让数据具备一定区分度的字段
索引的数据结构?
主流是B+Tree,还有Hash结构 bitMap索引,其中MySql不支持BitMap索引,同时基于MyISAM 或 InnoDB的MySql不支持Hash
二叉查找树:
有左右子树,对于树中的节点值X 他的左子树的任意节点值小于X,右字数任意节点值大于X,时间复杂度O(logn)
但在插入过程中可能会产生以下问题 导致IO次数变多时间复杂度变为O(n),比全表扫描都要慢得多
B-Tree (通过合并上移下移来保证特征)
特征:
根节点至少包括两个孩子
树中每个节点最多含有M个孩子(m>=2)
除根节点和叶节点外,其他每个节点至少有ceil(m/2)个孩子
所有终端叶子节点都位于同一层(即叶子节点高度一致)
假设每个非终端结点中包含N个关键字信息,其中1)Ki(i=1...n)为关键字,且关键字按顺序升序排序K(i-1) B+-Tree (B-Tree 的变体) 非叶子节点的子树指针与关键字个数相同 非叶子节点得子树指针P[I],指向关键字【K[i],K[i+1]】的子树 非叶子节点仅用来做索引,数据保存在叶子节点中,即非叶子节点值和叶子节点值可能相同(保证树更矮) 所有叶子节点均有一个链指针指向下一个叶子节点并按大小顺序链接(可以方便横向跨子树进行统计,比如n>10 会直接统计10以后的叶子节点而不统计10以前的) 结论: B+Tree更适合用于做存储索引 1)B+树的磁盘读写代价更低,B+树的内部结构没有存储指向关键字具体信息的指针,所容纳的关键字多,一次IO可读取关键字数量更多。 2)B+树的查询效率更加稳定,由于非终端点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。 3)B+树更有利于数据库的扫描,只需要遍历节点就可以完成对整个数据库数据的扫描查找 Hash索引(理论上高于B+Tree):不稳定不支持线性查询 存放通过HASH算法计算出来的Hash值和行指针 优点 根据Hash的运算可以一次查找到数据所在的链表 缺点 仅仅能满足“=”,“in”,不能使用范围查询 无法被用来避免数据的排序操作 (HASH索引比较的是Hash算法计算后的值,不能保证和原有顺序(大小)一致) 组合索引中Hash是用组合全部索引值的方式进行查找的,无法通过组合索引中的部分索引键进行查询 无法避免表扫描,不同索引键可能存在相同索引值,需要通过访问实际数据进行比较 遇到大量Hash值相等的情况后,性能并不一定就会比B-Tree索引高(有可能出现极端情况,即很多不同数据计算出的索引值都一样变成线性存储结构) BitMap(位图)索引: 存储时按照状态分开,每个数据是否是这个值,按位存储 只适用于某个字段的值只有某种几个的情况 锁力度较大,不适合高并发联机系统,适用于并发低但是统计多的。 密集索引和稀疏索引的区别: 密集索引文件中的每个搜索码值都对应一个索引值,叶子节点不仅仅保存键值 并且保存了位于同一行记录里的其他列的信息,由于密集索引决定了一个表的物理排序,一个表只能有一个物理排列顺序故只能创建一个密集索引 稀疏索引文件只为索引码的某些值建立索引项,叶子节点仅保存键位信息和该行指针地址(或主键)定位到叶子后通过地址或主键寻找 存储引擎: MyISAM 索引和数据是分开存储的 (更适合大量的查询操作) InnoDB 索引和数据是一起存储的 (支持事务 支持行级锁 set update更快) 有且仅有一个密集索引 如果一个主键被定义,该主键作为密集索引 如果没有主键被定义,该表的第一个唯一非空索引作为密集索引 若不满足以上条件,innodb会在内部生成一个隐藏主键 非主键索引存储箱关键为何其对应的主键值,两次查找(查找次级索引自身,再查找主键索引或者物理索引索引) 如何定位并优化慢SQL? 该题目比较看经验 1)根据慢日志定位慢查询SQL(数据定义语言不会进入慢查询 慢日志:记录执行比较慢的SQL 执行命令:Show variables like‘ %quer%’ 从上到下分别是: SQL执行时间即超过多少时间算执行较慢,会记录超过这个时间的慢查询 慢日志开关:set global slow_query_log= on; 慢日志路径:set global long_query_time=1;(此句变量需要重连数据库后才生效) 使用命令修改后再重启数据库服务后会回复默认,可以在配置文件中修改 2)使用explain等工具分析sql: 显示了mysql如何使用索引来处理select语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句 type:mysql找到数据行的方式 最优—>最差(红字需要优化) extra:中出现以下两项表示mysql没有使用索引 3+)修改sql(减少使用*,减少使用模糊查询)或者使SQL尽量走索引(like‘%赵%’这种形式不会走索引,但是like‘赵%会走索引’、强制索引等) mysql的查询优化器会尽可能的使用索引并且使用最严格的索引消除尽可能多的数据行,最终目标是提交SQL语句查询数据行而不是排除数据行,sql优化器试图排除语句的目的在于排除数据行的素的越快,找到与条件匹配的数据行就越快,sql优化器会判断密集索引的叶子结点会带有数据,效率可能会低,故选择稀疏索引(有时候不一定会最优)。 联合索引的最左匹配原则的成因? 最左匹配原则:对于索引(A,B),有where A=1会走该索引,where A=1and B=1也会走该索引,where B=1则不会走该索引; mysql会一直向右匹配直到遇到范围查询(<,>,between,like)就停止匹配,比如a=3 and b=2 and c>5 and d=6,如果建立(abcd)顺序的索引,d是用不到索引的,如果建立(abdc)顺序的索引,abdc的索引都可以用到,abd 的顺序可以任意调整;=和in可以乱序,比如a=1 and b=2 and c=3 建立(abc)索引可以任意顺序,musql的查询优化器会帮你优化成索引可以识别的形式。 mysql创建联合索引会对复合索引的第一个索引字段排序在此基础上再对第二个字段排序,其中第一个字段是有序的,第二个字段是无序的、所以用第一个字段是可以用到索引的,单独用第二个字段是用不到索引的 从col3,col2,col1做索引会做出下图所示的索引,单使用col2无法走索引。 索引是建立的越多越好吗? 1)否定的,物极必反,数据量小的表不需要建立索引,建立会增加额外的索引开销 2)数据变更需要维护索引,更多的索引意味着更多的维护成本 3)更多的索引意味着需要更多的空间。