数据库
索引及B树和B+树的区别(多路平衡搜索树):
索引是一种帮助数据库管理系统(innodb引擎为B+树,也可修改为hash索引)高效获取数据的排好序的数据结构,比较常用的是B+树。一个完整的索引数据通常包含两部分:排序的值和对应的数据。索引可以将无序内容转换为有序的一个集合(相对)
.Hash索引和B+树索引区别是什么?
· B+树可以进行范围查询,Hash索引不能。
· B+树支持联合索引,Hash索引不支持。
· B+树支持order by排序,Hash索引不支持。
· Hash索引在等值查询上比B+树效率更高。 (hash类似hash表查询,O(1),B树类似二分查询,O(log2 n))
· B+树支持like进行模糊查询的时候,Hash索引根本无法进行模糊查询。
表中是否有索引:
show index from `表名`; |
或
1 | show keys from `表名`; |
然后看结果中的key_name是否包含你创建的索引名
查询是否使用了索引:sql语句前加个explain
聚集索引(主键索引):数据行的物理顺序与列值(一般是主键的那一列)的逻辑顺序相同,一个表中只能拥有一个聚集索引。
create table t1( id int primary key, name nvarchar(255) )
非聚集索引:该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以拥有多个非聚集索引
普通索引:就是给普通字段加上索引。
CREATE INDEX INDEX_USER_AGE ON `user`(age);
复合索引:就是好几个字段组成的索引,称为联合索引。遵循“最左匹配”,没有最左边的索引值,就没办法使用这个索引。在MySQL建立联合索引时会遵守最左前缀匹配原则,即最左优先,在检索数据时从联合索引的最左边开始匹配,顺序不对时引擎会自动优化为匹配联合索引的顺序,这样是能够命中索引的。可以说创建的idx_abc(a,b,c)索引,相当于创建了(a)、(a,b)(a,b,c)三个索引。由于构建一棵B+树只能根据一个值来确定索引关系,所以数据库依赖联合索引最左的字段来构建
唯一索引(CREATE UNIQUE INDEX):类似主键索引,都是值不能相同,但允许空
B:属于多叉树又名平衡多路查找树 一种在节点存储多条索引元素以及附带数据的树形结构,B树是专门为外部存储器设计的,如磁盘,它对于读取和写入大块数据有良好的性能,所以一般被用在文件系统及数据库中。
- 关键字集合分布在整颗树中;
- 任何一个关键字出现且只出现在一个结点中;
- 搜索有可能在非叶子结点结束;
- 其搜索性能等价于在关键字全集内做一次二分查找;
B+:,B树的变种,中间结点(非叶节点)只存索引,不存数据,且非叶结点中仅含其子树中的最大(或最小)关键字,所以关键字会重复出现;在叶子节点存储了所有索引元素和附带数据,且含有双向指针;b+树的中间节点不保存数据,所以磁盘页能容纳更多节点元素,更“矮胖”;查询性能更稳定,磁盘读写代价更低
Mysql如何为表字段添加索引???
1.添加PRIMARY KEY(主键索引)
ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` )
2.添加UNIQUE(唯一索引)
ALTER TABLE `table_name` ADD UNIQUE ( `column` )
3.添加INDEX(普通索引)
ALTER TABLE `table_name` ADD INDEX index_name ( `column` )
4.添加FULLTEXT(全文索引)
ALTER TABLE `table_name` ADD FULLTEXT ( `column`)
5.添加多列索引
ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )
数据库事务(MyISAM不支持事务和hash索引,而InnoDB支持)
1.数据库事务可以包含一个或多个数据库操作,但这些操作构成一个逻辑上的整体。事务具有原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)四个特性,简称 ACID,
2.原子性:构成逻辑整体的这些数据库操作,要么全部执行成功,要么全部不执行。
MySQL通过undo log来保证原子性;
比如,要修改A的值,那么在修改之前先读取A的原值,将A的原值写入undo log中,然后再修改A的值,再将undo log写入磁盘,然后将A的新值写入磁盘,事务提交;
如果在事务执行过程中意外宕机,那么就会读取undo log,将这个还没执行完的事务回滚;
3.一致性:构成事务的所有操作,要么全都对数据库产生影响,要么全都不产生影响,即不管事务是否执行成功,数据库总能保持一致性状态。数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。例如对银行转帐事务,不管事务成功还是失败,应该保证事务结束后ACCOUNTS表中Tom和Jack的存款和不变。AID保证C的达成。
隔离性:一个事务的执行不能被其他事务干扰。即一个事物内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事物之间不能互相干扰
持久性:指一个事物一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响
如果在事务在执行过程中宕机了,那么直接用undo log回滚;如果事务已经提交了,那么用redo log重做,保证了原子性和持久性;
事务会导致死锁,死锁解决:一是超时回滚,二是采用死锁检测机制(wait-for graph等待图)
脏写是指事务回滚了其他事务对数据项的已提交修改。
丢失更新是指事务覆盖了其他事务对数据的已提交修改,导致这些修改好像丢失了一样。
脏读是指一个事务读取了另一个事务未提交的数据
不可重复读是指一个事务对同一数据的读取结果前后不一致。脏读和不可重复读的区别在于:前者读取的是事务未提交的脏数据,后者读取的是事务已经提交的数据,只不过因为数据被其他事务修改过导致前后两次读取的结果不一样
幻读是指事务读取某个范围的数据时,因为其他事务的操作导致前后两次读取的结果不一致。幻读和不可重复读的区别在于,不可重复读是针对确定的某一行数据而言,而幻读是针对不确定的多行数据
什么是幻读,脏读,不可重复读?
事务A、B交替执行,事务A被事务B干扰到了,因为事务A读取到事务B未提交的数据,这就是脏读。
在一个事务范围内,两个相同的查询,读取同一条记录,却返回了不同的数据,这就是不可重复读。
事务A查询一个范围的结果集,另一个并发事务B往这个范围中插入/删除了数据,并静悄悄地提交,然后事务A再次查询相同的范围,两次读取得到的结果集不一样了,这就是幻读。
SQL标准为事务定义了不同的隔离级别,从低到高依次是
- 读未提交(READ UNCOMMITTED)
- 读已提交(READ COMMITTED)
- 可重复读(REPEATABLE READ)
- 串行化(SERIALIZABLE)
事务的隔离级别越低,可能出现的并发异常越多,但是通常而言系统能提供的并发能力越强。
隔离的原理:通过MVCC多版本并发控制机制(读已提交和可重复读使用,变种行级锁)和锁(行级锁(有索引才能用)、表级锁(不会死锁)、页级锁)实现,Mysql的当前读和快照读,通过保存数据在某个时间点的快照来实现的。为什么叫当前读?就是它读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。快照读读取的是快照版本,也就是历史版本,像不加锁的SELECT操作就是快照读
MVCC的锁:乐观锁(提交更新的时候,才会正式对数据的冲突与否进行检测),悲观锁(当其他线程想要访问数据时,都需要阻塞挂起):共享锁和排它锁。
左(外)连接、右(外)连接、内连接等等
左连接:SELECT * FORM a Left Join b on a.id =b.id
以左表为基础,根据ON后给出的两表的条件将两表连接起来。结果会将左表所有的查询信息列出,而右表只列出ON后条件与左表满足的部分,
反之为右连接。
内连接展示效果和where相同。
Where由于要先把两张表(笛卡尔积,n*m条记录)都加载到内存中创建一个临时表,所以比较占用资源。Join 会先判断数据行是否符合ON语句后面的条件,再决定是否JOIN,不创建临时表。
数据库主键,指的是一个列或多列的组合,其值能唯一地标识表中的每一行,通过它可强制表的实体完整性。主键主要是用与其他表的外键关联,以及文本记录的修改与删除。
范式
第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值。
第二范式在第一范式的基础之上更进一层。第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。
第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关
SQL
增:
INSERT INTO student VALUES( '张三', '女',1990,'中文系', '湖南省永州市');
删:
DELETE FROM students where name=’张三‘;
drop主要用于删除数据结构
truncate(立即生效,删除内容、释放空间,不主动记录日志,但事务中可以回滚. )和 delete(删除内容不删除定义,不释放空间,作为事务记录在日志中,可以回滚 )只删除数据不删除表的结构,delete之后设置为自动增长的Id不会从0开始,而truncate可以
速度 drop> truncate > delete tudent; //删除S
改:
UPDATE student SET sex=’女’ where name=’张思’;
查:
- ORDER BY asc 升序, ORDER By desc
SELECT * FROM student LIMIT 1,3; //(2到4行)
SELECT AVG(score) FROM student; //平均成绩
SELECT * FROM sc ORDER BY score DESC LIMIT 3; // 成绩前三名
SELECT name FROM sc WHERE score in(SELECT max(score) FROM sc) //高分
SELECT COUNT(id) FROM sc WHERE sex = '男' //男数量
索引:CREATE UNIQUE INDEX index_age ON student(id); //用Id作为唯一索引
创建表:
create table person(
id int primary key, //id为主键
name varchar(16) not null, //name不为空
age int,
phone varchar(11), );
1.聚集索引与非聚集索引的区别
(1)一个表中只能拥有一个聚集索引,而非聚集索引一个表可以存在多个。
(2)聚集索引,索引中键值的逻辑顺序决定了表中相应行的物理顺序;非聚集索引,索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同。
(3)索引是通过二叉树的数据结构来描述的,我们可以这么理解聚簇索引:索引的叶节点就是数据节点。而非聚簇索引的叶节点仍然是索引节点,只不过有一个指针指向对应的数据块。
(4)聚集索引:物理存储按照索引排序;非聚集索引:物理存储不按照索引排序;
2.为什么要用B+树,为什么不用普通二叉树?
可以从几个维度去看这个问题,查询是否够快,效率是否稳定,存储数据多少,以及查找磁盘次数,为什么不是普通二叉树,为什么不是平衡二叉树,为什么不是B树,而偏偏是B+树呢?
(1)为什么不是普通二叉树?
如果二叉树特殊化为一个链表,相当于全表扫描。平衡二叉树相比于二叉查找树来说,查找效率更稳定,总体的查找速度也更快。
(2)为什么不是平衡二叉树?
我们知道,在内存比在磁盘的数据,查询效率快得多。如果树这种数据结构作为索引,那我们每查找一次数据就需要从磁盘中读取一个节点,也就是我们说的一个磁盘块,但是平衡二叉树可是每个节点只存储一个键值和数据的,如果是B树,可以存储更多的节点数据,树的高度也会降低,因此读取磁盘的次数就降下来啦,查询效率就快啦。
(3)为什么不是B树而是B+树?
B+树非叶子节点上是不存储数据的,仅存储键值,而B树节点中不仅存储键值,也会存储数据。innodb中页的默认大小是16KB,如果不存储数据,那么就会存储更多的键值,相应的树的阶数(节点的子节点树)就会更大,树就会更矮更胖,如此一来我们查找数据进行磁盘的IO次数有会再次减少,数据查询的效率也会更快。
B+树索引的所有数据均存储在叶子节点,而且数据是按照顺序排列的,链表连着的。那么B+树使得范围查找,排序查找,分组查找以及去重查找变得异常简单。
4.什么是最左前缀原则?什么是最左匹配原则?
最左前缀原则,就是最左优先,在创建多列索引时,要根据业务需求,where子句中使用最频繁的一列放在最左边。
当我们创建一个组合索引的时候,如(a1,a2,a3),相当于创建了(a1)、(a1,a2)和(a1,a2,a3)三个索引,这就是最左匹配原则。
5.索引不适合哪些场景?
· 数据量少的不适合加索引
· 更新比较频繁的也不适合加索引=区分度低的字段不适合加索引(如性别)
6.索引有哪些优缺点?
(1)优点:
· 索引可以加快数据查询速度,减少查询时间
(2)缺点:
· 创建索引和维护索引要耗费时间
· 索引需要占物理空间,除了数据表占用数据空间之外,每一个索引还要占用一定的物理空间
· 以表中的数据进行增、删、改的时候,索引也要动态的维护
数据库优化:
- 索引
- 选择合适的数据库引擎,Myisam读性能高,但不支持事务,不支持hash索引
- 连接join(多表查询)代替子查询(where)
- delete\truncerte,truncate速度快