数据库三大范式
1、第一范式:确保每列保持原子性
2、第二范式:确保表中每列都与主键列相关
3、第三范式:确保表中每列都与主键列直接相关而不是间接相关
不要一味的去追求符合范式要求,实际项目中,需求 > 性能 > 表结构
索引底层原理
show global status like 'Innodb_page_size';
可以查询到每个节点中,mysql允许的最大大小,默认16kb
索引是帮助mysql高效获取数据的排好序的数据结构
索引的数据结构分为:二叉树 红黑树 hash表 b-tree
其中二叉树 红黑树的数据结构在 java 集合总结篇做过介绍
CSDN
在没有索引的情况下,执行select * from table where id = 1的语句,就会全表扫描,一行一行的匹配,然后对结果进行返回,如果数据量级比较大的情况,就会十分影响效率。
给id字段加了索引之后,在此执行该语句的时候,知道id为索引字段,就会根据索引的数据结构进行查找,比如说,二叉树的查找,红黑树的查找,就会比没有索引的线性查找快很多。当然,这两种数据结构也是有弊端的,比如说二叉树不够平衡,所以出现了红黑树,也叫二叉平衡树,红黑树因为在插入删除时要维护树结构,所以也会对效率造成影响,同时,如果使用这两种树结构来进行存储,当有大数据量,比如100万条,树就会很高,因为数据库的数据是存储在磁盘上的,因此每次进行查询,就会对磁盘进行一次io操作,所以这两种结构都不合适。
hash表结构,就类似于jdk1.8之前的hashmap底层,数组+链表,这种数据结构不提供范围查询的方式,如果说where name = 'zhangsan',会根据zhangsan计算出来索引值,并不是一个排序好的范围,所以不适合作为索引的底层。
b+tree结构,叶子节点包含了所有的索引,并且每个节点直接维护有指针指向下一节点,这样
因此,mysql的索引使用的是b+tree,具体b+tree和b-tree的区别,后面进行介绍。
b-tree
1、叶节点具有相同的深度,叶节点的指针为空
2、所有索引元素不重复
3、节点中的数据索引从左到右递增排序
这种结构,实际上是对红黑树的一种改造,使根节点同时有多个,中间有空隙,每个节点上带有数据,匹配到之后进行返回,这种结构可以控制树的高度,比方说查到id = 20的数据,首先进入根节点,判断得到20在15到56之间,往下找,找到20,因为节点中的数据索引都是递增的,所以到达最后一个分支的时候,查询效率也是较高的,最后返回data完事。但是每个索引处,都存放有data,数据量大的情况下,这种结构并不能支撑起太多的数据量级。但是对于范围查找的支持并不好。
b+tree (b-tree变种)
1、非叶子节点不存储data,只存储索引(冗余),这样可以存放更多的索引
2、叶子节点包含所有索引字段
3、叶子节点用指针连接,提高区间访问的性能
b+tree结构,所有的非叶子节点都没有data,这样可以使树可以存放更多的索引,先找到索引,再去叶子节点处查找data,非叶子节点都是要加载到内存的,带上data会浪费内存。有了冗余的索引元素,这样可以让所有的索引元素的存放到非叶子节点。主键即使是使用bigint,只占8byte的空间,16kb/8byte,就可以存下千万级的数据量。
mysql的存储引擎
常用的有MyISAM和InnoDB,是形容表的,数据库也可以设置,但是最终取决于表,默认InnoDB
MyISAM
它不支持事务,也不支持外键,尤其是访问速度快
InnoDB
InnoDB是一个健壮的事务型存储引擎,这种存储引擎已经被很多互联网公司使用,为用户操作非常大的数据存储提供了一个强大的解决方案。InnoDB还引入了行级锁定和外键约束
数据库的数据存储在磁盘上,data目录下,每个文件夹都是一个数据库实例
MyISAM:
单张表对应在磁盘上的文件有三个,.frm、.MYD、.MYI,分别存储着表结构,表中的数据,表中的索引,这种引擎的具体查找过程如下:
InnoDB:
单张表对应在磁盘上的文件有两个,.frm、.ibd,分别存储着表结构、表数据和索引(在一个文件中)
1)表数据文件本身就是按b+tree组织的一个索引结构文件
2)聚集索引 - 叶节点包含了完整的数据记录
3)为什么InnoDB表必须有主键,并且推荐使用整型的自增主键
没有主键,没有办法以b+tree的数据结构来组织数据,如果没有主键,会去扫描表中各个字段,如果有内容都不一样的字段,就会被设置为主键,如果不存在这样的字段,mysql会自动维护一个主键索引,因为数据库的资源十分珍贵,所以最好自己建一个主键。整型更好比较,因为b+tree底层是排好序的数据,使用自增的整型主键就可以直接往后面添加,不会重新排序,造成节点分裂。不自增的话还可能会有一个树平衡的操作,就会造成性能开销。
4)为什么非主键索引结构叶子节点存储的是主键值?
区别在于叶子节点,存储着完整的数据
InnoDB主键索引就是一个聚集索引,索引和数据分开存储就是非聚集索引,ibd = MYI+MYD
联合索引
联合索引的排序规则是从左至右,第一个字段进行排序,然后第二个,第三个....
sql优化
1、最左前缀法则
2、不在索引列上做任何操作(计算、函数、自动或者手动类型转换),会导致索引失效而转向全表扫描
3、mysql在使用不等于 != 或者<> 的时候,无法使用索引,会导致全表扫描
4、is null、is not null一般情况下也是无法使用索引的
5、like以通配符开头 ,mysql索引也会失效,变为全表扫描操作
6、尽量只访问索引列,减少select *
Linux安装mysql
和其他数据库相比,MySql有点与众不同,他的架构可以在多种不同场景中应用并发挥良好的作用,主要体现在存储引擎的架构上,插件式的存储引擎架构将查询处理和其他的系统任务以及数据的存储提取相分离。这种架构可以根据业务的需求和实际需要选择合适的存储引擎。
检查本机是否安装过mysql: rpm -qa|grep -i mysql
安装mysql服务端:rpm -ivh Mysql-server..... .rpm
安装mysql客户端:rpm -ivh Mysql-client..... .rpm
安装好之后,会提示说,创建了一个root最高权限账户root,但是没有密码,需要自己去设置密码
判断mysql是否安装成功:
1、查看mysql安装时创建的mysql用户和mysql组
cat /etc/passwd|grep mysql
mysql:x:101:103:MySQL server:/var/lib/mysql:/bin/bash
cat /etc/group|grep mysql
mysql:x:103:
2、可以查看版本信息
mysqladmin --version
启动mysql
service mysql start/stop
查看mysql进程
ps -ef|grep mysql
直接输入mysql,即可引入命令行,因为mysql默认没有设置密码,所以直接进去了,exit,按照安装时提示的命令,进行设置密码,再次要进入命令行时需要下面命令:
mysql -u root -p 输入正确的密码后即可进入
chkconfig mysql on
可以通过 ntsysv 命令查看是否设置成开机后自启动
装完记得修改字符集编码。
通过 show variables like 'character%' ; 可以查看字符集编码格式
拷贝一份配置文件
cp /usr/share/mysql/my-huge.cnf /etc/my.cnf (5.5版本)
5.6版本叫 my-default.cnf
修改字符集编码
[client]
default-character-set=utf8
[mysqld]
character_set_server=utf8
character_set_client=utf8
collation-server=utf8_general_ci
[mysql]
default-character-set=utf8
设置字符集之前创建的表,插入数据还是会乱码,新建的表不会乱码,所以一定要在安装完之后就进行设置。