MySQL查询成本

MySQL查询成本

MySLQ会将优化后的语句分别计算成本,取最优SQL执行。MySQL查询成本分为:

  1. IO成本:将磁盘数据加载到内存的成本。在MySQL的InnoDB引擎中就是一个叶子页。默认成本1.0.
  2. CPU成本:数据读取检测是否复核搜索条件。默认成本0.2.

基于成本的优化步骤

  1. 根据搜索条件,分析可能用到的索引。
  2. 计算全表扫描的查询成本。
  3. 计算使用每个索引的查询成本。
  4. 对比各种执行方案,取查询成本最低的方案。

单表查询计算成本计算

准备环境:

CREATE TABLE `product_order`  (`id` int(11) NOT NULL AUTO_INCREMENT,`order_number` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,`order_desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,`order_status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,`create_time` datetime NOT NULL,`expire_time` datetime NOT NULL,PRIMARY KEY (`id`) USING BTREE,UNIQUE INDEX `u_idx_three`(`create_time`, `order_status`, `expire_time`) USING BTREE,INDEX `idx_number`(`order_number`) USING BTREE,INDEX `idx_expire_time`(`expire_time`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 10004 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = COMPACT;

创建一个表,批量生成10000+数据,其中有三个索引:

  1. idx_number二级索引
  2. idx_expire_time二级索引
  3. create_time + order_status + expire_time联合索引

成本分析:

要分析的SQL:

SELECT*
FROMproduct_order o
WHEREo.order_number IN ( "9671332", "9504815", "2890999" )AND o.expire_time < '2024-06-01' AND o.expire_time > '2022-06-01'AND o.order_status = '0'AND o.order_desc LIKE '%这是备注%';

分析过程:

  1. 分析可能用到的索引,order_number或者expire_time。
  2. 全表扫描成本分析
show TABLE status like 'product_order'; -- 查看系统文件,其中两个属性, rows(预估行数):9907, data_length(数据大小):1589248

全表扫描成本为:

  1. IO成本:在InnoDB存储引擎中,一个叶子页的大小即一次IO,一个叶子大小为16KB,所以IO成本为:(data_length/16/1024) * 1 + 微调值(默认1.1)。
  2. CPU成本:rows * 0.2 + 微调值(默认1.0)。
  3. 在本SQL中的全表扫描成本为:1589248/16/1024 * 0.1 + 1.1 + 9907 * 0.2 + 1.0 = 1993.2。
  1. 分析可能用到的索引下的查询成本
    使用索引查询的成本为二级索引IO成本 + 回表操作的成本。

使用expire_time索引查询成本:

  1. 二级索引成本:如果使用到了索引且索引可以锁定某些范围也就是B+树子节点的数据范围,每有一个范围IO成本+1,因为o.expire_time < ‘2024-06-01’ AND o.expire_time > ‘2022-06-01’ 可以确定一个范围,所以IO成本为1;
  2. 回表成本:
    1. 找到数据最左边数据,然后找到最右边的数据,这个过程成本忽略不计。
    2. 计算范围内数据量,MySQL会进行估算(此处为2721条)。 cpu成本就为2721*0.2+0.01(微调值) = 544.21
    3. 每次回表是一次IO,所以IO成本为2721*1 = 2721
    4. 得到数据后过滤除使用索引的其他条件,这里是CPU成本,2721*0.2 = 544.2
  3. 使用expire_time索引查询成本为2721 + 544.21 + 544.2 = 3809.41,比全表扫描成本还高,所以不会使用这个二级索引,原因是回表的数据量高达2000+。

使用order_number索引的查询成本:

  1. 二级索引成本:in条件相当于三个叶子页,所以IO成本为 3;
  2. 回表成本:同上面逻辑 30.2+0.01(微调值) + 31 + 3*0.2 = 4.21
  3. 总成本 3+ 4.21 = 7.21

验证:通过explain format = json + select语句查看SQL的查询成本:7.21

{"query_block": {"select_id": 1,"cost_info": {"query_cost": "7.21"},"table": {"table_name": "o","access_type": "range","possible_keys": ["idx_number","idx_expire_time"],"key": "idx_number","used_key_parts": ["order_number"],"key_length": "34","rows_examined_per_scan": 3,"rows_produced_per_join": 0,"filtered": "1.67","index_condition": "(`my-test`.`o`.`order_number` in ('9671332','9504815','2890999'))","cost_info": {"read_cost": "7.20","eval_cost": "0.01","prefix_cost": "7.21","data_read_per_join": "54"},"used_columns": ["id","order_number","order_desc","order_status","create_time","expire_time"],"attached_condition": "((`my-test`.`o`.`expire_time` < '2024-06-01') and (`my-test`.`o`.`expire_time` > '2022-06-01') and (`my-test`.`o`.`order_status` = '0') and (`my-test`.`o`.`order_desc` like '%这是备注%'))"}}
}
总结

在使用二级索引的时候,如果需要回表,回表的成本是及其高的,所以MySQL一般会使用通过二级索引检索出来数据量少的索引,因为需要回表的数据量少,成本低。

Optimizer Trace(优化器追踪)

查看Optimizer Trace是否开启,默认关闭。

show variables like 'Optimizer Trac';-- 查看

开启Optimizer Trace,注意开启是session级别的。

set optimizer_trace 'enabled = on';

查看分析内容,会看到一个json串

select * from information_schema.OPTIMIZER_TRACE;

json串中的参数

  1. join_preparation:准备阶段,expanded_query:优化后的SQL语句。
  2. join_optimization:分析阶段,original_condition:索引处理。analyzing_range_alternatives:分析索引,查看成本
  3. considered_execution_plans:执行阶段

两表连接查询成本计算

两表连接查询的成本=单次查询驱动表的成本+多次查询被驱动表的成本。其中单次查询驱动表的成本称为驱动表扇出(fanout);被驱动表的查询次数取决于驱动表的扇出。

单词驱动表的删除是MySQL根据一定的算法进行猜测。因为如果驱动表的扇出可以根据驱动表的where条件确定范围,是可以计算的,如果where条件无法确定范围只能猜测。

多表连接查询成本计算

再多表连接查询时候,如果使用内连接查询多个表,可作为驱动表的表很多,而且连接顺序也很多。怎么办?

  1. 提前结束

如果计算的成本大于前面计算过的执行计划成本,会结束运算。

  1. 控制连接的深度:MySQL有一个参数可以控制连接的深度,(笼统地说就是超过多少个表就不会继续计算查询成本了);
show variables like 'optimizer_search_depth';-- 默认62
  1. 启发式规则

mysql根据以往SQL经验计算查询成本。

成本计算参数

因为每个服务器的IO效率和CPU效率不同,可以通过调节来提高效率。这里的参数就是我们计算IO和CPU开销的成本计算参数。一般不建议调整,因为不了解MySQL计算成本的底层逻辑。

如果未设置,使用默认值。

select * from mysql.server_cost;
select * from mysql.engine_cost;

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

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

相关文章

eBPF可观测之网络流量控制和管理traffic control浅尝

目录 工程背景 环境准备 安装工具​​​ 安装依赖包 安装C依赖库 操作步骤 目录结构 代码展示 效果展示 拓展提升 工程背景 首先发表一个"暴论" eBPF在可观测方面的应用&#xff0c;就是各种google。 不需要学习内核&#xff0c;只要掌握ebpf开发套路。…

STL库的ranges

STL库的ranges 在C STL标准库的<ranges>&#xff08;C20中引入&#xff09;中&#xff0c;定义了一套全面的关于范围的概念、类、模板、函数以及其他相关组件&#xff0c;旨在提高对元素序列的抽象化处理能力。主要包括以下几个方面&#xff1a; 范围&#xff08;Range…

lsof 命令

lsof&#xff08;list open files&#xff09;是一个列出当前系统打开文件的工具。在linux环境下&#xff0c;任何事物都以文件的形式存在&#xff0c;通过文件不仅仅可以访问常规数据&#xff0c;还可以访问网络连接和硬件。所以如传输控制协议 (TCP) 和用户数据报协议 (UDP) …

什么是TLAB?

这个得从内存申请说起。 一般而言生成对象需要向堆中的新生代申请内存空间&#xff0c;而堆又是全局共享的&#xff0c;像新生代内存又是规整的&#xff0c;是通过一个指针来划分的。 内存是紧凑的&#xff0c;新对象创建指针就右移对象大小size即可&#xff0c;这叫指针加法…

怎么通过互联网远程控制电脑?

远程访问又称为网络远程控制&#xff0c;它使用户能够通过互联网连接两台设备以解决问题。进行控制的电脑称为控制端&#xff0c;被控制的电脑则称为被控端。在远程访问过程中&#xff0c;控制端电脑掌握整个连接的操作。远程控制软件会捕获被控端电脑的操作&#xff0c;并在主…

绘画智能体分享

这是您请求的故宫雪景图&#xff0c;角落有一只可爱的胖猫&#xff0c;采用了水墨画风格&#xff0c;类似于张大千的作品。希望您喜欢这幅画&#xff01; &#x1f3a8; 选项 1【转变风格】——将这幅画转变为梵高的后印象派风格&#xff0c;增添一些梵高特有的笔触和色彩。 &…

Superset二次开发之Github项目推送到GitLab仓库

以下是从GitHub克隆Superset项目并将其推送到GitLab的详细操作步骤 lab 地址: xxx lab 配置: 生成SSH密钥 ssh-keygen -t rsa -b 4096 -C "邮箱地址" 默认情况下密钥会生成在~/.ssh (/c/Users/Administrator/.ssh/id_rsa)目录下。 公钥添加到GitLab: 打开公钥文件…

# 第十八届东北ccpc程序设计竞赛(A)

ProblemA paper watering 题意: 对一个数进行k次操作&#xff0c;操作有两种类型:1.将数开根号后向下取整&#xff1b;2.将该数取平方。求出这个数字能改成多少个不同的数&#xff08;包括一开始的原数&#xff09;. 思路&#xff1a; 如果这个数开方后为原来数字&#xff…

enum编程入门:探索枚举类型的奥秘

enum编程入门&#xff1a;探索枚举类型的奥秘 在编程的世界里&#xff0c;enum&#xff08;枚举&#xff09;类型是一种特殊的数据类型&#xff0c;它允许我们为变量设置一组预定义的、有限的值。这种类型在很多编程语言中都得到了广泛的应用&#xff0c;为开发者提供了更加清…

短时间内如何顺利通过 Java 面试?

今天我们来探讨一个重要的话题&#xff1a;短时间内如何顺利通过 Java 面试&#xff1f; 在此之前&#xff0c;我正在精心编写一套完全面向小白的 Java 自学教程&#xff0c;我相信这套教程会非常适合正在努力提升的你。教程里面涵盖了丰富全面的编程教学内容、详细生动的视频…

在HTML中写入JavaScript

在网站中添加JavaScript代码是为了增加页面的交互性。这可以通过直接在HTML文件中写入JavaScript代码&#xff0c;或者通过引入外部JavaScript文件来实现。下面我将详细说明这两种方法。 直接在HTML中写入JavaScript 这种方法简单直接&#xff0c;适合用于快速测试或添加少量的…

liunx telnet 安装

1&#xff0c;离线包下载 &#xff08;1&#xff09;首先下载 telnet-client (或 telnet) 客户端软件包&#xff0c;这里我们下载 telnet-0.17-64.el7.x86_64.rpm 版本&#xff1a; 下载地址&#xff1a;http://www.rpmfind.net/linux/rpm2html/search.php?querytelnet 安装…

上网行为监控软件大盘点:好用的上网行为管理软件一览

这是后台私信来的客户发来的图片&#xff0c;他们老板想要给自己公司安装上网行为监控软件。 可见&#xff0c;企业对员工上网行为的监控与管理已经是很多企业都开始重视的问题。 上网行为管理软件能够帮助企业确保网络资源得到合理分配&#xff0c;提升工作效率&#xff0c;…

ch5链路层和局域网

回顾TCP/IP参考模型&#xff0c;明确链路层和物理层在整个模型中的地位&#xff0c;简要提出链路层要解决的问题是单段链路的数据传输&#xff0c;物理层解决的是数字信号与电气信号之间的相互转换。 链路层概述 节点&#xff1a;主机和路由器(包括网桥和交换机) 链路&#xf…

QT 信号和槽教程,窗体和控件对象之间的沟通一般都使用信号和槽

Qt的信号和槽&#xff08;Signals and Slots&#xff09;机制是一种强大的对象间通信方式&#xff0c;它允许对象在完全解耦的情况下相互通信。以下是关于Qt信号和槽的简明教程&#xff1a; 基本概念 信号&#xff08;Signal&#xff09;&#xff1a;信号是由Qt对象发出的通知…

(2024,LoRA,全量微调,低秩,强正则化,缓解遗忘,多样性)LoRA 学习更少,遗忘更少

LoRA Learns Less and Forgets Less 公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 1. 引言 2. 背景 3. 实验设置 3.2 使用编码和数学基准测试来衡量学习&#xff08;目标域…

数据分析必备:一步步教你如何用Pandas做数据分析(14)

1、Pandas 聚合 Pandas 聚合的操作实例 创建滚动&#xff0c;扩展和ewm对象后&#xff0c;可以使用多种方法对数据执行聚合。 1.1、对DataFrame聚合 我们创建一个DataFrame并对其应用聚合 import pandas as pd import numpy as np df pd.DataFrame(np.random.randn(10, 4)…

jpeg编码学习

正点原子stm32教程提到过jpeg解码库libjpeg&#xff0c;但是没有提到jpeg编码&#xff0c;我也好奇jpeg编码怎么实现&#xff0c;用代码怎么生成jpeg文件的。所以最近学习了jpeg编码&#xff0c;在这里做记录。 参考文章 jpeg图片格式详解 https://blog.csdn.net/yun_hen/art…

跨越障碍:解决复杂网页数据提取的挑战

在数字化时代&#xff0c;网页数据提取已成为获取信息的重要途径。然而&#xff0c;随着网页设计的日益复杂化&#xff0c;从这些页面中提取有用数据的任务也变得更加困难。本文将探讨在面对复杂网页时&#xff0c;如何有效地提取所需数据&#xff0c;并分析可能遇到的挑战及其…

一文了解-电子公司组织架构

以下仅为一般研发设计公司的岗位&#xff0c; 不包括工厂。 总经理 柏柏有话说: 不多说&#xff0c;人中龙凤、群山俯首、众神膜拜&#xff01; 项目总监 产品总监 软件总监 测试总监 销售总监 人事总监 财务总监 采购总监 柏柏有话说: 这么说吧&#xff0c; 柏柏的前同龄同事…