谁便宜就选谁---基于成本的优化

news2024/11/15 11:41:59

什么是成本

我们之前老说MySQL执行一个查询可以有不同的执行方案,它会选择其中成本最低,或者说代价最低的那种方案去真正的执行查询。不过我们之前对成本的描述是非常模糊的,其实在MySQL中一条查询语句的执行成本是由下面这两个方面组成的:

I/O成本
  我们的表经常使用的MyISAM、InnoDB存储引擎都是将数据和索引都存储到磁盘上的,
  当我们想查询表中的记录时,需要先把数据或者索引加载到内存中然后再操作。
  这个从磁盘到内存这个加载的过程损耗的时间称之为I/O成本。
CPU成本
  读取以及检测记录是否满足对应的搜索条件、对结果集进行排序等这些操作损耗的时间称之为CPU成本。

对于InnoDB存储引擎来说,页是磁盘和内存之间交互的基本单位,设计MySQL的大佬规定读取一个页面花费的成本默认是1.0,读取以及检测一条记录是否符合搜索条件的成本默认是0.2。1.0、0.2这些数字称之为成本常数,这两个成本常数我们最常用到,其余的成本常数我们后边再说。

单表查询的成本

在一条单表查询语句真正执行之前,MySQL的查询优化器会找出执行该语句所有可能使用的方案,对比之后找出成本最低的方案,这个成本最低的方案就是所谓的执行计划,之后才会调用存储引擎提供的接口真正的执行查询,这个过程总结一下就是这样:

  1. 根据搜索条件,找出所有可能使用的索引

  2. 计算全表扫描的代价

  3. 计算使用不同索引执行查询的代价

    3.1. 范围区间数量
    3.2. 需要回表的记录数: 需要确定区间最左记录和区间最右记录之间的数量
    优化器需要计算二级索引的某个范围区间到底包含多少条记录,对于本例来说就是要计算idx_key2在(10, 1000)这个范围区间中包含多少二级索引记录,计算过程是这样的:

    • 先根据key2 > 10这个条件访问一下idx_key2对应的B+树索引,找到满足key2 > 10这个条件的第一条记录,我们把这条记录称之为区间最左记录。
      我们前头说过在B+数树中定位一条记录的过程是贼快的,是常数级别的,所以这个过程的性能消耗是可以忽略不计的。

    • 然后再根据key2 < 1000这个条件继续从idx_key2对应的B+树索引中找出第一条满足这个条件的记录,我们把这条记录称之为区间最右记录,这个过程的性能消耗也可以忽略不计的。

    • 如果区间最左记录和区间最右记录相隔不太远(在MySQL 5.7.21这个版本里,只要相隔不大于10个页面即可),那就可以精确统计出满足key2 > 10 AND key2 < 1000条件的二级索引记录条数。
      否则只沿着区间最左记录向右读10个页面,计算平均每个页面中包含多少记录,然后用这个平均值乘以区间最左记录和区间最右记录之间的页面数量就可以了。
      那么问题又来了,怎么估计区间最左记录和区间最右记录之间有多少个页面呢?解决这个问题还得回到B+树索引的结构中来:
      在这里插入图片描述如图,我们假设区间最左记录在页b中,区间最右记录在页c中,那么我们想计算区间最左记录和区间最右记录之间的页面数量就相当于计算页b和页c之间有多少页面,而每一条目录项记录都对应一个数据页,所以计算页b和页c之间有多少页面就相当于计算它们父节点(也就是页a)中对应的目录项记录之间隔着几条记录。在一个页面中统计两条记录之间有几条记录的成本就贼小了。
      不过还有问题,如果页b和页c之间的页面实在太多,以至于页b和页c对应的目录项记录都不在一个页面中该咋办?继续递归啊,也就是再统计页b和页c对应的目录项记录所在页之间有多少个页面。之前我们说过一个B+树有4层高已经很了不得了,所以这个统计过程也不是很耗费性能。

    3.3. 根据这些记录里的主键值到聚簇索引中做回表操作
    3.4. 回表操作后得到的完整用户记录,然后再检测其他搜索条件是否成立

  4. 对比各种执行方案的代价,找出成本最低的那一个

连接查询的成本

对于两表连接查询来说,它的查询成本由下面两个部分构成:

  • 单次查询驱动表的成本
  • 多次查询被驱动表的成本(具体查询多少次取决于对驱动表查询的结果集中有多少条记录)

调节成本参数

一条语句的执行其实是分为两层的:server层 、存储引擎层。server层进行连接管理、查询缓存、语法解析、查询优化等操作,在存储引擎层执行具体的数据存取操作<。也就是说一条语句在server层中执行的成本是和它操作的表使用的存储引擎是没关系的,所以关于这些操作对应的成本常数就存储在了server_cost表中,而依赖于存储引擎的一些操作对应的成本常数就存储在了engine_cost表中。

Good SQL

show engine innodb status
show tabel status like ‘table_name'
show tables from 'db_name' like 'table_name'
show index from table_name

mysql> select * from mysql.server_cost;
+------------------------------+------------+---------------------+---------+
| cost_name                    | cost_value | last_update         | comment |
+------------------------------+------------+---------------------+---------+
| disk_temptable_create_cost   |       NULL | 2021-09-08 16:23:46 | NULL    |
| disk_temptable_row_cost      |       NULL | 2021-09-08 16:23:46 | NULL    |
| key_compare_cost             |       NULL | 2021-09-08 16:23:46 | NULL    |
| memory_temptable_create_cost |       NULL | 2021-09-08 16:23:46 | NULL    |
| memory_temptable_row_cost    |       NULL | 2021-09-08 16:23:46 | NULL    |
| row_evaluate_cost            |       NULL | 2021-09-08 16:23:46 | NULL    |
+------------------------------+------------+---------------------+---------+
6 rows in set (0.00 sec)
mysql>
mysql> select * from mysql.engine_cost;
+-------------+-------------+------------------------+------------+---------------------+---------+
| engine_name | device_type | cost_name              | cost_value | last_update         | comment |
+-------------+-------------+------------------------+------------+---------------------+---------+
| default     |           0 | io_block_read_cost     |       NULL | 2021-09-08 16:23:46 | NULL    |
| default     |           0 | memory_block_read_cost |       NULL | 2021-09-08 16:23:46 | NULL    |
+-------------+-------------+------------------------+------------+---------------------+---------+
2 rows in set (0.00 sec)
mysql>

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

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

相关文章

十四、坦克大战(上)

文章目录 一、坦克大战游戏演示(略)二、java绘图坐标体系三、java绘图技术3.1 快速入门3.2 绘图原理Graphics类 四、java事件处理机制五、绘制坦克5.1 坦克抽象类、己方坦克、敌方坦克5.2 自定义面板5.3 绘图界面 一、坦克大战游戏演示(略) 二、java绘图坐标体系 三、java绘图…

LVGL 控件之日历(lv_calendar)

目录 一、日历1、组成2、创建日历3、日期的设置/显示3.1 设置当前日期3.2 显示日期3.3 日历头 4、设置日期高亮5、设置日名6、事件7、API 函数 一、日历 1、组成 日历部件由两个部分组成&#xff1a; 主体背景 LV_PART_MAIN&#xff1b;各个按钮 LV_PART_ITEMS&#xff08;指…

kubeadm部署 Kubernetes(k8s) 高可用集群【V1.20 】

kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具。 calico.yaml kubernertes-dashboard.yaml 1. 安装要求 在开始之前&#xff0c;部署Kubernetes集群机器需要满足以下几个条件&#xff1a; 7台机器&#xff0c;操作系统Openeuler22.03 LTS SP4硬件配置&#…

【GPT】Coze使用开放平台接口-【1】创建插件

本文档主要描述在 coze 里面把开放平台的接口创建为插件&#xff0c;供别人调用。本系列调用的接口&#xff0c;都是调用快商通 AI 开放平台的接口 注意&#xff1a;如果是团队需要的&#xff0c;建议直接在团队空间里面创建这些&#xff0c;不然在个人空间创建得很爽&#xff…

Linux——命令行文件的管理(创建,复制,删除,移动文件,硬链接与软链接)

目录 一、创建文件和目录 二、复制文件和目录 三、删除文件和目录 四、移动文件和目录 五、硬链接和软链接&#xff08;软链接也指符号链接&#xff09; 索引节点&#xff08;inode) 硬链接 软链接&#xff08;符号链接&#xff09; 一、创建文件和目录 mkdir命令可以创…

PCIe 复位:必须了解的PERST#

1.什么是PERST# PERST#作为 Fundamental Reset&#xff0c;是直接通过边带信号PERST#&#xff08;PCI Express Reset&#xff09;产生的。Fundamental Reset会复位整个PCIe设备&#xff0c;初始化所有与状态机相关的硬件逻辑&#xff0c;端口状态以及配置空间中的配置寄存器…

使用谷歌翻译的推荐理由及其他翻译工具推荐~

在现在快节奏的工作中&#xff0c;翻译工具已成为我们日常当中不可或缺的助手。其中&#xff0c;谷歌翻译以其高效、准确的特点&#xff0c;在众多翻译软件中脱颖而出。以下&#xff0c;我为您详细介绍为何推荐在工作中使用谷歌翻译&#xff0c;并同时提供其他三款优秀的翻译工…

linux内核驱动:pca953xIO扩展芯片驱动总结

目录 前言一、PCA9536芯片介绍二、驱动说明三、配置流程四、应用操作方式 前言 本笔记总结使用ti 的PCA953x进行SOC的GPIO扩展时步骤&#xff0c;基于linux内核版本5.10.xxx&#xff1b; 一、PCA9536芯片介绍 【1】PCA9536是基于i2c接口的GPIO扩展芯片&#xff0c;最大支持到…

【Java学习】多线程JUC万字超详解

所属专栏&#xff1a;Java学习 1. 多线程的概念 线程&#xff1a;线程是操作系统能够进行运算调度的最小单位&#xff0c;它被包含在进程之中&#xff0c;是进程的实际运作单位 下面这些每一个能够运行的软件就是一个进程 并发&#xff1a;在同一时刻&#xff0c;有多个…

网络编程学习:TCP/IP协议

TCP/IP协议简介 TCP/IP协议包含了一系列的协议&#xff0c;也叫TCP/IP协议族&#xff08;TCP/IP Protocol Suite&#xff0c;或TCP/IP Protocols&#xff09;&#xff0c;简称TCP/IP。 分层结构 为了能够实现不同类型的计算机和不同类型的操作系统之间进行通信&#xff0c;引…

Java中的锁(四)利用读写锁实现高性能网页缓存

文章目录 背景Ehcache2源码解析-如何实现缓存网页读写锁ReentrantReadWriteLock解析读写锁的特性读写锁是如何实现的&#xff1f; 如何将Ehcach2-web的源码迁移到Ehcach3中&#xff1f;/ 如何自定义Filter实现高性能网页缓存&#xff1f; 背景 在我们的销售页面&#xff0c;有…

Django+Vue酒店推荐系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 需要的环境3.2 Django接口层3.3 实体类3.4 config.ini3.5 启动类3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质创作者&…

Linux文件操作(二)

Linux文件操作&#xff08;二&#xff09; 导语文件和目录维护chmodchownlink及其变体dir及其变体chdir和getcwd 扫描目录opendirreaddirtelldirseekdirclosedir示例程序 错误处理strerrorperror /procfcntlmmap相关mmapmsyncmunmap 总结参考文献 导语 文件操作的第二部分&…

juzige/Monitoring-System-基于Java语言的光伏监控系统

Photovoltaic-Monitoring-System-Based-on-Java-Language 基于Java语言的光伏监控系统光伏发电系统光伏软件系统光伏监控系统源码光伏发电系统源码-智电云 一、 介绍 光伏光伏发电预测逆变器监控逆变器数据采集光伏运维光伏电站光伏功率预测光伏监控系统光伏发电系统光伏软件…

【CSS in Depth 2 精译_022】3.6 一招搞定容器内元素间距的问题 + 3.7 本章小结

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一章 层叠、优先级与继承&#xff08;已完结&#xff09; 1.1 层叠1.2 继承1.3 特殊值1.4 简写属性1.5 CSS 渐进式增强技术1.6 本章小结 第二章 相对单位&#xff08;已完结&#xff09; 2.1 相对…

jQuery入门(六)jQuery实现瀑布流分页案例

一、瀑布流分页案例分析 1.1) 功能分析&#xff1a; 鼠标下拉&#xff0c;加载分页数据(10条) &#xff0c;如下图&#xff1a; 案例分析&#xff1a; 1.2) 如何确定当前显示的数据已经浏览完毕&#xff1f; 公式&#xff1a;(滚动条距底部的距离 滚动条上下滚动的距离 当…

【Python篇】Python 类和对象:详细讲解(下篇)

文章目录 Python 类和对象&#xff1a;详细讲解&#xff08;下篇&#xff09;15. 接口和协议&#xff08;Interfaces and Protocols&#xff09;15.1 什么是接口&#xff1f;15.2 协议的基本概念例子&#xff1a;定义飞行协议详细解释输出示例 16. 装饰器模式&#xff08;Decor…

A02、Java编程性能调优(02)

1、Stream如何提高遍历集合效率 1.1、什么是Stream 现在很多大数据量系统中都存在分表分库的情况。例如&#xff0c;电商系统中的订单表&#xff0c;常常使用用户 ID 的 Hash 值来实现分表分库&#xff0c;这样是为了减少单个表的数据量&#xff0c;优化用户查询订单的速度。 …

ZYNQ-Utlscale-RFSOC看门狗

ZYNQ-Utlscale-RFSOC看门狗复位 ZYNQ-Utlscale-RFSOC 看门狗的程序网上里程很少&#xff0c;开源资料也是几乎没有&#xff0c;最近需要用到这个功能&#xff0c;来来回回搞了一周才搞定。刚开始参考ZYNQ7000的资源&#xff0c;发现MPSOC不适用。很感谢下面的几篇文章&#xf…

探索TinyDB:轻量级数据库的优雅之旅

文章目录 探索TinyDB&#xff1a;轻量级数据库的优雅之旅背景&#xff1a;为何选择TinyDB&#xff1f;TinyDB是什么&#xff1f;如何安装TinyDB&#xff1f;简单库函数使用方法场景应用常见Bug及解决方案总结 探索TinyDB&#xff1a;轻量级数据库的优雅之旅 背景&#xff1a;为…