索引优化分析

性能下降,SQL慢、执行时间长、等待时间长

  • 数据过多——分库分表
  • 关联太多的表,太多join——SQL优化
  • 没有充分利用到索引 ——索引建立
  • 服务器调优及各个参数设置——调整my.cnf

其中优化手段“建立索引”最快捷也最常用。

预热—常见通用的join查询

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xZtVJ9KX-1627788034664)(D:\QianFeng\博客\join的七种链接方式.png)]

其中:union关键字在使用时,两个结果的字段相等、字段数相等、字段顺序一致。

union allunion的区别在于去重union会去重。

select a.*,b.* from t_emp a
left join t_dept b on a.deptid = b.id
where b.id is null
union
select a.*,b.* from t_dept b
left join t_emp a on a.deptid = b.id
where a.id is null;
-- 查询a表独有和b表独有的数据

mysql 单表瓶颈500w

索引简介

索引(Index)是帮助MySQL高效获取数据的数据结构。

索引的本质:索引是数据结构

可将索引理解为"排好序的快速查找数据结构"。

数据库系统维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用数据,这样就可以在这些数据结构上实现高级查找算法。这些数据结构就是索引。

索引的存放位置:一般来说,索引本身也很大,不可能全部存储在内存中,因此,索引往往以索引文件的形式存储在磁盘中。

索引的优势:

  • 提高数据检索的效率,降低数据库的IO成本;
  • 通过索引对数据进行排序,降低数据排序的成本,减少CPU的消耗。

索引的劣势:

  • 在提高查询速率的同时,降低了表更新的速度。因在更新表时,MySQL不仅保存表数据,还需保存索引文件每次添加的索引列字段
  • 实际上索引也是一张表,该表保存了主键和索引字段,并指向实体表的记录,所以索引也需占用空间。

索引的结构:

B_tree 平衡树

  • Btree

    1. 非叶子节点包含

      1. 索引指向的数据
      2. 向下的指针
      3. 指向数据的指针
  • B+tree
    • 非叶子节点不包含索引指向的数据

MySQL选择B+tree作为索引,相对有限的内存中,B+tree的占用空间要比Btree小三分之一,相对发生IO的次数更少,时间更短。

时间复杂度

同一问题可用不同的算法解决,而一个算法的质量优劣将影响到算法及程序的执行效率。算法分析的目的在于选择合适的算法和改进算法。

O(n) 时间复杂度 算法随着数量级n的增加在时间维度上的复杂程度。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MciZf6g7-1627788034670)(D:\QianFeng\博客\Mysql_学习记录\image-20210615215759545.png)]

聚簇索引和非聚簇索引

聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。

“聚簇”表示数据行和相邻的间值聚簇存储在一起。

只有主键索引是聚簇索引,即按照顺序排列好的索引。

除了主键索引,其余建立的索引都是非聚簇索引,特点:非聚簇索引要对所有索引进行查找。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-exstmr40-1627788034673)(image-20210615221121122.png)]

mysql索引分类

单值索引

​ 即一个索引只包含单个列,一个表可以有多个单列索引

create table
customer(id int(10) unsigned auto_increment,customer_no varchar(200),customer_name varchar(200),primary key(id),key(customer_name));
-- key(customer_name) 随着表的创建,同时创建索引

唯一索引

​ 索引列的值必须必须唯一,但允许有空值

主键索引

​ 设定为主键后数据库会自动建立索引,Innodb 为聚簇索引

复合索引

​ 即一个索引包含多个列。针对多个字段创建一个索引

create index idx_age_deptid_name on t_emp(age,deptid,name)

​ 通过符合索引查询的结果为复合索引内的n条数据,即复合索引包含几条字段就返回几条字段的查询结果。

基本语法

  • 创建 create [unique] index [indexName] on table_name(column)

    • 创建单值索引

      给表t_emp表中的name字段创建索引:

      create index idx_name on t_emp(name)

    • 唯一索引的创建

      在mysql中,随着主键的创立会自动生成索引,所以对于表中其他字段数据集唯一的字段可以设置唯一索引

      为员工表中员工编号字段创建唯一索引

      create unique index idx_empno in temp(emp_no)

    • 复合索引

  • 删除 drop index [indexName] on mytable;

  • 查看 show index from table_name\G

  • 使用alter命令(一般情况使用create就足够了)

    -- 四种方式来添加数据表的索引alter table tbl_name add primary key(column_list);
    -- 该语句添加一个主键,意味着索引值必须唯一且不为空alter table tbl_name add unique index_name(column_list);
    -- 这条语句创建索引的值必须是唯一的(除了Null外,Null可能会出现多次alter table tbl_name add index index_name(column_list);
    -- 添加普通索引,索引值可出现多次alter table tbl_name add fulltext index_name(column_list);
    -- 该语句指定是索引为fulltext,用于全文索引
    

什么情况下需要创建索引

  • 主键自动创建唯一索引;;
  • 频繁作为查询条件的字段应该创建索引;
  • 查询中与其它表关联的字段,外键关系建立索引;
  • 单键/组合索引的选择问题,组合索引的性价比更高;
  • 查询中排序的字段,排序字段若通过索引去访问将大大提升排序速度;
  • 查询中统计或分组字段 ,
    • group by 相较于order by 更伤性能,因为group by中包含order by先排序后分组。

那些情况不许创建索引

  • 表记录太少
  • 经常增删改查的表或字段
  • where条件里用不到的字段不需要创建索引
  • 过滤性不好的不适合创建索引

衡量是否因该建索引,怎么建立索引的“尺子”

Explain 就是mysql提供给使用者的“尺子”

一、Explain是什么(查看执行计划)

执行计划:在MySQL逻辑架构中optimizer(优化器)在不改变查询结果的情况下调整sql执行顺序,生成执行计划。

使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈。

二、Explain能干什么?

三、Explain怎么用

EXPLAIN sql查询语句

Explain sql语句 返回对sql语句的分析情况。

执行计划包含的信息(关键的):

  1. id

    • select 查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序
    • 三种id情况:
      • id号相同:执行顺序由上到下(所显示分析情况表)
      • id不相同:如果是子查询,id的序号会递增,id越大优先级越高,越先被执行;
      • id列中id既有相同又有不同时:先按id不同,再按id相同进行优先级划分
    • 关注点:id号每个号码,表示一趟独立的查询,一个sql的查询趟数越少越好。(相同号码代表一趟查询)
  2. type

    显示查询使用了何种类型。

    • 从最好到最差:

      system>const>eq_ref>ref>range>index>ALL

      • all:全表扫描、效率极低(当type字段中出现此关键词,就可对其进行索引创建)
      • index:覆盖索引,出现index 时sql使用了索引但是没有通过索引进行过滤,一般是使用了覆盖索引或者是利用索引进行了排序分组;(需要进行优化)
      • range:只检索给定范围的行,使用一个索引来选择行。key列显示使用了那个索引。一般就是在你的where语句中出现了between、<、>、in等的查询语句,这种范围扫描索引扫描比全表扫描要好,因为它只需要开始于索引的某一点,而结束于另一个点,不会涉及到扫描全部索引

思考题:如何向标中填入大量数据

  1. 一条语句插入多行数据

  2. 索引的优缺点

    1. 优点:查询排序快
    2. 缺点:所有的写操作变慢

    所以通过将表中除主键索引外的其他索引全部删除,可加快插入速度

  3. 关闭事务的自动提交,手动提交事务,一次完成多条数据插入

  4. 多线程插入数据,实现优化。

查询优化

批量数据脚本

  • 向表中插入50w数据

    1. 建表
    CREATE TABEL 'dept'('id' INT(11) NOT NULL AUTO_INCREMENT,'deptName' VARCHAR(30) DEFAULT NULL,'address' VARCHAR(30) DEFAULT NULL,'ceo' INT NULL,PRIMARY KEY('id')
    )ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;CREATE TABLE 'emp'('id' INT(11) NOT NULL AUTO_INCREMENT,'empno' INT NOT NULL,'name' VARCHAR(20) DEFAULT NULL,'age' INT(3) DEFAULT NULL,'deptid' INT(11) DEFAULT NULL,PRIMARY KEY('id')
    )ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
    1. 设置参数 log_bin_trust_function_creators

      查看参数是否开启:SHOW VARTABLES LIKE 'log_bin_trust_function_creators'

      log_bin :是mysql 的二进制日志,实现MySQL主从复制时使用的,MySQL默认为关闭状态。

      将参数打开:SET GLOBAL log_bin_trust_function_creators=1

      其中关于“global”,如果不填加,那么该参数开启只在当前窗口有效;如果添加,整体所有窗口都有效。

    2. 创建函数,保证每条数据都不同

      # 随机产生字符串
      DELIMITER $$
      # delimiter 修改结束符
      CREATE FUNCTION rand_string(n INT) RETURNS VARCHAR(255)
      BEGIN
      DECLARE chars_str VARCHAR(100) DEFAULT
      'abcdefghijklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ';
      DECLARE return_str VARCHAR(255) DEFAULT;
      DECLARE i INT DEFAULT 0;
      WHILE i<N DO
      SET return_str=CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*52),1));
      SET i=i+1;
      END WHILE;
      RETURN return_str;
      END$$# 加入要删除
      # drop function rand_string;# 随机产生部门编号
      DELIMITER $$
      CREATE FUNCTION rand_num(from_num INT,to_num INT) RETURNS INT(11)
      BEGIN
      DECLARE i INT DEFAULT 0;
      SET i=FLOOR(from_num+RAND()*(to_num - from_num + 1));
      RETURN I;
      END$$
      # 假如要删除
      # drop function rand_num;

      delimiter修改结束符,需要用到MySQL编程函数,所以修改结束符,以方便MySQL编程的进行。

    3. 创建存储过程

      批量生成数据、导数、数据的操作

      • 创建往emp表中插入数据的存储过程

        DELIMITER $$
        CREATE PROCEDURE insert_emp(START INT,max_NUM INT)
        BEGIN
        DECLARE i INT DEFAULT 0;
        #set autocommit = 0 把autocommit设置为0
        SEET autocommit=0
        REPEAT
        SET i=i+1;
        INSERT INTO emp(empno,NAME,age,deptid)
        VALUES((START+i),rand_string(6),rand_num(30,50),rand_num(1,10000)       );
        UNTIL i = max_num
        END REPEAT;
        COMMIT;
        END$$
        

        PROCEDURE存储过程

        SEET autocommit=0自动提交=0,将自动提交关闭

      • 创建往dept标中插入数据的存储过程

        同理编写部门表的存储过程

        # 执行存储过程,向dept 表中添加随机数据
        DELIMITER $$
        CREATE PROCEDURE 'insert_dept'(max_num INT)
        BEGIN
        DECLARE i INT DEFAUL 0;
        SET autocommit=0;
        REPEAT
        SET i=i+1;
        INSERT INTO dept(deptname,address,ceo)
        VALUES(rand_string(8),rand_string(10),rand_num(1,500000)
        );
        UNTIL i=max_num
        END REPEAT;
        COMMIT;
        END$$
        
    4. 调用存储过程

      # 执行存储过程,向dept表中添加一万条数据
      DELIMITER ;
      CALL inster_dept(10000);# 向emp表中添加50万条数据
      CALL inster_emp(100000,50000);
      

前面一直在提到,通过创建索引能够更快速的从大数据标中完成查询操作,然而在工作中我们会针对一条sql创建多个索引,那么问题就出现了,由于多个索引的存在,我们只有将索引删除掉,才能够保障下一条sql的正常执行。

删除多条索引

删除索引前,我们必须先要知道具体需要删除的索引是哪些,然后进行删除。

  1. 查询索引名

    SHOW INDEX FROM table_name,但show仅是展现,无法从中提取出来。

    在MySQL数据库中有一张表存储索引信息,在information_schema元数据(描述数据的数据)库中保存,STATISTICS 统计表中存储。STATISTICS表中存储着索引名称INDEX_NAME和索引对应的表名TABLE_NAME和库名TABLE_SCHEMA、索引的序列SEQ_IN_INDEX等字段。

    注:在删除索引时要注意,主键索引不可以删除;对于复合索引删除,索引序列为1的即可

    由上所述,我们就可以查询到想要删除t_emp表的索引的语句:

    SELECT index_name FROM information_schema.STATISTICS WHERE table_name='t_emp' AND table_shema='mydb' AND index_name <> 'PRIMARY' AND seq_in_index = 1;

  2. 取出索引名-字符串

    通过游标对象来提取第一步查询出来的索引

    CURSOR 游标
    FETCH xxx INTO xxx
    
  3. 拼接索引名的drop语句是字符串类型 如何将字符串转变为sql

    预编译prepare 预编译 xxx EXECUTE

# 实现批量删除索引的存储过程
DELIMITER $$
CREATE PROCEDURE 'proc_drop_index'(dbname VARCHAR(200),tablename VARCHAR(200))
BEGINDECLARE done INT DEFAULT 0;DECLARE ct INT DEFAULT 0;DECLARE _index VARCHAR(200) DEFAULT *;DECLARE _cur CURSOR FOR SELECT index_name FROM  information_schema.STATISTICS WHERE table_name='t_emp' AND table_shema='mydb' AND index_name <> 'PRIMARY' AND seq_in_index = 1;DECLARE CONTINUE HANDLER FOR NOT FOUND set done=2;OPEN _cur;FETCH _cre INTO _index;WHILE _index<>"DOSET @str=CONCAT("drop index",_index,"on",tablename);PREPARE sql_str FROM @str;EXECUTE sql_str;DEALLOCATE PREPARE sql_str;SET _index=";FETCH _cur INTO _index;END WHILE;
CLOSE _cur;
END$$
# 执行存储过程
CALL proc_drop_index("dbname","tablename");

2.MySQL索引优化相关推荐

  1. MySQL第12天:MySQL索引优化分析之性能优化案例实践

    MySQL索引优化分析之性能优化案例实践 执行计划中各select_type含义可以看:MySQL第11天:MySQL索引优化分析之性能分析 https://weibo01.blog.csdn.net ...

  2. MySQL第11天:MySQL索引优化分析之性能分析

    MySQL索引优化分析之性能分析 一.MySQL Query Optimizer 二.MySQL常见瓶颈 三.Explain(执行计划) 1.什么是执行计划?          2.执行计划能干什么? ...

  3. MySQL第10天:MySQL索引优化分析之索引介绍

    MySQL索引优化分析之索引简介 1.索引是什么? 2.索引优势.劣势 3.索引分类.基本语法 4.索引结构 5.哪些情况需要创建索引? 6.哪些情况不需要创建索引? ---------------- ...

  4. MySQL第9天:MySQL索引优化分析之join查询

    MySQL索引优化分析之join查询 #编写时间:2017.3.12 #编写地点:广州 常见join查询: 1.SQL执行顺序:手写.机读.总结 (1)手写 (2)机读 (3)总结 2.join图 3 ...

  5. MySQL第8天:MySQL索引优化分析之SQL慢

    MySQL索引优化分析之SQL慢 #编写时间:2017.3.11 #编写地点:广州 性能下降SQL慢,执行时间长,等待时间长的原因有: (1)查询语句写的不合理 (2)索引失效:单值索引.符合索引 ( ...

  6. 讲真,MySQL索引优化看这篇文章就够了

    本文主要讨论MySQL索引的部分知识.将会从MySQL索引基础.索引优化实战和数据库索引背后的数据结构三部分相关内容,下面一一展开. 一.MySQL--索引基础 首先,我们将从索引基础开始介绍一下什么 ...

  7. MySQL索引优化分析

    转载来源:https://www.cnblogs.com/itdragon/p/8146439.html MySQL索引优化分析 为什么你写的sql查询慢?为什么你建的索引常失效?通过本章内容,你将学 ...

  8. mysql物理删除索引_mysql创建索引,mysql索引优化,mysql索引创建删除

    mysql创建索引,mysql索引优化,mysql索引创建删除 ================================ ©Copyright 蕃薯耀 2020-11-23 http://fa ...

  9. MySQL索引优化是什么意思?底层原理是什么?

    MySQL索引优化是指通过对MySQL数据库中的索引进行优化,提高查询性能和效率的过程.索引是一种数据库对象,它可以提高查询数据的速度,通过创建索引可以使得查询操作更快速.更高效. 底层原理是:MyS ...

  10. mysql索引优化有几种_mysql索引优化

    索引类型 从物理存储角度上,索引可以分为聚集索引和非聚集索引. 1.聚集索引(Clustered Index) 聚集索引决定数据在磁盘上的物理排序,一个表只能有一个聚集索引. 2.非聚集索引(Non- ...

最新文章

  1. mac启动本地redis_通过 Laravel Sail 构建基于 Docker 的本地开发环境
  2. 中国芯片研究再获国际顶会最佳论文提名!清华魏少军、刘雷波团队出品
  3. python提供的默认的构造方法是什么_Python面试常见问题,__init__是构造函数吗?...
  4. mysql数据库用hs_MySQL数据库安装步骤
  5. Linux上的TIME_WAIT和tcp_fin_timeout
  6. Verilog HDL中容易生成锁存器的两种情况
  7. python学习之最常用的内置函数
  8. 【jQuery笔记Part1】07-jQuery操作css-添加删除切换类、开关灯泡案例
  9. 设计模式17_命令模式
  10. XPO学习(3)----数据查询
  11. 理解storm的ACKER机制原理
  12. 字符串的HashCode可能相同
  13. iOS开发之UIAlertController的适配
  14. 备忘: Visual Studio 2013 VC++ IDE 使用小贴示。
  15. Modscan和Modsim 两种Modbus调试工具使用说明
  16. lorawan服务器通信协议,LoRaWAN协议(三)–Server端数据协议
  17. nmap快速扫描大量主机端口方法
  18. [MySQL系列] 使用STRAIGHT_JOIN 优化inner join查询排序索引问题
  19. ClipCap: CLIP Prefix for Image Captioning
  20. Android之UI学习篇二:TextVeiw显示表情和跑马灯效果

热门文章

  1. 为什么要做网站备案?
  2. 50个Java精品源码免积分下载
  3. 最全Java项目合集(附源码课件),可完美运行
  4. 60GHz通信标准简介
  5. Elasticsearch的节点与分片
  6. kubernetes文档翻译
  7. 计算机硬盘sata,sata硬盘是什么
  8. 存量时代,汽车4S店要通过什么服务来吸引消费者
  9. 旅游攻略小程序毕业设计毕设作品开题报告答辩PPT
  10. 淘宝图片上传,拍立淘接口