主要考察的是索引、锁部分。
如何设计一个关系型数据库(RDBMS)?
1.存储(文件系统),即将数据持久化到硬盘中。2.程序实例模块,对存储进行逻辑上的管理,主要分为八个部分: 索引管理——优化查询效率 锁管理——支持并发 存储管理 ——逻辑关系转换成物理存储关系 缓存机制——优化执行效率 SQL解析——解析SQL语句 日志管理——记录操作 权限划分——进行多用户管理 容灾机制——灾难恢复查询数据方式有两种:
1.全局(表)扫描,将数据分块或分批次加载到内存,逐块进行查询,效率慢适合小规模数据。2.索引查找,能够避免全局扫描,将数据查找限定在一定的范围内,提升查找效率。主键、唯一键以及普通键等,能够使数据具备一定区分性的字段。
生成索引——二叉查找树进行二分查找,树的高度如果很高,在每个判断的树的结点都会进行一次I/O,效率较低。(因此可以在每个子结点存储更多的数据,即B-Tree)。
生成索引——建立B-tree结构进行查找,包含关键字、指向子结点的指针。结点最多能存储的数据取决于每个存储快的容量和数据库的相关配置。目的,尽可能的减少I/O次数。(m表示每个结点包含的孩子数)(前4条限定B-树的孩子树和深度,5条限定B-树的关键字数和大小)(查找效率O(logn)(插入或删除数据,分裂、合并、上升等操作保证下面5条规则)。
1.根结点至少包括两个孩子。 2.树中每个结点最多包含有m个孩子(m>=2)。 3.根结点和叶结点除外,其他每个结点至少有ceil(m/2)个子结点。 4.叶子结点位于同一层。 5.生成索引——建立B+Tree结构进行查找(主要使用,更适合做存储索引)。B±树是B-树的变体,定义基本与B树相同。除了:
1.非叶子结点的子树指针与关键字个数相同。 2.非叶子结点的子树指针P[i],指向关键字值(K[i],K[i+1])的子树。 3.非叶子结点只做索引,这样非叶子结点空间不存储数据,有更多的空间存储索引,数据只存储在叶子结点,搜索只在叶子结点终结。 4.所有叶子结点均有一个链指针指向下一个叶子结点(有序表存储),查找不会返回到叶子结点,而是横向跨子树统计(范围统计)。生成索引—建立Hash结构进行查找。只需一次hash查找就能找到数据所在的buckets,再将该bucket加载到内存,因为bucket里面的数据存储结构为链表,通过指针查找,查找相应数据。
另外,还有BitMap位图索引。
mysql有两种数据的存储格式:InnoDB和MyISAM
例如:若使用where id = 14这样的条件查询主键,按照B+树的查找规则即可查到对应的叶子结点并获得对应的主键和行数据。若对稀疏索引进行主键筛选,需经历两个步骤:在稀疏索引的B+树中检索该键,定位到主键信息,再利用主键信息在主见索引B+树中再次进行检索操作。
2.MyISAM使用的是稀疏索引(包含.frm),主键索引和辅助键索引结构都一样,只是存储的信息不同一个存储的是主键,另一个是辅助键两个索引结构都存储在一个文件中(.MYI),表数据存储在另一个文件中(.MYD)。索引树是独立的,对于表数据而言主键索引和辅助键索都一样。MyISAM结构的数据库中,一个session对某一表进行操作时,会给该表进行加锁,并block其他session对该表的操作。当对数据进行读(select)的时候,会自动加上表级别的读锁;增删改(insert、delete、update)的时候,会自动加上表级别的写锁。当表的读锁未被释放时,想要对表进行写锁,会被阻塞,直到所有的读锁释放。
1.读锁为共享锁,当一个表先上了读锁还能再加读锁,不能上排他锁,故称之为共享锁。2.写锁为排他锁,当一个表先上了写锁就不能对其加读锁(select)或者写锁(insert、delete、update),故称之为排他锁。3.也可以手动改变共享锁为排他锁,即在每个select的后面加上‘for update’。手动加共享锁‘lock in share mode’。4.上述两种锁的情况同样适用于InnoDB。5.MyISAM不支持事务,sql语句执行完成后,会自动释放锁。InnoDB默认是自动提交数据
1.InnoDB默认支持行级锁。
2.InnoDB支持事务,用的是二段锁(加锁和解锁分为两个步骤,先对同一个事务里的一批操作进行加锁,然后commit的时候,再对事务里加上的锁统一进行解锁。当commit自动提交时,看起来和MyISAM差不多)。可以通过sessio获取锁,暂时不自动提交(‘set autocommit = 0’ 关闭当前session的自动提交,只针对当前session)的方式,模拟并发访问的过程。InnoDB对共享锁进行了优化,需要自己显示加锁。
3.MyISAM一旦操作了表的数据,就会默认加表级锁,因此与索引无关。而InnoDB中默认使用的是行级锁,只有sql用到了索引,涉及到的行都会被上共享锁或排他锁。
4.主键id用到的是密集索引,‘index_area_title’是联合索引,‘motto’无索引。以该无索引的字段进行sql操作(注意,该sql中不涉及任何索引,只以motto为操作条件),如果一个session先在A行上共享锁,另一个session在B行上排他锁,还是会被bolck。当不走索引的时候,整张表都会被锁住。即InnoDB在sql没有用到索引的时候,用到的是表级锁。而sql用到索引的时候,用到的是行级锁和gap(部分)锁。
5.InnoDB还支持意向的表级锁,共享读锁(IS)、共享写锁(IX),作用于MyISAM的表级锁类似,在InnoDB中的IS、IX作用是:在表级别操作的时候,不用轮询每一行是否有行锁。
6.行级锁是否一定比表级锁好?不一定,锁的粒度越细,代价越高。表级锁在表的头部直接加锁,而行级锁还要在扫描到某行的时候,对其进行上锁。
7.InnoDB支持事务,比不支持事务的MyISAM的开销更大。
1.按锁的粒度划分,表级锁、行级锁、页级锁
2.按锁级别划分,共享锁、排他锁
3.按锁的方式,自动锁、显示锁
4.按操作划分,DML锁(针对数据)、DDL锁(针对表结构)
5.按使用方式划分,乐观锁、悲观锁
悲观锁:对外界的操作持保守态度,在整个数据的处理过程中,将数据处于锁定状态。悲观锁的实现,基于数据库提供的锁机制。全程用排他锁实现,即悲观锁。悲观并发控制,实际上是先上锁、再访问的保守策略,但是也会有额外的开销、增加产生死锁的概率。在只读的事务中,不会产生数据的冲突,加锁会降低事务的并发性。
乐观锁:认为数据一般情况下不会产生冲突,所以只在数据进行commit的时候才会对数据进行冲突检测。如果发现冲突,返回用户信息由用户决定。实现机制不依靠数据库的锁机制,而是记录数据的版本(版本号、时间戳)。因此不会产生死锁,但是也会产生不可预料的冲突,例如:两个事务都读取数据的某一行,进行版本号的更新,再进行回写,就会产生数据冲突。
REPEATABLE-READ是数据库mysql默认的隔离级别,最高级别是SERIALIZABLE(所以的sql操作都会默认加上锁)。隔离级别越高,虽然越能避免并发的问题,但是会导致串行化严重、并发效率不高。
1.更新丢失——mysql所有事物隔离级别在数据库层面上均可避免这种情况。
2.脏读——READ-COMMITTED事物隔离级别及以上可避免。
脏读:一个事务读取到另一个事务未提交(执行sql操作,但是因为故障,又rollback回滚的情况)的数据。
3.不可重复读——REPEATABLE-READ事物隔离级别以上可避免。
不可重复读:一个事物对数据的多次读取,结果不一致,即读取的数据不可靠。
4.幻读——SERIALIZABLE事物隔离级别可避免。
幻读:一个事务进行sql操作时,影响行的数目变了,因为另一个事务对该表进行了(insert、delete)sq操作。
1.对于单个表,如果用GROUP BY,那么select语句中选出来的列要么是GROUP BY里用到的列,要么就是带有聚合函数的列。(满足select子句中的列名必须为分组列或列函数 )
2.列函数对于GROUP BY子句定义的每个组各返回一个结果。
例子:
select count(course_id), sum(score) from score GROUP BY sid 1.即根据sid对score表进行分组,分组完成之后可以通过count、sum等聚合函数对每个组进行运算。2.GROUP BY会把分组的结果集,缓存到临时表里,再通过统计函数对结果集进行统计并展示。 select s.student_id, stu.name, count(s.course_id),sum(s.score) from score s, student stu where s.student_id = stu.student_id GROUP BY s.student_id 1.对于多表联查,不受规则(满足select子句中的列名必须为分组列或列函数 )限制。例子
select student_id,count(course_id),sum(score) from score GROUP BY student_id; select student_id,avg(score) from score GROUP BY student_id HAVING avg(score)>60 #查询没有学全所有课的同学的学号、姓名 select s.student_id,stu.name from student stu,score s WHERE stu student_id= s.student_id GROUP BY s.student_id HAVING count(*) < (select count(*) from course)最后修改于时间:2020年10月15号
