Mysql(三、查询优化)

一、基本概念

1. 查询是在数据库中查找到合适数据,并返回结果集
2. 查询优化可以从如下几个方面去解决: 
        2.1 为数据表编写索引
        2.2 如何最大程度的利用索引

二、优化方式

  • 优化第一个着手点:该字段是否有索引及是否生效
  • 滥用索引,有可能反而会导致查询性能变慢

1. 常见索引

1. PRIMARY KEY(主键索引):     列值唯一(不可以有null, 表中只有一个
2. UNIQUE(唯一索引) :          列值唯一(可以包含一个null),一个表中可以有多个唯一索引
3. 加INDEX(普通索引) :          仅仅为查找速度加快
4. FULLTEXT(全文索引) :        对文本的内容进行分词,进行搜索
5. 多列索引:                   多列值组成一个索引,专门用于组合搜索,其效率大于索引合并
ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` ) 
ALTER TABLE `table_name` ADD UNIQUE ( `column` ) 
ALTER TABLE `table_name` ADD INDEX index_name ( `column` )
ALTER TABLE `table_name` ADD FULLTEXT ( `column`) 
ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )

-- 展示所有索引
show index from table_name

2. 索引引入

2.1 使用前
  • 不添加索引,数据行无序, select * from table where company_num < = 17。会对每一行数据去判断字段否满足条件
  • 如果表中数据很大,但符合查询条件的数据行很少。遍历数据去检索很浪费时间的

在这里插入图片描述

2.2 引入后
  • 查找为13数据,索引到14时,则不会继续往下匹配,直接返回结果
  • 添加索引,索引值是经过分类的,因此从第几行数据开始及结束(定位算法)
  • 数据表中支持多索引,多个索引单独在查询时候进行工作;
  • 索引中的数据行一般会比数据文件的数据行短一些,当增删该数据时,来回移动较短的索引值比来回移动较长的数据文件的数据方便一些
  • 对于写数据很频繁的数据表,不宜建立太多的索引,因为每次写数据,都要对该表的所有索引进行重新排列;
    在这里插入图片描述
2.3 索引位置
  • 索引位置和具体的数据库引擎有关,mysql5.5之后默认内置存储引擎是InnoDB
  • InnoDB使用一个表空间,将所有的InnoDB类型的数据表的数据和索引存储。可以通过配置,使其为每个数据表分别创建一个自己的表空间,但是该表的数据和索引,都是保存在自己的同一个表空间里面;

3. 索引查询优化解释

  • where子句后的字段的匹配(如上面的例子);
  • 关联操作中与其他数据表里的数据行相匹配的时候;
#三个表t1,t2,t3,每个数据表都各自包含c1,c2,c3的列,每个数据列包含1-1000;
select t1.c1,t2.c2,t3.c3 from t1 inner join t2 inner join t3 where t1.c1=t2.c2 and t1.c1= t3.c3;
  1. 如果不使用索引,则检索基数100010001000 = 10亿种数据组合,再从其中筛选符合的1000中;
  2. 对t2.c2,t3.c3添加索引后: t1表中检索第一行数据,t2的时候,可以直接匹配到相等的数据(定位算法),同理可以匹配到t3;t1表仍然使用的是全局搜索,但是t2和t3都会很快得到匹配的列;
  • 使用MIN(),MAX()函数的列,添加索引后可直接定位到数据,而不用全表扫描;
  • 使用order by 和group by的字段,添加索引可快速响应;

4. 索引缺点

  • 频繁写数据的表:写数据的时候,不仅要为数据列写入数据,而且要更新该表中所有字段上的索引项,索引 更新方面的开销会很大,写入性能较差
  • 索引需要占用一定的磁盘空间,滥用索引导致表空间很快达到上限;

5. 索引注意

  • where子句后:=匹配字段,order by,group by,min(),max(),以及联查(最适合),不需要为select 后面的字段添加索引;
  • 数据列维度值: 一个列中出现的不重复的个数,如一个列中包含1,2,3,4,4,4,5,那么维度值为五;维度越高,不重复的数据越多,索引也就能更好的对数据行进行分区。如果一个数据列只有两个值如性别,即使添加索引,但查询优化程序发现某个值的出现频率超过30%,就会放弃索引而进行全局扫描,索引失效;
  • 数据列的值尽量短小: 尽量选用比较小的数据类型,比如char(20)能满足,就不要用char(100),可以提高索引的性能;
    1. 短小的值可以让比较操作更快进行,加快索引查找速度;
    2. 短小的值可以让索引体积更小,减少磁盘IO工作
  • 字符串的前缀添加索引: 假如一个char(200)的字符串,前10个字符串都是唯一的,后面的字符串相同,则仅仅为前面10个添加索引,就是变相的把数据列的值减小了;
  • 不要过分使用索引: 过分使用索引,会导致写入性能极大降低;

三、mysql查询优化器

1. 概念

发出一条sql查询时,mysql会分析这条sql,并考虑是否可以优化该条sql以加快查询;

2. 优化机理
  • 主要针对的是查看该条sql是否可以用索引来进行查询;
  • 以最严格的查询条件,尽可能多,快地将数据排除;
  • 可以通过在查询的sql前面加explain来查看具体的执行;
# 1. 最严格的条件: false条件,将所有数据都会排除,而不再去用id去匹配了(ID带索引的)
select * from cnip  where id>1000 and false;
# 2. 条件一满足的条数:900个,条件二满足的条数:300个, 两个都满足的条数:70;
# 查询优化器先检索条件二,再去检索条件一,尽可能每次检索都能更多更快排除不符合的数据
select * from cnip  where column1="value1" and column2="value2";
3. 优化查询具体方案
  • 尽量使用数据类型相同的列比较: 如果两个列都带索引,两个列数据类型相同时,查询的性能就会高一些;(如Char(10)和Varchar(10),Int和BigInt就属于不同的数据类型),索引虽然不会失效,但是查询性能会受到影响;
  • 使带索引的列在表达式中单独出现: 如果某个带索引的列,参与了数字运算或者函数,就会导致索引失效,但可以优化sql来进行改善;
# id带索引,但是查询的时候索引失效,因为要把所有id检索到,并去除2,改为下面进行优化
# 可以通过explain来查看具体索引是否失效了
explain select * from cnip where id*2<1000;
explain select * from cnip where id<1000/2;

# 给birthday建立索引,按照第一个查询,索引失效,可以改为第二行的
explain select * from student where YEAR(birthday)<'2020';
explain select * from student where birthday<'2020-01-01';
  • 不要在like开始的地方写出通配符----索引失效
-- 模糊匹配,索引可以正常使用,下面两个sql等价
select * from student where name like 'sd%';
select * from student where name >= 'sd' and name<='sf';

-- 模糊匹配,索引失效,进行全局搜索
select * from student where name like '%sd%';
  • 尽量不要在sql中使用or----导致索引失效:
explain select * from student where name = '4' or name = '3';
  • 避免过多使用mysql的类型转换----导致索引失效:
# name字段为字符串,这样写,系统会将'4','4th','4.0'都会转换为4,因此会放弃索引全局搜索
explain select * from student where name = 4; 
# 可以正常使用索引
explain select * from student where name = '4'; 

- 当mysql分析全表扫描比使用索引快的时候 ---- 导致索引失效

  • 多使用联结查询而不是子查询: 很多时候联结查询可能会比子查询速度快很多;
4. explain语句详解
explain select * from student where name like 'sd%'

在这里插入图片描述

  • select_type: 包含SIMPLE等;
  • table: 查询的表名;
  • partition: 数据的分区;
  • type: 数据查找的类型;
  1. all: 全表扫描,一般这种的具有最大的优化空间;
  2. range: 基于索引的扫描;
  • possible keys: 可能用到的索引;
  • key: 实际用到的索引;
  • key_len: 索引长度;
  • **row:**数据要最少检索几行才能得到所有结果;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值