第一范式:数据库表中的每一列是最小的数据项,不可分割。
第二范式:非主属性完全依赖于主属性
第三范式:不光非主属性完全依赖于主属性,并且非主属性之间也不能有依赖关系,即每个非主属性都是独立存在的。
注:主属性就是主键,主键可能由多个字段组成;候选码跟主键一样都是能标识一个元组,只不过候选码是一个集合而主键只有一个,因此我认为候选码包含主键。
如果使用的引擎是myisam,则此时id是8;如果使用的存储引擎是innodb,则此时的id为6。
innodb的最大自增id是存储在内存中的,数据库重启后最大id就会丢失。
cmd命令行:mysql -V
数据库客户端:select version();
原子性、一致性、隔离性、永久性。
原子性:事务要么全部完成,要么失败,不会再中途中完成。
一致性:事务对数据的修改都完全满足数据库的约束条件。
隔离性:数据库允许多个事务并发访问数据库中的数据;隔离性可以防止多个事务并发执行时导致数据不一致;隔离性有四个级别:读未提交,读已提交,可重复读,序列化。
永久性:事务一旦完成,则对数据库中数据的修改是永久性的。
char的大小固定,但是效率较高;varchar的大小可以改变,节省内存空间,但是它的效率要低一些。
float可以存储8位10进制数据,在内存中占用4个字节;double是可以存储16位的十进制数据,在内存中占用8个字节。
内连接:显示两表中满足条件的数据;
左连接:显示左表中全部的数据,以及右表中满足条件的数据;
右连接:显示右表中全部的数据,以及左表中满足条件的数据。
注:那些不满足条件的字段,你查询出来是null值,也是可以查询的。
索引是满足某种查找算法的数据结构,这些数据结构以某种方式指向数据,因此提高了数据的查询效率。
mysql的索引一般都是b+树实现的。
可以用explain查看SQL执行查询的过程,以此来分析索引是否满足需求。
读未提交、读已提交、可重复读、序列化
读未提交:一个事务可以读取另一个事务为提价的数据。可能会出现脏读、幻读和不可重复读。
读已提交:一个事务只有被提交后才能被另一个事务读到。可能会出现幻读和可重复读。
可重复读:在一个事务中,可以重读读取某个数据所得的结果都是一致的。可能会出现幻读。
序列化:代价最高的隔离界别,可以防止脏读、幻读和不可重复读。
脏读:一个事务可以读取另一个事务未提交的数据。
不可重复读:在同一个事务中,前后两次读取同一数据得到的结果不一样。如事务a读取了某个数据后,事务b修改了这个数据,那么事务a再次读这个数据得到的数据就跟第一次读的不一样了。
幻读:比如有事务a修改成功了某个数据,接着事务b将这个数据还原了,等事务a再去查看修改结果的时候发现自己没有修改成功,就像是发生了幻觉一样。
innodb:事务、外键、行级锁,如果对数据的操作以更新、删除为主,查询和插入较少的并且对事务的完整性和并发性要求较高的话,推荐使用innodb。
myisam:全文索引表级锁,如果对数据库数据操作以查看和插入为主,更新和删除较少并且对事务的完整性和并发性要求不高的话,推荐使用myisam引擎。
myisam支持表锁、innodb支持行锁和表锁。
表锁:开销小,加锁快,不会出现死锁。锁的力度大,发生锁冲突的概率最高,并发量最低。
行锁:开销大,加锁慢,会出现死锁。锁的力度小,发生锁冲突的概率最小,并发量高。
乐观锁:每次拿数据的时候都会认为别人不回去修改数据,因此不会上锁,只有在提交更新的时候才会去判断一下这期间别人有没有修改数据。
悲观锁:每次拿数据的时候都认为别人会修改数据,因此会上锁,别人因此访问不到数据,直到锁被释放。
乐观锁需要自己去实现,可以在表中增加一个version字段,每次修改数据成功后,version的值就会+1,等到自己提交数据的时候拿着自己的version和数据集中表的version去对比,如果一致则修改,不一致则放弃。
可以使用explain来查询sql语句的执行计划;开启慢查询日志。
为查询的字段创建索引;避免使用select*;选择正确的存储引擎。
下午我会将实现索引用到的数据结构补充上,还有二级索引和聚合索引。主要是二叉树、平衡二叉树、红黑树、b树和b+树。
b树:树的度(高度)是几,则每个节点存储的元素个数是度的个数-1,当每个节点存储的元素满了以后中间元素就会向上分裂。元素存储在每个节点里。
b+树(mysql):非叶子节点不存储元素,叶子节点存储元素;同样是达到了每个叶子节点的存储个数后中间元素向上裂变,但是中间元素还会留在叶子节点中一份;叶子节点最终形成一个双向链表。
补:如何解决不可重复读(mvcc)?
mvcc多版本并发控制,用于处理读写冲突,提高数据库在高并发场景下的吞吐性能。
mvcc只在读已提交和可重复读两个隔离级别下工作。
mysql的innodb引擎的默认隔离级别,是通过行级锁+mvcc实现的,正常读不加锁,写的时候再加锁。
mvcc的实现依赖是隐藏字段、read view、undo log。
补:innodb引擎为什么要使用b+树来实现呢?
相对于二叉树,层级更少,查询效率更高。
相对于b树,b树是叶子节点和非叶子节点都会存储元素,这会到这每一页中存储的指针或key(指针入量比key的个数永远多一个)数量变少,如果数据量过大的话,会导致树的层级过高,影响查询效率;而b+树非叶子节点只存储指针或key,叶子节点用来存储元素,大大降低了树的层级,增加了查询效率。
相对于哈希索引,b+树索引的非叶子节点是双向链表支持范围查询和排序,而哈希索引是精确查找,不支持范围查询且存储的元素是无序的。
补:说一说索引的分类?
mysql的索引有四个:主键索引、唯一索引、常规索引、全文索引。
在innodb引擎中索引有两个:聚集索引和二级索引。
还有单列索引和联合索引,你懂得。
聚集索引一般是主键索引,非叶子节点中存的是主键而叶子节点中存的是主键所在的这一样的行信息;
二级索引,一般是为某个字段创建的索引,叶子节点中存储的是这个字段所有的值,非叶子节点存储的是字段的id。
查询的时候如果有二级索引,先走二级索引然后再走聚集索引,这种情况叫做回表查询,如果直接查询主键的话走聚集索引就不会出现回表查询了,因此效率更高。
聚集索引一定会有的,而二级索引需要自己去创建,聚集索引一般是以主键作为索引,如果整张表没有主键则用唯一索引作为聚集索引,如果也没有唯一索引,那么就用用rowid作为聚集索引。
补:说一说索引什么情况下会失效?
一般是索引关联了多个多个字段。
不满足最左前缀法则;索引中有范围查询;索引中有列运算;索引中的字符串不加引号;索引中有模糊查询;索引中有or连接条件;全文索引比走自定义索引快。
最左前缀法则:索引中关联的字段,最左边的字段一定存在,不然会出现索引失效或者部分失效;
范围查询:索引中如果某个字段用了范围查询,则此字段右边的索引失效;
模糊查询:索引中如果有某个字段进行了模糊查询,aaa%索引不会失效,而%aaa索引会失效;
or连接条件:如果查询条件中用or连接了,那么只有or两端的字段都有索引时索引才会生效;
全文索引:就是一行一行的去判断是否满足条件;
可以用explain对索引进行性能分析。
补:什么是覆盖索引和回表查询?
覆盖索引就是查询的字段尽量出现是索引中的字段(索引中的字段+id可以在二级索引查询的时候查询到),如果没有可以为查询的字段创建一个联合索引,这样就避免了会表查询;
回表查询就是走索引(二级索引)没有查全自己想要的,还需要走联合索引,因此这种情况就叫回表查询,会降低查询效率。
补:什么是前缀索引和前缀树?
前缀索引是为了缩减索引的长度,减少索引所占的空间,增加查询效率。
前缀树是基于前缀索引构建的属性结构,前缀树的非叶子节点存储的是某个索引字段的一部分前缀,叶子节点存储的是索引字段的前缀和id;