首先了解数据库存储两大常用引擎 Innodeb和MyISAM
数据库引擎 | 存储方式 | 底层结构 | 事务 | 锁 | 索引 | 主外键 |
---|---|---|---|---|---|---|
MyISAM | 存储三个文件frm表结构和myd数据和myi索引 | B树 | No | 行级锁 | 非聚集 | No |
Innodeb | 存储两个文件 frm表结构和myd数据 | B+树 | Yes | 行级锁和表级锁(默认) | 聚集索引 | Yes |
B树是每一个节点都存在key和访问磁盘value的索引,B+树是叶子节点才存数据值,其它都是索引
单值索引where name=‘xxx’ 复合索引where name=‘xx’ and email=‘xxx’ 唯一索引:值得是唯一值的
create index idx_user_name on user(name) //单值
create index idx_user_nameEmail on user(name,email) //复合
create unique index idx_user_id on user(id) //
Sql执行顺序
索引本质是数据结构,目的是提高查找效率,排好序的快速查找数据结构就是索引
数据库系统还维护者满足特定查找算法的数据结构,这些数据结构以某种方式指向数据,比如B树和B+树
B树
叶子节点存储的是磁盘数据的地址
查询快,但是增删慢,因为每次修改,还要修改指向数据的索引
优势: 提高检索效率,降低数据排序成本,避免全盘扫描
索引不是越多越好
索引也是一张表,保存了主键与索引字段,所以也占内存,
而且虽然提高查询速度,但是降低更新表的速度,因为mysql不仅要保存数据,还要保存一下索引文件每次更新添加的索引列字段,都会调整更新后带来的键值变化的索引
如果一个表没有建索引,会自动以主键为索引,如果没有主键,会自动选取一个不为空的当主键
explain+sql
explain select * form user
就是说明该行数据关联了哪个表执行
syetem>const>eq_ref>ref>range>index>All
单表连接 如果是直接索引改的话,可以把type从all改为ref,因为一旦遇到了范围查询索引就会失效 type就会是range
双表连接 相反键
如果是左连接,那索引建在左边,没效果,因为左连接就是含左表所有记录,建在右边,会减少很多rows
三表连接 都是左连接设置给后两行,rows会变少,然后type是ref
优先优化最里层的,然后就是尽可能减少join循环次数,然后用小表来连接大表
当无法得知join的字段是否有索引的时候,且内存充足的话可以调大joinBuffer的大小,来缓存
全值匹配,然后如果是建立了三个索引的复合索引,但是where没有从第一个开始(火车头,最左匹配原则)
全值匹配我最爱,中间兄弟不能断,
函数自动转换或者计算会失效索引,范围之后全失效
使用不等于会使索引失效
is null ,is not null 也会使索引失效
尽量使用覆盖索引,索引列和查询列一致,之访问索引的查询,减少select *
like以%开头会使索引失效,百分like加右边
如何解决like%写右边索引失效
比如 给name 和age建立索引,两个%不会失效索引
用覆盖索引来避免全盘扫码
【优化总结口诀】
全值匹配我最爱,最左前缀要遵守;
带头大哥不能死,中间兄弟不能断;
索引列上少计算,范围之后全失效;
Like百分写最右,覆盖索引不写星;
不等空值还有or,索引失效要少用;
VAR引号不可丢,SQL高级也不难!
每次取数据都是按页取,Innodb是16kb,MYyISAM是4kb
set global slow_query_log=1;
show variables like ‘%slow_query_log%’;
会出现slow_query_log_file地址
set global long_query_time=3; //修改慢查询阈值
打开log文件
show global status like ‘Slow_queries%’; //打印慢sql条数
mysqldumpslow 日志分析
是mysql可以用来分析当前会话中语句执行的资源消耗情况,
默认保存最近15次运行结果,默认关闭set profiling=on
然后会显示sql ,id,执行时间,
再show profile cpu,block io for query id查看sql执行生命周期
按操作来分有读锁和写锁
可以想想读写锁,读锁可以共享同时,但是写锁是独占的不能和读锁一起,也不能和写锁一起
lock table 表名 read,表名 write;
unlock tables;释放表锁
MYIASAM是写锁优先,不适合作为查询的数据库引擎,适合写的场景,比如店家上架
按照类别分有表锁和行锁
表锁粒度大,效率低,容易死锁,冲突高
行锁粒度小,效率高,页锁,发生锁的冲突低,并发级别高
Innodeb支持
什么是事务,事务是保证业务要么成功要么失败的方案,具有ACID属性
A 原子性 要么双方一起成功要么一起失败
C 一致性 成功后的总合和之前的总合应该相等,质量没有变化
I 隔离性 每个事务的执行不会影响其它的事务,且事物内部对外部不可见
D 持久性 事务完成,数据永久保存在数据库中
更新丢失
两个事务都同时更新一行数据,一个事务对数据的更新把另一个事务对数据的更新覆盖了。这是因为系统没有执行任何的锁操作,因此并发并没有被隔离开来。
脏读
一个事务读取到了另一事务未提交的数据操作结果。这是相当危险的,因为很可能所有的操作都被回滚。
A修改数据之前,有200快,B查到了未提交的200,A这时候扣了100块,提交完是100,B却是查到未提交的之前的200
不可重复读(修改)
一个事务对同一行数据重复读取两次,但是却得到了不同的结果
Mysql默认是可重复读
幻读(新增和删除)
未提交读: 可以处理更新丢失,如果一个事务已经开始写数据,则不允许其他事务同时进行写操作,但允许其他事务读此行数据。可通过“排他写锁”实现。
提交读: 处理更新丢失、脏读。读取数据的事务允许其他事务继续访问改行数据,但是未提交的写事务将会禁止其他事务访问改行。可通过“瞬间共享读锁”和“排他写锁”实现。
可重复读取(Repeatable Read): 处理更新丢失、脏读和不可重复读取。读取数据的事务将会禁止写事务,但允许读事务,写事务则禁止任何其他事务。可通过“共享读锁”和“排他写锁”实现,别人在读的时候不允许其它人写
序列化(Serializable): 提供严格的事务隔离。要求失去序列化执行,事务只能一个接一个地执行,不能并发执行
隔离级别越高,越能保证数据的完整性和统一性,但是对并发性能的影响也越大。对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed。它能够避免脏读,而且具有较好的并发性能。尽管它会导致不可重复读、幻读和第二类丢失更新这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。