MYSQL 索引下推 45讲

刘老师群里,看到一位小友 问<MYSQL 45讲>林晓斌的回答
大意是一个组合索引 (a,b,c) 条件 a > 5 and a <10 and b='123', 这样的情况下是如何?
林老师给的回答是 A>5  ,然后下推B='123'

小友 问 "为什么不是先 进行范围查询,然后在索引下推 b='123'?"
然后就没有然后了....


说真的,不是我有意踩林老师, 我只是说<MYSQL 45 讲>吃个半饱, 大脑半醒半睡,好比晚上2点睡,早上被8点闹钟催醒. 上午在公司里梦游状态样.

极客这种课程,视乎给人感觉不全面,不细致.相对于等同价格的书来说,性价比太低了.

以前买了一本ORACLE ACE写的一本MYSQL入门的书.书中把BINLOG CACHE 归类于共享内存. 
高鹏(八怪)说BINLOG CAHCE是线程的内存. 
ACE 看来就是个荣誉技术编辑&总编. 

MYSQL 产生大量数据的过程

我们做个实验,用上面链接的表和数据!

添加个组合索引

KEY `idx_age_income_education` (`age`,`income_year`,`top_education`)

我们还是先讲下索引下推是什么鬼?
在很早很早以前 MYSQL 分为一阴一阳两面.  SERVER层负责阳的一面,引擎层负责阴的一面.

在这里我们记住一点就是服务层server负责过虑结果集, 只要执行计划有WHERE字眼,说明服务层执行了过滤操作, 另外ROW+FILER % 也可以窥爱一下.

引擎层返回服务层要的数据! 一个SQL有多个WHERE 条件,我们看哪个条件能命中引擎层的二级索引. 我们就把这个条件传给引擎层.引擎层通过这个条件筛选数据,然后返回,服务层再用剩余的条件,进一步筛选过滤(FILTER)记录,积累到NET_BUF满后就发生给客户.

引擎层一般会预读,大约是100条件记录,然后一条,一条给服务层,服务层判断一条记录,再问引擎要一条.

上面一般过程,不必牢记! 重点是 为什么不把服务层过滤条件,全拿到引擎层做呢?  其实都是内存操作,在引擎层还是服务层差距不大.

那为什么要ICP呢?  所以重点是索引, 是服务层把更多的条件,下推到索引上.是引擎上的二级索引.

通过索引过滤掉更多不符合条件的记录. 这样减少去读聚集索引!

一般二级索引都被内存缓存,聚集索引相对较大,不易缓存在内存里.读聚集索引可能要发生IO操作. 能通过ICP优化,能更多减少不必要的IO操作!

MYSQL 专业叫法是 读聚集索引, ORACLE 叫法是 回表!  回表和读聚集索引功能是类似的, 回表操作是直接从索引获得物理ID,直接定位到表具体行.而MYSQL读二级索引获得逻辑ID,还要通过主键聚集索引,根节点,分支节点,再到页节点,多了两次IO操作. 每个逻辑ID都要多两次IO操作. 比回表多了很多次IO操作.再说MYSQL是16K一个页,ORACLE是8K一个页. 优化思路是一样的,实现细节是有区别的. 算法一样,数据结构不一样. 作为MYSQL DBA. 如果还有OCP,COM,ACE头衔,自然不能说"回表",太LOW!

MySQL服务层负责SQL语法解析、生成执行计划等,并调用存储引擎层去执行数据的存储和检索。

索引下推下推其实就是指将部分上层(服务层)负责的事情,交给了下层(引擎层)去处理。

我们来具体看一下,在没有使用ICP的情况下,MySQL的查询:

  • 存储引擎读取索引记录;

  • 根据索引中的主键值,定位并读取完整的行记录;

  • 存储引擎把记录交给Server层去检测该记录是否满足WHERE条件。

使用ICP的情况下,查询过程:

  • 存储引擎读取索引记录(不是完整的行记录);

  • 判断WHERE条件部分能否用索引中的列来做检查,条件不满足,则处理下一行索引记录;

  • 条件满足,使用索引中的主键去定位并读取完整的行记录(就是所谓的回表);

  • 存储引擎把记录交给Server层,Server层检测该记录是否满足WHERE条件的其余部分。

我们还可以看一下执行计划,
看到Extra一列里Using index condition,这就是用到了索引下推。

  • 只能用于range、 ref、 eq_refref_or_null访问方法;

  • 只能用于InnoDB和 MyISAM存储引擎及其分区表;

  • InnoDB存储引擎来说,索引下推只适用于二级索引(也叫辅助索引);

我们使用下面SQL 看下执行计划 根据上面说只要EXTAR using index condition 使用索引条件 这英文取得让人误会. 为啥不多加个单词"using index pushdown condition "

select * from dba_test.personal_identity_info where  age > 35  and income_year > 10000 and   income_year < 20000  and top_education='大学' ; 
-- NO ICP key_len=10 rows=75 filtered=8.28 Extra=Using where select * from dba_test.personal_identity_info where  age >= 35 and age <= 65; 
-- ICP  key_len=1 rows=206 filtered=100 Extra=Using index condition  select * from dba_test.personal_identity_info where  age > 35 and age < 65; 
-- ICP  key_len=1 rows=196 filtered=100 Extra=Using index condition select * from dba_test.personal_identity_info where  age > 35 and age < 65 and top_education='大学'; 
-- NO ICP key_len=10 rows=75 filtered=19.6 Extra=Using where select * from dba_test.personal_identity_info where  age > 35 and age < 65  and income_year > 10000 ; 
-- ICP  key_len=1 rows=196 filtered=33.33 Extra=Using index conditionselect * from dba_test.personal_identity_info where  age >= 35 and age <= 65  and income_year > 10000; 
-- ICP  key_len=6 rows=206 filtered=33.33 Extra=Using index conditionselect * from dba_test.personal_identity_info where  age = 35  and income_year > 10000 and  income_year < 20000  and top_education='大学' ; 
-- ICP  key_len=6 rows=1 filtered=7.50 Extra=Using index conditionselect * from dba_test.personal_identity_info where  income_year > 10000 and  income_year < 20000  and top_education='大学' ;-- NO ICP key_len=10 rows=75 filtered=11.11 Extra=Using where

从上面八种情况,或许可以推导出,只要WHERE条件命中了组合索引第一个字段.

它一定会走索引! 其它条件命中组合索引其它字段,也能走索引.

ICP条件1:WHERE条件命中索引第一个字段.

ICP条件2:WHERE其它条件能命中组合索引其它字段,不过不能有等值查询

select * from dba_test.personal_identity_info where  age >= 35 and age <= 65 and top_education='大学';
-- NO ICP key_len=10 rows=75 filtered=20.60 Extra=Using where select * from dba_test.personal_identity_info where  age between 35 and 65 and top_education='大学';
-- NO ICP key_len=10 rows=75 filtered=20.60 Extra=Using where
另外两个情况下,还是其它WHERE条件命中组合索引且等值 ICP就失效
我的MYSQL 是 8.0.24. 索引下推是开启的
select @@optimizer_switch;
/*
index_merge=on,index_merge_union=on,index_merge_sort_union=on,
index_merge_intersection=on,engine_condition_pushdown=on,
index_condition_pushdown=on,mrr=on,
mrr_cost_based=on,block_nested_loop=on,batched_key_access=off,
materialization=on,semijoin=on,
loosescan=on,firstmatch=on,duplicateweedout=on,
subquery_materialization_cost_based=on,
use_index_extensions=on,condition_fanout_filter=on,derived_merge=on,
use_invisible_indexes=off,skip_scan=on,hash_join=on,
subquery_to_derived=off,prefer_ordering_index=on,
hypergraph_optimizer=off,derived_condition_pushdown=on
*/set optimizer_switch="index_condition_pushdown=off";
set optimizer_switch="index_condition_pushdown=on";
我们还可以explain format=tree 看的更清楚

explain FORMAT=tree select * from dba_test.personal_identity_info where age > 35 and age < 65 and top_education='大学' and income_year > 10000;
/*
-> Filter: ((personal_identity_info.age > 35) and (personal_identity_info.age < 65) and (personal_identity_info.income_year > 10000))  (cost=7.24 rows=5)-> Index lookup on personal_identity_info using idx_personal_identity_info_top_education (top_education='大学')  (cost=7.24 rows=75)
*/    explain FORMAT=tree select * from dba_test.personal_identity_info where  age >= 35 and age <= 65 and top_education='大学' and income_year > 10000;
/*
-> Filter: ((personal_identity_info.age >= 35) and (personal_identity_info.age <= 65) and (personal_identity_info.income_year > 10000))  (cost=7.26 rows=5)-> Index lookup on personal_identity_info using idx_personal_identity_info_top_education (top_education='大学')  (cost=7.26 rows=75)
*/explain FORMAT=tree   select * from dba_test.personal_identity_info where  age > 35  and income_year > 10000 and   income_year < 20000  and top_education='大学' ;
/*
-> Filter: ((personal_identity_info.age > 35) and (personal_identity_info.income_year > 10000) and (personal_identity_info.income_year < 20000))  (cost=7.37 rows=6)-> Index lookup on personal_identity_info using idx_personal_identity_info_top_education (top_education='大学')  (cost=7.37 rows=75)
*/explain FORMAT=tree   select * from dba_test.personal_identity_info where  age = 35  and income_year > 10000 and  income_year < 20000  and top_education='大学' ;
/*
-> Index range scan on personal_identity_info using idx_age_income_education, with index condition: ((personal_identity_info.age = 35) and (personal_identity_info.income_year > 10000) and (personal_identity_info.income_year < 20000) and (personal_identity_info.top_education = '大学'))  (cost=0.71 rows=1)
*/explain FORMAT=tree   select * from dba_test.personal_identity_info where  age > 35 and age < 65; 
/*
-> Index range scan on personal_identity_info using idx_age_income_education, with index condition: ((personal_identity_info.age > 35) and (personal_identity_info.age < 65))  (cost=88.46 rows=196)
*/
explain FORMAT=tree  select * from dba_test.personal_identity_info where  age = 35  and income_year > 10000 ;
/*
-> Index range scan on personal_identity_info using idx_age_income_education, with index condition: ((personal_identity_info.age = 35) and (personal_identity_info.income_year > 10000))  (cost=3.86 rows=8)
*/

前三个没有下推,后三个下推了,从中可推导出,ICP可以推进多个条件.

另外 推导出

ICP条件3:WHER条件命中组合索引第一个字段且是等值也生效.

看起来条件2和条件3有点冲突,其实不冲突!

一般来说,命中索引的只有一个WHER条件.

这个经验来自ORACLE,MYSQL通过EXPLAIN FORMAT=TREE是看不出来的.

这样只能跟踪源码才可知,跟踪源码是件很累的事情,成本高收益低!

以上胡说八道

 

此刘老师,不是那个刘老师! 那个刘老师太那个了,200号人捐款4.2万.

说是他自己用个脚本换来的,然后捐给武汉.自己独占了荣誉.

也没感谢大家捐款,也没在公号列出感谢名单.培训也就是培训脚本

如何使用! 说白了就是PPT宣传你的脚本有多么多么厉害.

online脚本套用ORACLE官方脚本SQLHC.

好像 搞得大家200号人 没有良心没有善心,就冲着你的牛X脚本来的?

还搞个PDF污蔑我. 只能忽悠没有脑子的小年轻!

脚本有鸟用,谁敢把来历不明的脚本,用在生产环境中?

8千行再套用个SQLHC,我没有精力去分析代码,

早就扔在上上家公司的办公电脑里!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/26916.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

热门开源大模型项目推荐

一&#xff1a;开源大模型热门项目推荐 NNI&#xff1a;由微软发布的开源AutoML工具包&#xff0c;支持神经网络超参数调整。最新版本对机器学习生命周期的各个环节做了全面支持&#xff0c;包括特征工程、神经网络架构搜索(NAS)、超参调优和模型压缩。适用于各种机器学习项目&…

C++240613

自由发挥登录窗口的应用场景&#xff0c;实现一个登录窗口界面 要求&#xff1a;每行代码都有注释 #include "my_widget.h"My_Widget::My_Widget(QWidget *parent): QWidget(parent) {//设置窗口的标题this->setWindowTitle("真爱生命&#xff0c;远离赌博&…

2024大交通场景空间策展洞察报告

来源&#xff1a;邻汇吧&万一商管 近期历史回顾&#xff1a; 2024国内工商业储能市场研究报告.pdf 2023幸福企业白皮书.pdf 2024年欧亚地区移动经济报告.pdf 内容供应链变革 2023人工智能与首席营销官&#xff08;CMO&#xff09; AI科技对PC产业的影响.pdf 金融业数据应用…

智能合约漏洞类型

Are We There Yet? Unraveling the State-of-the-Art Smart Contract Fuzzers | Proceedings of the IEEE/ACM 46th International Conference on Software Engineering

Java求职季 必备知识脑图 收藏起来 !!!

Java初中级知识脑图 面试超实用 1.Git 下载链接 导图下载地址 &#xff1a; https://mm.edrawsoft.cn/mobile-share/index.html?uuid31d00742157057-src&share_type1 2.JUC 下载链接 https://mm.edrawsoft.cn/mobile-share/index.html?uuid6c0be457444921-src&s…

计算机网络 —— 应用层(DNS域名系统)

计算机网络 —— 应用层&#xff08;DNS域名系统&#xff09; 什么是DNS域名的层次结构域名分类 域名服务器的分类域名解析方式递归查询&#xff08;Recursive Query&#xff09;迭代查询&#xff08;Iterative Query&#xff09;域名的高速缓存 我们今天来看DNS域名系统 什么…

批量文件重命名技巧:轻松替换删除文件夹名中的字母,实现高效文件管理新境界

在数字化时代&#xff0c;我们每天都会面对大量的文件和文件夹。无论是工作文档、学习资料还是个人收藏&#xff0c;文件命名的规范性都显得尤为重要。然而&#xff0c;手动一个一个去修改文件名&#xff0c;不仅耗时耗力&#xff0c;还容易出错。那么&#xff0c;有没有一种方…

SAP ABAP 之面向对象OO

文章目录 前言一、类的理解二、如何创建ABAP类 a.类的定义与构成 b.类的访问区域 c.特殊方法 d.类的继承 三、类中参数的使用 a.IMPORTING / EXPORTING b.CHANGING c.RETURNING d.EX…

PHP杂货铺家庭在线记账理财管理系统源码

家庭在线记帐理财系统&#xff0c;让你对自己的开支了如指掌&#xff0c;图形化界面操作更简单&#xff0c;非常适合家庭理财、记账&#xff0c;系统界面简洁优美&#xff0c;操作直观简单&#xff0c;非常容易上手。 安装说明&#xff1a; 1、上传到网站根目录 2、用phpMyad…

leetcode695 岛屿的最大面积

题目 给你一个大小为 m x n 的二进制矩阵 grid 。 岛屿 是由一些相邻的 1 (代表土地) 构成的组合&#xff0c;这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。你可以假设 grid 的四个边缘都被 0&#xff08;代表水&#xff09;包围着。 岛屿的面积是岛上值…

基于springboot实现入校申报审批系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现入校申报审批系统演示 摘要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装入校申报审批系统软…

【最新鸿蒙应用开发】——Context上下文对象

应用上下文Context 1. 概述 应用上下文&#xff08;Context&#xff09;是应用程序的全局信息的接口。它是一个抽象类&#xff0c;提供了访问应用程序环境的方法和资源的方法。应用上下文可以用于获取应用程序的资源、启动Ability、发送广播等。每个应用程序都有一个应用上下…

【机器学习】机器学习赋能医疗健康:从诊断到治疗的智能化革命

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀目录 &#x1f4d2;1. 引言&#x1f4d9;2. 机器学习在疾病诊断中的应用&#x1f9e9;医学影像分析&#xff1a;从X光到3D成像带代码&#x1…

C++面试准备

变量作用&#xff1a;给一段指定的内存空间起名&#xff0c;方便操作这段内存。 常量&#xff1a;用于记录程序中不可更改的数据。 #include <iostream> using namespace std;#define DAY 7 int main() {cout << "一周有" << DAY << "…

路由器怎么设置局域网?

局域网&#xff08;Local Area Network&#xff0c;LAN&#xff09;是指在一个相对较小的地理范围内&#xff0c;如家庭、办公室或学校等&#xff0c;通过路由器等设备连接起来的计算机网络。设置局域网可以方便地实现内部资源共享和信息交流。本文将介绍如何设置局域网以及一个…

maven 显式依赖包包含隐式依赖包,引起依赖包冲突

问题&#xff1a;FlinkCDC 3.0.1 代码 maven依赖包冲突 什么是依赖冲突 依赖冲突是指项目依赖的某一个jar包&#xff0c;有多个不同的版本&#xff0c;因而造成类包版本冲突 依赖冲突的原因 依赖冲突很经常是类包之间的间接依赖引起的。每个显式声明的类包都会依赖于一些其它…

Java I/O操作

引言 在Java编程中&#xff0c;输入和输出&#xff08;I/O&#xff09;操作是必不可少的部分。Java I/O通过一系列流&#xff08;Stream&#xff09;类和方法&#xff0c;支持文件操作、控制台输入输出、网络I/O等多种I/O操作。本文将详细介绍Java I/O的基础概念、文件操作、字…

FPGA专项课程即将开课,颁发AMD官方证书

社区成立以来&#xff0c;一直致力于为广大工程师提供优质的技术培训和资源&#xff0c;得到了众多用户的喜爱与支持。为了满足用户需求&#xff0c;我们特别推出了“基于Vitis HLS的高层次综合及图像处理开发”课程。 本次课程旨在帮助企业工程师掌握前沿的FPGA技术&#xff…

携程任我行礼品卡怎么用?

前两天我用积分兑了张携程卡&#xff0c;但是最近有没有假期&#xff0c;这张携程卡又不知道咋用 最后朋友告诉我可以在收卡云上转让&#xff0c; 去收卡云看了一眼&#xff0c;携程卡现在99.1折&#xff0c;果断出了&#xff0c;到账速度好快啊

Java多线程编程与并发处理

引言 在现代编程中&#xff0c;多线程和并发处理是提高程序运行效率和资源利用率的重要方法。Java提供了丰富的多线程编程支持&#xff0c;包括线程的创建与生命周期管理、线程同步与锁机制、并发库和高级并发工具等。本文将详细介绍这些内容&#xff0c;并通过表格进行总结和…