第10章_索引优化与查询优化(覆盖索引, 索引下推等)

**4.**子查询优化

MySQL 从 4.1 版本开始支持子查询,使用子查询可以进行 SELECT 语句的嵌套查询,即一个 SELECT 查询的结果作为另一个SELECT 语句的条件。 子查询可以一次性完成很多逻辑上需要多个步骤才能完成的 SQL 操作 。
子查询是 MySQL 的一项重要的功能,可以帮助我们通过一个 SQL 语句实现比较复杂的查询。但是,子 查询的执行效率不高。 原因:
① 执行子查询时, MySQL 需要为内层查询语句的查询结果 建立一个临时表 ,然后外层查询语句从临时表中查询记录。查询完毕后,再 撤销这些临时表 。这样会消耗过多的 CPU 和 IO 资源,产生大量的慢查询。
② 子查询的结果集存储的临时表,不论是内存临时表还是磁盘临时表都 不会存在索引 ,所以查询性能会受到一定的影响。
③ 对于返回结果集比较大的子查询,其对查询性能的影响也就越大。
MySQL 中,可以使用连接( JOIN )查询来替代子查询。 连接查询 不需要建立临时表 ,其 速度比子查询要快 ,如果查询中使用索引的话,性能就会更好。

结论:尽量不要使用NOT IN 或者 NOT EXISTS,用LEFT JOIN xxx ON xx WHERE xx IS NULL替代

8.优先考虑覆盖索引

8.1****什么是覆盖索引?

理解方式一 :索引是高效找到行的一个方法,但是一般数据库也能使用索引找到一个列的数据,因此它不必读取整个行。毕竟索引叶子节点存储了它们索引的数据;当能通过读取索引就可以得到想要的数据,那就不需要读取行了。 一个索引包含了满足查询结果的数据就叫做覆盖索引。
理解方式二 :非聚簇复合索引的一种形式,它包括在查询里的 SELECT 、 JOIN 和 WHERE 子句用到的所有列 (即建索引的字段正好是覆盖查询条件中所涉及的字段)。
简单说就是, 索引列 + 主键 包含 SELECT 到 FROM 之间查询的列 。

8.2****覆盖索引的利弊

好处:
1. 避免 Innodb 表进行索引的二次查询(回表)
2. 可以把随机 IO 变成顺序 IO 加快查询效率
弊端:
索引字段的维护 总是有代价的。因此,在建立冗余索引来支持覆盖索引时就需要权衡考虑了。这是业务 DBA,或者称为业务数据架构师的工作。

10. 使用****索引下推

Index Condition Pushdown(ICP) 是 MySQL 5.6 中新特性,是一种在存储引擎层使用索引过滤数据的一种优化方式。ICP 可以减少存储引擎访问基表的次数以及 MySQL 服务器访问存储引擎的次数。

10.1****使用前后的扫描过程对比

在不使用 ICP 索引扫描的过程:
storage 层:只将满足 index key 条件的索引记录对应的整行记录取出,返回给 server 层
server 层:对返回的数据,使用后面的 where 条件过滤,直至返回最后一行。

server层在生成执行计划后, 按如下步骤执行查询:

  1. server层首先调用存储引擎的接口进行读数据(read data)==>定位到满足条件的第一条二级索引记录(Read index)
  2. 根据B+树索引快速定位到这条二级索引记录后, 根据二级索引记录的主键值进行回表操作(get records),将完整的用户记录返回给存储引擎(Load data), 将完整记录返回给server层
  3. server层再根据using where 判断其他搜索条件是否成立, 如果成立则将其发送给其他客户端; 否则向存储引擎要下一条数据
  4. 由于每条记录都有next_record 属性, 根据该属性定位下一条符合条件的二级索引记录
    下图即Using prefix index to get records过程

    使用 ICP 扫描的过程:
    storage 层:
    首先将 index key 条件满足的索引记录区间确定,然后在索引上使用 index filter对每条记录 进行过滤。将满足的 index filter条件的索引记录才去回表取出整行记录返回 server 层。不满足 index filter 条件的索引记录丢弃,不回表、也不会返回server 层, 之后判断下一条数据。
    server 层:
    对返回的数据,使用 table filter 条件做最后的过滤。

    server层在生成执行计划后, 按如下步骤执行查询:
  5. server层首先调用存储引擎的接口进行读数据(read data)==>定位到满足条件的第一条二级索引记录(Read index)
  6. 根据B+树索引快速定位到这条二级索引记录后, 先不进行回表操作(get records),而是 先判断一下所有关于索引中包含的列的条件( 就是假如使用的是联合索引, 而其他条件所在列恰好也在联合索引内)是否成立(Using index condition), 如果不成立, 直接跳过不再回表, 如果成立, 正常回表并将完整的用户记录返回给存储引擎(Load data), 将完整记录返回给server层
  7. server层再判断其他搜索条件( 不在联合索引内,如果有这样的条件还要加上using where)是否成立, 如果成立则将其发送给其他客户端; 否则向存储引擎要下一条数据
  8. 由于每条记录都有next_record 属性, 根据该属性定位下一条符合条件的二级索引记录, 并继续上述操作
    下图即 Using index condition 操作


使用前后的成本差别
使用前,存储层多返回了需要被 index filter 过滤掉的整行记录
使用 ICP 后,直接就去掉了不满足 index filter 条件的记录,省去了他们回表和传递到 server 层的成本。
ICP 的 加速效果 取决于在存储引擎内通过 ICP 筛选 掉的数据的比例。

10.2 ICP****的使用条件

ICP 的使用条件:
① 只能用于二级索引 (secondary index) 毕竟一级索引也不需要回表
② explain 显示的执行计划中 type 值( join 类型)为 range 、 ref 、 eq_ref 或者 ref_or_null 。
③ 并非全部 where 条件都可以用 ICP 筛选,如果 where 条件的字段不在索引列中,还是要读取整表的记录到server 端做 where 过滤。
④ ICP 可以用于 MyISAM 和 InnnoDB 存储引擎
⑤ MySQL 5.6 版本的不支持分区表的 ICP 功能, 5.7 版本的开始支持。
⑥ 当 SQL 使用覆盖索引时,不支持 ICP 优化方法。

10.3 ICP****使用案例

**12.**其它查询优化策略

12.1 EXISTSIN****的区分

问题:
不太理解哪种情况下应该使用 EXISTS,哪种情况应该用 IN。选择的标准是看能否使用表的索引吗?
这两条语句有一些区别 : 上面的是不相关子查询, 需要从内部查出数据给外边用
: 下面的是相关子查询, 需要从外部传入数据给内部用

**12.2 COUNT(*)COUNT(具体字段)**效率

面试经常问
问:在 MySQL 中统计数据表的行数,可以使用三种方式: SELECT COUNT(*) 、 SELECT COUNT(1) 和 SELECT COUNT(具体字段 ) ,使用这三者之间的查询效率是怎样的?

12.3关于SELECT(*)

在表查询中,建议明确字段,不要使用 * 作为查询的字段列表,推荐使用 SELECT < 字段列表 > 查询。原因:
① MySQL 在解析的过程中,会通过 查询数据字典 将 "*" 按序转换成所有列名,这会大大的耗费资源和时
间。
② 无法使用 覆盖索引

12.5多使用COMMIT

只要有可能,在程序中尽量多使用 COMMIT ,这样程序的性能得到提高,需求也会因为 COMMIT 所释放的资源而减少。
COMMIT 所释放的资源:
回滚段上用于恢复数据的信息
被程序语句获得的锁
redo / undo log buffer 中的空间
管理上述 3 种资源中的内部花费

3 join****语句原理

我碰见题时候再来补充

4. 排序优化

同上

相关推荐
.Eyes1 小时前
OceanBase 分区裁剪(Partition Pruning)原理解读
数据库·oceanbase
MrZhangBaby2 小时前
SQL-leetcode— 2356. 每位教师所教授的科目种类的数量
数据库
一水鉴天2 小时前
整体设计 之定稿 “凝聚式中心点”原型 --整除:智能合约和DBMS的在表层挂接 能/所 依据的深层套接 之2
数据库·人工智能·智能合约
翔云1234563 小时前
Python 中 SQLAlchemy 和 MySQLdb 的关系
数据库·python·mysql
孙霸天3 小时前
Ubuntu20系统上离线安装MongoDB
数据库·mongodb·ubuntu·备份还原
Java 码农3 小时前
nodejs mongodb基础
数据库·mongodb·node.js
TDengine (老段)3 小时前
TDengine IDMP 运维指南(4. 使用 Docker 部署)
运维·数据库·物联网·docker·时序数据库·tdengine·涛思数据
TDengine (老段)3 小时前
TDengine IDMP 最佳实践
大数据·数据库·物联网·ai·时序数据库·tdengine·涛思数据
彬彬醤4 小时前
Mac怎么连接VPS?可以参考这几种方法
大数据·运维·服务器·数据库·线性代数·macos·矩阵
废喵喵呜4 小时前
达梦数据库-实时主备集群部署详解(附图文)手工搭建一主一备数据守护集群DW
网络·数据库·tcp/ip