MySQL优化、索引、事务

MySQL优化

(1)使用limit对查询结果的记录进行限定
(2)避免select *,将需要查找的字段列出来
(3)使用连接(join)来代替子查询
(4)拆分大的delete或insert语句
(5)使用explain查询和分析SQL的执行计划

(一)Count()和Max()优化

select max(col_name) from table_name 会进行全表扫描
create index idx_name on table_name(col_name)
默认B+树索引,顺序存储,只需要取到B+树中的最后一个值,就可以。不必进行表的操作,避免了磁盘操作。
max可以通过索引优化,覆盖索引,完全可以通过索引查询到结果,称为覆盖索引。

select count(), count(col_name) from table_name;
count(
)是包含NULL值的结果 count(col_name)不包含NULL

(二)limit优化

limit 常用于分页处理, 时常会伴随order by 从句使用, 因此大多时候会使用 file sorts 这样造成大量的IO问题。
select col_name1,col_name2 from table_name order by col_name limit num1, num2;

  • 优化步骤1:使用有索引的列或主键进行order by操作
    select col_name1,col_name2 from table_name order by index_col_name limit num1, num2;
  • 优化步骤2:记录上次返回的主键,在下次查询时使用主键过滤。
    select col_name1,col_name2 from table_name where index_col_name > num1 and index_col_name <= num2 order by index_col_name limit 1, num1-num2;
    避免了数据量大时扫描过多的记录

(三)如何选择合适的列建立索引?

  1. 在where从句, group by从句, order by从句,on 从句出现的列
  2. 索引字段越小越好
  3. 离散度大的列放到联合索引的前面
    select * from payment where staff_id = 2 and customer_id = 584;
    是index(staff_id,customer_id)好?还是index(customer_id,staff_id)好?
    由于customer_id的离散度更大,所以应该使用index(customer_id,staff_id)好
    判断两列的离散度
    select count(distinct customer_id), count(distinct staff_id) from payment

(四)索引的维护 重复及冗余索引

重复索引是指相同的列以相同的顺序建立同类型的索引
冗余索引是指多个索引的前缀列相同,或是在联合索引中包含了主键的索引。(innodb每个索引后面附加主键)

mysql索引

功能: 快速查询
数据少的时候,功能不是很大,数据可以完全缓存在内存中,全表扫描也很快。
没有索引
每一列都建立索引
都是不对的

mysql索引是在存储引擎层实现的。
mysql支持的索引类型

B-tree

  • B-tree索引的特点
  • B-tree索引能够加快数据的查询速度
  • B-tree索引更适合进行范围查找(顺序存储)

什么情况下可以用到B树索引

  • 全值匹配的查询 order_sn = ‘9873’
  • 匹配最左前缀的查询 (a,b,c) a, a b, a b c
  • 匹配列前缀查询 order_sn = ‘98%’
  • 匹配范围值的查询 order_sn>’347′ and order_sn<‘567’
  • 精确匹配左前列并范围匹配另一列
  • 只访问索引的查询
  • 因为是顺序存储的也可以应用在order by中

Btree索引的使用限制

  • 如果不是按照索引最左列开始查找,则无法使用索引
  • 使用索引时不能跳过索引中的列
  • Not in 和 < >操作无法使用索引
  • 如果查询中有某个列的范围查询,则其右边的所有列都无法使用索引

Hash索引

Hash索引的特点

  • Hash索引是基于Hash表实现的,只有查询条件精确匹配Hash索引中的所有列时,才能够使用Hash索引。
  • 对于Hash索引中的所有列,存储引擎都会为每一行计算一个Hash码,Hash索引中存储的就是Hash码。 结构紧促,查询速度快。

Hash索引的限制

  • Hash索引必须进行二次查找(只存储了键值,没存除值,根据键值去内存或磁盘中找数据)
  • Hash索引无法用于排序
  • Hash索引不支持部分索引查找也不支持范围查找
  • Hash索引中Hash码的计算可能存在Hash冲突(选择性很差,比如性别就不合适,身份证号就合适)

为什么要使用索引

  • 索引大大减少了存储引擎需要扫描的数据量
  • 索引可以帮助我们进行排序以避免使用临时表
  • 索引可以把随机I/O变为顺序I/O

索引是不是越多越好

  • 索引会增加写操作的成本
  • 太多的索引会增加查询优化器的选择时间

索引优化策略

  • 索引列上不能使用表达式或函数
    select … from product where to_days(out_date)-to_days(current_date)<=30 使用函数
    select … from product where out_date<=date_add(current_date,interval 30 day)

  • 前缀索引和索引列的选择性
    create index index_name on table(col_name(n));
    索引的选择性是不重复的索引值和表的记录数的比值

    《MySQL优化、索引、事务》

  • 联合索引
    如何选择索引列的顺序

  • 经常会被使用到的列优先

  • 选择性高的列优先

  • 宽度小的列优先

  • 覆盖索引
    优点:

    • 可以优化缓存,减少磁盘IO操作
    • 可以减少随机IO,变随机IO操作变为顺序IO操作,磁盘处理顺序IO比随机IO快的多
    • 可以避免对Innodb主键索引的二次查询
    • 可以避免MyISAM表进行系统调用
  • 无法使用覆盖索引的情况

    • 存储引擎不支持覆盖索引
    • 查询中使用了太多的列 select *这种
    • 使用双%%的like查询,mysql底层api限制的

使用索引来优化查询

使用索引扫描来优化排序

  • 通过排序操作
  • 按照索引顺序扫描数据
  • 索引的列的顺序和Order By自居的顺序完全一致
  • 索引中所有列的方向(升序,降序)和Order By字句完全一致
  • Order by中的字段全部在关联表中的第一张表中

利用索引优化锁

  • 索引可以减少锁定的行数
  • 索引可以加快处理速度,同时也加快了锁的释放

删除重复和冗余的索引
primary key(id), unique key (id), index(id)
index(a), index(a,b)
primary key(id), index(a, id) innodb会自动把主键加到二级索引

索引的维护和优化

更新索引统计信息及减少索引碎片

MySQL事物

(一)事务(Transaction)及其ACID属性

事务是由一组SQL语句组成的逻辑处理单元,事务具有以下4个属性,通常简称为事务的ACID属性:
1.原子性(Atomicity):事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行。
2.一致性(Consistent):在事务开始和完成时,数据都必须保持一致状态。这意味着所有相关的数据规则都必须应用于事务的修改,以保持数据的完整性;事务结束时,所有的内部数据结构(如B树索引或双向链表)也都必须是正确的。
3.隔离性(Isolation):数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行。这意味着事务处理过程中的中间状态对外部是不可见的,反之亦然。
4.持久性(Durable):事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。

(二)并发事务处理带来的问题

相对于串行处理来说,并发事务处理能大大增加数据库资源的利用率,提高数据库系统的事务吞吐量,从而可以支持更多的用户。但并发事务处理也会带来一些问题,主要包括以下几种情况。
1.更新丢失(Lost Update):
当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题--最后的更新覆盖了由其他事务所做的更新。例如,两个编辑人员制作了同一文档的电子副本。每个编辑人员独立地更改其副本,然后保存更改后的副本,这样就覆盖了原始文档。最后保存其更改副本的编辑人员覆盖另一个编辑人员所做的更改。如果在一个编辑人员完成并提交事务之前,另一个编辑人员不能访问同一文件,则可避免此问题。
2.脏读(Dirty Reads):
一个事务正在对一条记录做修改,在这个事务完成并提交前,这条记录的数据就处于不一致状态;这时,另一个事务也来读取同一条记录,如果不加控制,第二个事务读取了这些“脏”数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被形象地叫做”脏读”。
3.不可重复读(Non-Repeatable Reads):一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现其读出的数据已经发生了改变、或某些记录已经被删除了!这种现象就叫做“不可重复读”。
4.幻读(Phantom Reads):一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为“幻读”。

(三)事务隔离级别

在上面讲到的并发事务处理带来的问题中,“更新丢失”通常是应该完全避免的。但防止更新丢失,并不能单靠数据库事务控制器来解决,需要应用程序对要更新的数据加必要的锁来解决,因此,防止更新丢失应该是应用的责任。
“脏读”、“不可重复读”和“幻读”,其实都是数据库读一致性问题,必须由数据库提供一定的事务隔离机制来解决。数据库实现事务隔离的方式,基本上可分为以下两种:
1.在读取数据前,对其加锁,阻止其他事务对数据进行修改。
2.不用加任何锁,通过一定机制生成一个数据请求时间点的一致性数据快照(Snapshot),并用这个快照来提供一定级别(语句级或事务级)的一致性读取。从用户的角度来看,好像是数据库可以提供同一数据的多个版本,因此,这种技术叫做数据多版本并发控制(MultiVersion Concurrency Control,简称MVCC或MCC),也经常称为多版本数据库。
数据库的事务隔离越严格,并发副作用越小,但付出的代价也就越大,因为事务隔离实质上就是使事务在一定程度上 “串行化”进行,这显然与“并发”是矛盾的。同时,不同的应用对读一致性和事务隔离程度的要求也是不同的,比如许多应用对“不可重复读”和“幻读”并不敏感,可能更关心数据并发访问的能力。
为了解决“隔离”与“并发”的矛盾,ISO/ANSI SQL92定义了4个事务隔离级别,每个级别的隔离程度不同,允许出现的副作用也不同,应用可以根据自己的业务逻辑要求,通过选择不同的隔离级别来平衡 “隔离”与“并发”的矛盾。
下表很好地概括了这4个隔离级别的特性:

隔离级别读数据一致性脏读不可重复读幻读
未提交读(Read uncommitted)最低级别,只能保证不读取物理上损坏的数据
已提交读(Read committed)语句级
可重复读(Repeatable read)事务级
可序列化(Serializable)最高级别,事务级
    原文作者:threerocks
    原文地址: https://www.jianshu.com/p/e5934fc91a5c
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞