目录
1. 索引
索引优化是对查询性能优化最有效的手段。索引能够轻易将查询性能提高好几个数量级。
索引的目的在于提高查询效率。
B+树结构。
创建索引结构时,要使用区分度较高的字段那一列; 索引字段占用空间要尽量的小。
在建表时,添加索引;不要在添加数据后,再添加索引,会将所有数据都会扫描,很慢。
聚集索引 primary key
1. 按照每张表的主键(primary key)构造一棵B+树,同时叶子结点存放的是行记录全部数据,也将聚集索引的叶子结点称为数据页,每个数据页都通过一个双向链表来进行链接。每张表只能拥有一个聚集索引。
2. 如果未定义主键,MySQL取第一个唯一索引(unique)而且只含非空列(not null)作为主键,InnoDB使用它作为聚集索引。
3. 如果都没有,InnoDB就自己产生一个这样的ID值,它有六个字节,而且是隐藏的,使其作为聚集索引。
好处:
1.它对主键的排序查找和范围查找速度非常快,叶子节点的数据就是用户所要查询的数据。如用户需要查找一张表,查询最后的10位用户信息,由于B+树索引是双向链表,所以用户可以快速找到最后一个数据页,并取出10条记录。
2.范围查询(range query),即如果要查找主键某一范围内的数据,通过叶子节点的上层中间节点就可以得到页的范围,之后直接读取数据页即可。
聚集索引的添加方式:
# 两种创建方式:
create table t1(id int primary key,);
create table t1(id int,primary key(id));
# 表创建后添加索引
alter table 表名 add primary key(id);
# 删除索引
alter table 表名 drop primary key;
辅助索引
where 后面写其它字段条件,比如 ...where name=‘xxx’,没有用主键索引,这时候就需要给name字段添加辅助索引,加速查询。
除了聚集索引以外的其他索引都是辅助索引,也称非聚集索引。
与聚集索引区别是:辅助索引的叶子节点不包含行记录的全部数据,只存放对应字段与它的值,以及主键的值。如{'name字段',name的值,主键id值}这样一个标签。
唯一索引 unique
create table t1(id int unique);
create table t1(id int,unique key u_name(id)); # 给这个索引起u_name名字
# 表创建后添加索引
alter table s1 add unique key u_name(id);
# 删除索引
alter table s1 drop index u_name;
普通索引:
# 创建
create table t1(id int,index index_name(id));
alter table s1 add index index_name(id);
creatr index index_name on s1(id);
# 删除
alter table s1 drop index u_name;
drop index 索引名 on 表名;
覆盖索引:
InnoDB存储引擎支持覆盖索引(covering index,或称索引覆盖),即从辅助索引中就可以得到查询记录,而不需要查询聚集索引中的记录。
好处:辅助索引不包含整行记录的所有信息,故其大小要远小于聚集索引,因此可以减少大量的IO操作。
联合索引:最左原则。(联合主键/唯一/普通等)
索引是有个最左匹配的原则的,所以建联合索引的时候,将区分度高的放在最左边,依次排下来,范围查询的条件尽可能的往后边放。
creatr table t1(id int,name char(10),index index_name(id,name));
正确使用索引
并不是说我们创建了索引就一定会加快查询速度,若想利用索引达到预想的提高查询速度的效果,我们在添加索引时,必须遵循以下问题:
1.范围问题,或者说条件不明确,条件中出现这些符号或关键字:>、>=、<、<=、!= 、between...and...、like
范围越大,速度越小;
...where id=1000 比 ...where id>1000 要快。
使用like时,通配符写在后面要比写在前面快。 'al%' > '%ex'
2.尽量选择区分度高的列作为索引(树的高度较低),区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0。
3.=和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式。
4. 索引列不能参与计算,保持列“干净“。
5.and与or的逻辑
条件1 and 条件2:所有条件都成立才算成立,但凡要有一个条件不成立则最终结果不成立
条件1 or 条件2:只要有一个条件成立则最终结果就成立
and:mysql会按照联合索引,从左到右的顺序找一个区分度高的索引字段(这样便可以快速锁定很小的范围),加速查询。
or:mysql会按照条件的顺序,从左到右依次判断。
6.最左前缀匹配原则,非常重要的原则,对于组合索引mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配(指的是范围大了,有索引速度也慢),比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。
查询优化神器——explain
rows是核心指标,绝大部分rows小的语句执行一定很快.
mysql> explain select * from s1 where id=10000;
+----+-------------+-------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | s1 | ALL | NULL | NULL | NULL | NULL | 2987134 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.01 sec)
2. mysql创建用户和授权
对新用户增删改
1.创建用户:
# 指定ip:192.118.1.1的chao用户登录
create user 'chao'@'192.118.1.1' identified by '123';
# 指定ip:192.118.1.开头的chao用户登录
create user 'chao'@'192.118.1.%' identified by '123';
# 指定任何ip的chao用户登录
create user 'chao'@'%' identified by '123';
2.删除用户
drop user '用户名'@'IP地址';
3.修改用户
rename user '用户名'@'IP地址' to '新用户名'@'IP地址';
4.修改密码
set password for '用户名'@'IP地址'=Password('新密码');
对当前的用户授权管理
#查看权限
show grants for '用户'@'IP地址'
#授权 chao用户仅对db1.t1文件有查询、插入和更新的操作
grant select ,insert,update on db1.t1 to "chao"@'%';
# 表示有所有的权限,除了grant这个命令,这个命令是root才有的。chao用户对db1下的t1文件有任意操作
grant all privileges on db1.t1 to "chao"@'%';
#chao用户对db1数据库中的文件执行任何操作
grant all privileges on db1.* to "chao"@'%';
#chao用户对所有数据库中文件有任何操作
grant all privileges on *.* to "chao"@'%';
#取消权限
# 取消chao用户对db1的t1文件的任意操作
revoke all on db1.t1 from 'chao'@"%";
# 取消来自远程服务器的chao用户对数据库db1的所有表的所有权限
revoke all on db1.* from 'chao'@"%";
取消来自远程服务器的chao用户所有数据库的所有的表的权限
revoke all privileges on *.* from 'chao'@'%';
3. 数据备份与还原
备份:
mysqldump -uroot -p -B -d 库 >路径+文件名称.sql
-B :会记录库名,还原的时候会自动创建这个库。
还原:
mysql -uroot -p < 路径+文件名称.sql
4. mysql锁
Innodb默认加行锁, MyISAM 默认表锁。
# 加表锁:
显示加锁:
共享读锁:lock table tableName read;
独占写锁:lock table tableName write;
同时加多锁:lock table t1 write,t2 read;
批量解锁:unlock tables;
# 行级锁:
排它锁:
select * from 表名 where 条件 for update;
查看死锁
第一种:
1.查询是否锁表
show OPEN TABLES where In_use > 0;
2.查询进程(如果您有SUPER权限,您可以看到所有线程。否则,只能看到自己的线程)
show processlist
3.杀死进程id(就是上面命令的id列)
kill id
第二种:
1.查看下在锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
2.杀死进程id(就是上面命令的trx_mysql_thread_id列)
kill 线程ID
例子:
查出死锁进程:SHOW PROCESSLIST
杀掉进程 KILL 420821;
其它关于查看死锁的命令:
1:查看当前的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
2:查看当前锁定的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
3:查看当前等锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
5. 事务
逻辑上是一组sql语句操作,组成这组操作的各个sql语句,执行时要么全部成功,要么全部失败。
5.1 事务属性
事务是由一组SQL语句组成的逻辑处理单元,事务具有ACID属性。
1. 原子性(Atomicity):事务是一个原子操作单元。在当时原子是不可分割的最小元素,其对数据的修改,要么全部成功,要么全部都不成功。
2. 一致性(Consistent):事务开始到结束的时间段内,数据都必须保持一致状态。
3. 隔离性(Isolation):数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的"独立"环境执行。
4. 持久性(Durable):事务完成后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。
5.2 事务常见问题
1.更新丢失(Lost Update)
原因:当多个事务选择同一行操作,并且都是基于最初选定的值,由于每个事务都不知道其他事务的存在,就会发生更新覆盖的问题。类比github提交冲突。
2.脏读(Dirty Reads)
原因:事务A读取了事务B已经修改但尚未提交的数据。若事务B回滚数据,事务A的数据存在不一致性的问题。
3.不可重复读(Non-Repeatable Reads)
原因:事务A第一次读取最初数据,第二次读取事务B已经提交的修改或删除数据。导致两次读取数据不一致。不符合事务的隔离性。
4.幻读(Phantom Reads)
原因:事务A根据相同条件第二次查询到事务B提交的新增数据,两次数据结果集不一致。不符合事务的隔离性。
5.3 操作
开启事物:start transaction; / begin;
commit; 提交保存
rollback; 回滚事务
在事务中加锁,如果一直没有commit,这把锁一直会存在。