MySQL高级---第二部分【索引优化】

    xiaoxiao2025-02-11  19

    ---分析--- 1.观察一天,看看生产的慢SQL情况; 2.开启慢查询日志,设置阈值,必读超过5秒就是 慢SQL,并将它抓取出来; 3.ecplain+慢SQL分析 4.show profile 5.运维经理or DBA,进行SQL数据库服务器的参数调优

    ==总结 1.慢查询的开启并捕获 2.explain+慢SQL分析 3.show profile查询SQL在MYSQL服务器里面的执行细节和生命周期 4.SQL数据库服务器的参数调优。

    3.5 索引优化

    3.5.1 单表查询优化

    1.建表

    2. 实例

    #查询 category_id 为1 且  comments 大于 1 的情况下,views 最多的 article_id。 

    #结论:很显然,type 是 ALL,即最坏的情况。Extra 里还出现了 Using filesort,也是最坏的情况。优化是必须的。 #开始优化: # 1.1 新建索引+删除索引

    create index idx_article_ccv on article(category_id,comments,views);

    # 1.2 第2次EXPLAIN

    #结论: #type 变成了 range,这是可以忍受的。但是 extra 里使用 Using filesort 仍是无法接受的。 #但是我们已经建立了索引,为啥没用呢? #这是因为按照 BTree 索引的工作原理, # 先排序 category_id, # 如果遇到相同的 category_id 则再排序 comments,如果遇到相同的 comments 则再排序 views。 #当 comments 字段在联合索引里处于中间位置时, #因comments > 1 条件是一个范围值(所谓 range), #MySQL 无法利用索引再对后面的 views 部分进行检索,即 range 类型查询字段后面的索引无效。

    # 1.3 删除第一次建立的索引 DROP INDEX idx_article_ccv ON article;  # 1.4 第2次新建索引 #ALTER TABLE `article` ADD INDEX idx_article_cv ( `category_id` , `views` ) ; create index idx_article_cv on article(category_id,views);

    # 1.5 第3次EXPLAIN

    #结论:可以看到,type 变为了 ref,Extra 中的 Using filesort 也消失了,结果非常理想。 DROP INDEX idx_article_cv ON article;

    3.5.2 双表查询优化

    1.建表

    2.案例:

    # 下面开始explain分析

    #结论:type 有All # 添加索引优化 ALTER TABLE `book` ADD INDEX Y ( `card`); # 第2次explain EXPLAIN SELECT * FROM class LEFT JOIN book ON class.card = book.card;

    #可以看到第二行的 type 变为了 ref,rows 也变成了优化比较明显。#这是由左连接特性决定的。LEFT JOIN 条件用于确定如何从右表搜索行,左边一定都有, #所以右边是我们的关键点,一定需要建立索引。

    建立一个右表索引 # 删除旧索引 + 新建 + 第3次explain DROP INDEX Y ON book; ALTER TABLE class ADD INDEX X (card);

    建议:

    1、保证被驱动表的join字段已经被索引。被驱动表  join 后的表为被驱动表  (需要被查询)

    2、left join 时,选择小表作为驱动表,大表作为被驱动表。但是 left join 时一定是左边是驱动表,右边是被驱动表

    3、inner join 时,mysql会自己帮你把小结果集的表选为驱动表。mysql 自动选择。小表作为驱动表。因为 驱动表无论如何都会被全表扫描?。所以扫描次数越少越好

    4、子查询尽量不要放在被驱动表,有可能使用不到索引。若必须用到子查询,可将子查询设置为驱动表,,因为驱动表的type 肯定是 all,而子查询返回的结果表没有索引,必定也是all。

    5、 左连接建在右表,右连接建在左表。

    6.、索引最好设置早要经常查询的字段中

    7.优先优化内层循环

    3.5.3 案例(索引失效)

    若一个字段上有多种索引呢?某一索引失效,可以继续使用其他索引不影响。

    建表

    1. 全值匹配我最爱

    索引  idx_staffs_nameAgePos 建立索引时 以 name , age ,pos 的顺序建立的。全值匹配表示 按顺序匹配的

    2.最佳左前缀法则

    如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列。

     and 忽略左右关系。既即使没有没有按顺序 由于优化器的存在,会自动优化。 经过试验结论  建立了 idx_nameAge 索引  id 为主键     1.当使用覆盖索引的方式时,(select name/age/id from staffs where age=10 (后面没有其他没有索引的字段条件)),即使不是以 name 开头,也会使用 idx_nameAge 索引。     既 select 后的字段 有索引,where 后的字段也有索引,则无关执行顺序。     2.除开上述条件 才满足最左前缀法则。

    3、不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描

    4.、存储引擎不能使用索引中范围条件右边的列

     范围 若有索引则能使用到索引,范围条件右边的索引会失效(范围条件右边与范围条件使用的同一个组合索引,右边的才会失效。若是不同索引则不会失效)

    5、尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select *

    6、mysql 在使用不等于(!= 或者<>)的时候无法使用索引会导致全表扫描

    索引  idx_nameAgeJob          idx_name 使用 != 和 <> 的字段索引失效( != 针对数值类型。 <> 针对字符类型 前提 where and 后的字段在混合索引中的位置比比当前字段靠后  where age != 10 and name='xxx'  ,这种情况下,mysql自动优化,将 name='xxx' 放在 age !=10 之前,name 依然能使用索引。只是 age 的索引失效)

    7、is not null 也无法使用索引,但是is null是可以使用索引的

    8、like以通配符开头('

    转载请注明原文地址: https://yun.8miu.com/read-135691.html
    最新回复(0)