mysql索引
定义:索引是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据库所在的物理地址。
使用索引后可以不用扫描全表来定位某行的数据,而是先通过索引表找到该行数据对应的物理地址然后访问相应的数据,因此能加快数据库的查询速度
索引就好比是一本书的目录,可以根据目录中的页码快速找到所需的内容
索引是表中一列或者若干列值的排序办法
建立索引的目的是为了加快对表中记录的查找或者排序
索引的作用
设置了适合的索引后,数据库利用各种快速定位技术,能够大大加快查询速度,这是创建索引的最主要的目的
当表很大或者查询速度牵扯到多个表中时,使用索引可以提高查询的速度
可以降低数据库的IO成本。可以保证数据库中每一行数据的唯一性
可以加快表与表之间的连接
在使用分组和排序的时候,可以大大减少分组和排序的时间
建立索引在搜索和恢复数据库中的数据时能显著提高性能
索引的副作用(缺点)
索引需要占用额外的磁盘空间
对于MYISAM引擎而言,索引文件以及数据是分离的,索引文件用于保存数据记录的地址。而INNODB引擎的表数据文件本身就是索引文件
在插入和修改数据时要花费更多的时间,因为索引也会随之变动的
建立索引的原则与依据
索引虽然可以提升数据的查询速度,但是并不能在任何情况下都建立索引,因为索引本身就会消耗系统资源,在有索引的情况下,数据库会先进行索引查询,然后定位到具体的数据行。如果索引使用不当·,反而会增加数据库的负担。
表的主键、外建必须都要有索引。如果没有索引,每一次查询都要把表遍历一遍,会严重的影响数据库的性能
经常与其他表进行连接的表,会在连接字段上建立索引
唯一性太差的字段是不适合建立索引的
更新太频繁的字段是不适合建立索引的
经常出现在where子句中的字段,特别是大表的字段,应当建立索引
在经常进行group by 、orderby by 的字段上建立索引
索引应该建立在选择性高的字段上
索引应该建立在小字段上,对于大字段的文本字段甚至超长字段,是不需要建立索引的
索引的分类以及创建
create table member (id int(10),name varchar(10),cardid int(18),phone int(11),address varchar(50),remark text);
(1)普通索引:最基本的索引类型,没有唯一性的限制条件
create index 索引名 on 表名 (列名[(length)]);
#length:是可选项,下面的length同理,如果忽略length的值,则会在使用整个列的值来作为索引,如果指定,使用列的前length个字符来创建索引,这样有利于减小索引文件的大小,在不损失精确度的情况下,长度越短越好
举例:
cerate index name_index on member (name);
修改表结构的方式创建
alter table 表名 add index 索引名字 (列名);
创建表的时候来指定索引 (不太推荐)
create table 表名 (字段1 数据类型,字段2 数据类型.....,index 索引名 (列名));
(2)唯一索引:与普通索引类似,但是区别是唯一索引的每一个值都是唯一的,唯一索引可以允许有空值,但是是和主键是不同的。如果是用组合索引创建,则列值的组合值必须是唯一的,添加唯一键将自动创建唯一索引
直接创建唯一索引
create unique index 索引名 on 表名(列名);
举例:
create unique index cardid_index on member(cardid);
修改表的方式创建
alter table 表名 add unique 索引名字(列名);
创建表的时候指定:create table 表名 (字段1 数据类型,字段2 数据类型.....,unique 索引名 (列名));
(3)主键索引:是一种特殊的唯一索引,必须指定为"primary key"。一个表只能有一个主键,不允许有空值。
添加主键将自动创建主键索引
创建表的时候来指定:
create tables 表名 (......... ,primary key (列名));
修改表的方式创建
举例:alter table member add primary key (id);
(4)组合索引,(单列索引与多列索引)。可以是单列上创建的索引,也可以是在多列上创建的索引,需要满足最左侧原则。因为select语句的where 的工作原理是依次从左往右执行的,因而在使用select 语句查询where 条件语句使用的字段时,顺序请务必一致。否则索引将不会生效。
create table 表名 (列名1 数据类型,列名2 数据类型.......... ,index 索引名字 (列名1 ,列名2,列名3.....));
select * from 表名 where 列名1='内容1' and 列名2='内容2' and 列名3='内容3';
(5)全文索引(fulltext):适合在进行迷糊查询的时候使用,可以用于在一边文章中检索文本信息,在mysql 5.6版本前只能使用myisam 引擎,在5.6之后的版本可以使用innodb索引,全文索引可以在char、varchar 、text 类型的列上创建,每表只允许拥有一个全文索引
直接创建索引
create fulltext index 索引名 on 表名 (列名);
修改表的方式创建
alter table member add fulltext remark_index (remark);
创建表的时候指定索引
create table 表名 (字段1 数据类型,字段2 数据类型.....,fulltext 索引名字 (列名));
#数据类型可以为char、varchar、text
使用全文索引查询
select * from 表名 where match (列名) against ('查找内容')
insert into member values(1,'zhang',2,li,3,'wang','this is member for us!');
使用全文搜索,但是因为没有数据,所以报空
查看索引
show index from 表名;
show keys from 表名;
各个字段的含义如下
table :表的名称
non_unique :如果索引不能包括重复的词,则是0.否则为 1
key_name;索引的名称
seq_in_index :索引中的序号,从1开始
colum_name:列名称
collation:列以什么样的方式来存储在索引中,在mysql中,有值'A'升序或者null(五分类)
cardinality: 索引中唯一值数据的估计值
sub_part :如果列只是部分的被编入到索引,则为被编入索引的字符的数目,如果整列都被编入索引,则为null
packed: 指示关键词。如何被压缩如果没有被压缩,则为null
null: 如果含有null,则含有yes , 如果没有的话,那么该列含有no
index_type :用过的索引方法(btree , fulltext .hash ,rtree)
删除索引
直接删除索引
drop index 索引名 on 表名;
修改表方式删除索引
alter table 表名 drop index 索引名;
删除主键索引
alter table 表名 drop primary key;
总结:mysql索引
索引的主要作用加快 数据库数据查询速度,对字段排序
如何加快查询速度的?(优化)
索引保存索引的值以及这个值的数据所在行的物理地址,使用索引后可以不用再扫描/遍历全表来定位某行数据,而是先通过索引值找到对应行数据的物理地址后访问相应的数据。
拿索引做比喻,索引就像是书本的目录
副作用:索引文件额外占用磁盘空间,修改或插入会花费更多时间
创建索引的原则
表数据较多时,一般超过300行,就应该创建索引
一般是在主键、 外键、经常出现在where,group by, order by或者多表查询时连接的字段上创建索引
索引一般不建议在唯一性差的、 会频繁更新的、大文本字段上创建
mysql事物
1、事物的概念
事物是一种机制,一个操作序列,包含了一组数据库的命令,并且把所有的命令视作为一个整体一起向系统提交或者撤销操作请求,就是说这一组数据库命令要么都执行,要么都不执行
事物是一个不可分割的工作逻辑单元,在数据库系统上执行并发操作的时候,事物是最小的控制单元
事物适用于多用户同时操作的数据库系统的场合,例如银行、保险公司、以及证券交易系统
事物通过事物的整体性以保证数据的一致性
事物能够提高在向表中更新和插入信息期间的可靠性
2、事物的ACID特点
是指在可靠的数据库管理系统中,事物应该具备有的四个特性,原子性、一致性、隔离性、持久性。这是可开数据库应具备的几个特性
原子性:指的是一个不可再分割的工作单位,事物中的操作要么都发生,要么都不发生。
事物是一个完整的操作,事物的各个元素是不可分割的
事物中的所有元素必须为一个整体提交或者回滚
如果事物的任何元素失败、那么整个事物将失效
一致性
指的是在事物开始前和事物结束后,数据库的完整性约束没有被破坏
当事物完成时,数据库必须处于一致的状态
在事物开始前,数据库中存储的数据处于一致的状态
在正在进行的事物当中,数据可能处于不一致的状态
当事物成功完成后,数据必须再次回到已知的一致状态
隔离性:
指的是2在并发环境当中,当不同的事物同时操纵相同的数据的时,每个事物都有各自的完整数据空间
对数据进行的修改的并发事物是彼此隔离的,表明事物必须是独立的,他不应以任何方式依赖于或者影响其他事物‘
修改数据的事物可以在另一个使用相同数据的事物开始前访问这些数据,或者在另外一个使用相同数据的事物结束之后再访问这些数据。
也就是说并发访问数据库时,一个用户的事物不能被其他事物所干扰。各个并发事物之间数据是独立的
持久性:
指不管系统是否发生故障,事物的处理结果都是永久的
一旦事物被提交,事物的效果都会被永久的保留在数据库中
总结:在事务管理中,原子性是基础,隔离性是手段,一致性是目 的,持久性是结果。
当多个客户端并发地址访问同一个表时,可能出现下面的一致性问题
1、脏读:一个事物读取了另一个事物未提交的数据,而这个数据是可能回滚的
2、不可重复读,一个事物内两个相同的查询却返回了不同数据,这是由于查询时系统中其他事物修改的提交而引起的
3、幻读:一个事物对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行,同时,另外一个事物也修改了这个表中的数据。这种修改是向表中插入一行新的数据,那么操作前一个事物的用户会发现表中还有没有修改的数据行,就好像发生了幻觉一样
4、丢失更新:两个事物同时读取同一条记录,a先修改记录,b提交数据后的b修改结果覆盖了a的修改结果
事物隔离级别决定了事物之间可见的级别
mysql事物支持如下的四种隔离,用以控制事物所做的修改,并将修改通告到其他并发的事物
1、未提交读
允许一个事物可以看到其他事物未提交的修改
2、提交读
允许一个事物可以看到其他事物已经提交的修改,但是未提交的是不可看见的
3、可重复读
确保如果在一个事物中执行两次相同的select语句,都能得到相同的结果,不管其他事物是否提交这些数据
4、串行读(锁表)
完全串行话的读,将一个事物与其他事物完全的隔离,每次读都徐璈获得表级共享锁,读写都会相互阻塞
mysql默认的事物处理级别是可重复读,而oracle server是提交读
事物处理级别的作用范围分为两种
全局级:对所有的会话有效
会话级别:只对当前的会话有效
查询全局事物隔离级别
show global variables like '%isolation'
select @@global.tx_ioslation;
查询会话事物隔离级别
show global variables like '%isolation'
select @@global.tx_ioslation;
select @@tx_ioslation;
设置全局事物隔离级别
set global transaction ioslation level read committed;
设置会话事物隔离级别
set session transaction ioslation level read committed;
查询会话事务隔离级别:
show session variables like '&isolation%' ;
SELECT @@session.tx isolation;
SELECT @@tx_isolation;
设置全局事务隔离级别:
set global transaction isolation level read committed;
设置会话事务隔离级别:
set session transaction isolation level read committed;
3.事务控制语句
BEGIN或START TRANSACTION: 显式地开启一个事务。
COMMIT或COMMITWORK:提交事务,并使已对数据库进行的所有修改变为永久性的。
ROLLBACK或ROLLBACK WORK:回滚会结束用户的事务,并撤销正在进行的所有未提交的修改。
SAVEPOINT S1:使用SAVEPOINT 允许在事务中创建一一个回滚点,一 -个事务中可以有多个SAVEPOINT; “S1"代表回滚点名称。
ROLLBACK TO [SAVEPOINT] S1: 把事务回滚到标记点。
案例:
use kgc;
create table account (
id int(10) primary key not null,
name varchar (40),
money double
);
insert into account values(1, 'A' , 1000);
insert into account values(2, 'B', 1000);
#测试提交事务
begin;
update account set money= money - 100 where name='A' ;
4.使用set设置控制事务
SET AUTOCOMMIT=0; #禁止自动提交
SET AUTOCOMMIT=1; #开启自动提交,Mysq1默认为1
SHOW VARIABLES LIKE ' AUTOCOMMIT'; #查看Mysql中的AUTOCOMMIT值
如果没有开启自动提交,当前会话连接的mysql的所有操作都会当成- - 个事务直到你输入rollbackl commit;当前事务才算结束。当前事务结
束前新的mysql连接时无法读取到任何当前会话的操作结果。
如果开起了自动提交,mysql 会把每个sql语句当成一个事务, 然后自动的commit。
当然无论开启与否,begin; commit lrollback;都是独立的事务。
use kgc;
select * from account;
SET AUTOCOMMIT=0;
update account set money= money + 100 where name='B';
select * from account;
quit
mysql -u root -P
use kgc;
select * from account;
mysql存储引擎
MyISAM 表支持3种不同的存储格式:
(1)静态(固定长度)表
静态表是默认的存储格式。静态表中的字段都是非可变字段,这样每个记录都是固定长度的,这种存储方式的优点是存储非常迅速,容易缓存,出现故障容易恢复;缺点是占用的空间通常比动态表多。
(2)动态表
动态表包含可变字段,记录不是固定长度的,这样存储的优点是占用空间较少,但是频繁的更新、删除记录会产生碎片,需要定期执行OPTIMIZETABLE语句或myisamchk-r命令来改善性能,并且出现故障的时候恢复相对比较困难。
(3)压缩表
压缩表由myisamchk工具创建,占据非常小的空间,因为每条记录都是被单独压缩的,所以只有非常小的访问开支。
#查看系统支持的存储引擎
show engines;
#查看表使用的存储引擎
方法一:
show table status from 库名where name='表名'\G
方法二:
use库名;
show create table 表名;
#修改存储引擎
1.通过alter table 修改
use库名;
alter table 表名engine=MyISAM;
2.通过修改/etc/my.cnf 配置文件,指定默认存储引擎并重启服务
vim /etc/my.cnf
..........................
[mysqld]
.........................
default-storage-engine=INNODB
systemctl restart mysql.service
注意:此方法只对修改了配置文件并重启mysq1服务后新创建的表有效,已经存在的表不会有变更。
3.通过create table 创建表时指定存储引擎
use库名;
create table 表名(字段1数据类型,...) engine=MyISAM;
//InnoDB行锁与索引的关系
InnoDB行锁是通过给索引项加锁来实现的,如果没有索引,InnoDB将通过隐藏的聚簇索引来对记录加锁。
1)
delete from t1 where id=1;
如果id字段是主键,innodb对 于主键使用了聚簇索引,会直接锁住整行记录。
2)
delete from t1 where name='aaa' ;
如果name字段是普通索引,会先锁住索引的两行,接着会锁住相应主键对应的记录。
3)
delete from t1 where age=23;
如果age字段没有索引,会使用全部打1描过滤,这时表上的各个记录都将加,上锁。
//死锁
死锁一般是事务相互等待对方资源,最后形成环路造成的。
案例:
```html/xml
create table t1(id int primary key, name char(3), age int) ;
insert into t1 values(1, 'aaa' ,22) ;
insert into t1 values(2, 'bbb',23);
insert into t1 values(3, 'aaa' ,24);
insert into t1 values(4, 'bbb',25);
insert into t1 values(5, 'ccc',26);
insert into t1 values(6, 'zzz' ,27) ;
session 1 session 2
begin; | begin;
delete from t1 where id=5;
select * from t1 where id=1 for update;
delete from t1 where id=1; #死锁发生
update t1 set name= 'qqqq' where id=5; #死锁发生
#forupdate可以为数据库中的行上一-个排它锁。当--个事务的操作未完成时候,其他事务可以读取但是不能写入或更新。
//如何尽可能避免死锁?
1)以固定的顺序访问表和行。
2)大事务拆小。大事务更倾向于死锁,如果业务允许,将大事务拆小。
3)在同一个事务中,尽可能做到一-次锁定所需要的所有资源,减少死锁概率。
4)降低隔离级别。如果业务允许,将隔离级别调低也是较好的选择,比如将隔离级别从RR调整为RC,可以避免掉很多因为gap锁造成的死锁
5)为表添加合理的索引。如果不使用索引将会为表的每一行记录添加上锁,死锁的概率大大增大。