MySQ 8.0 推出直方图,性能大大提升!

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
云数据库 RDS PostgreSQL,高可用系列 2核4GB
简介: MySQ 8.0 推出直方图,性能大大提升!
  • 创建和删除直方图
  • 直方图信息
  • 优化案例

查询优化器负责将SQL查询转换为尽可能高效的执行计划,但随着数据环境不断变化,查询优化器可能无法找到最佳的执行计划,导致SQL效率低下。造成这种情况的原因是优化器对查询的数据了解的不够充足,例如:每个表有多少行数据,每列中有多少不同的值,每列的数据分布情况。

因此MySQL8.0.3推出了直方图(histogram)功能,直方图是列的数据分布的近似值,其向优化器提供更多的统计信息。比如字段NULL的个数,每个不同值的百分比,最大/最小值等。

MySQL的直方图分为:等宽直方图和等高直方图,MySQL会自动分配使用哪种类型的直方图,无法干预 等宽直方图:每个bucket保存一个值以及这个值的累计频率

  • 等高直方图:每个bucket保存不同值的个数,上下限以及累计频率

直方图同时也存在一定的限制条件:

  • 不支持几何类型以及json类型的列
  • 不支持加密表和临时表
  • 无法为单列唯一索引的字段生成直方图

创建和删除直方图

创建语法

ANALYZE TABLE tbl_name UPDATE HISTOGRAM ON col_name [, col_name] WITH N BUCKETS;

创建直方图时能够同时为多个列创建直方图,但必须指定bucket数量,范围在1-1024之间,默认100。对于bucket数量应该综合考虑其有多少不同值、数据的倾斜度、精度等,建议从较低的值开始,不符合再依次增加。

删除语法

ANALYZE TABLE tbl_name DROP HISTOGRAM ON col_name [, col_name];

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能。

项目地址:https://github.com/YunaiV/ruoyi-vue-pro

直方图信息

MySQL通过字典表column_statistics来保存直方图的定义,每行记录对应一个字段的直方图,已JSON格式保存。

root@employees 13:49:  select json_pretty(histogram) from information_schema.column_statistics where table_name='employees' and column_name='first_name';;
{
  "buckets": [
    [
      "base64:type254:QWFtZXI=",
      "base64:type254:QWRlbA==",
      0.010176045588684237,
      13
    ],
  "data-type": "string",
  "null-values": 0.0,
  "collation-id": 255,
  "last-updated": "2020-09-09 05:47:32.548874",
  "sampling-rate": 0.163495700259278,
  "histogram-type": "equi-height",
  "number-of-buckets-specified": 100
}

MySQL为employees的first_name字段分配了等高直方图,默认为100个bucket。

当生成直方图时,MySQL会将所有数据都加载到内存中,并在内存中执行所有工作。如果在大表上生成直方图,可能会将几百M的数据读取到内存中的风险,因此我们可以通过参数hitogram_generation_max_mem_size来控制生成直方图最大允许的内存量,当指定内存满足不了所有数据集时就会采用采样的方式。

root@employees 14:12:  select histogram->>'$."sampling-rate"' from information_schema.column_statistics where table_name='employees' and column_name='first_name';;
+---------------------------------+
| histogram->>'$."sampling-rate"' |
+---------------------------------+
| 0.163495700259278               |
+---------------------------------+

从MySQL8.0.19开始,存储引擎自身提供了存储在表中数据的采样实现,存储引擎不支持时,MySQL使用默认采样需要全表扫描,这样对于大表来说成本太高,采样实现避免了全表扫描提高采样性能。

通过INNODB_METRICS计数器可以监视数据页的采样情况,这需要提前开启计数器

root@employees 14:26:  SELECT NAME, COUNT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE 'sampled%'\G
*************************** 1. row ***************************
 NAME: sampled_pages_read
COUNT: 430
*************************** 2. row ***************************
 NAME: sampled_pages_skipped
COUNT: 456
2 rows in set (0.04 sec)

采样率的计算公式为:sampled_page_read/(sampled_pages_read + sampled_pages_skipped)

基于微服务的思想,构建在 B2C 电商场景下的项目实战。核心技术栈,是 Spring Boot + Dubbo 。未来,会重构成 Spring Cloud Alibaba 。

项目地址:https://github.com/YunaiV/onemall

优化案例

复制一张表出来,源表不添加直方图,新表添加直方图

root@employees 14:32:  create table employees_like like employees;
Query OK, 0 rows affected (0.03 sec)
root@employees 14:33:  insert into employees_like select * from employees;
Query OK, 300024 rows affected (3.59 sec)
Records: 300024  Duplicates: 0  Warnings: 0
root@employees 14:33:  ANALYZE TABLE employees_like update HISTOGRAM on birth_date,first_name;
+--------------------------+-----------+----------+-------------------------------------------------------+
| Table                    | Op        | Msg_type | Msg_text                                              |
+--------------------------+-----------+----------+-------------------------------------------------------+
| employees.employees_like | histogram | status   | Histogram statistics created for column 'birth_date'. |
| employees.employees_like | histogram | status   | Histogram statistics created for column 'first_name'. |
+--------------------------+-----------+----------+-------------------------------------------------------+

分别在两张表上查看SQL的执行计划

root@employees 14:43:  explain format=json select count(*) from employees where (birth_date between '1953-05-01' and '1954-05-01') and first_name like 'A%';
{
  "query_block": {
    "select_id": 1,
    "cost_info": {
      "query_cost": "30214.45"
    },
    "table": {
      "table_name": "employees",
      "access_type": "ALL",
      "rows_examined_per_scan": 299822,
      "rows_produced_per_join": 3700,
      "filtered": "1.23",
      "cost_info": {
        "read_cost": "29844.37",
        "eval_cost": "370.08",
        "prefix_cost": "30214.45",
        "data_read_per_join": "520K"
      },
      "used_columns": [
        "birth_date",
        "first_name"
      ],
      "attached_condition": "((`employees`.`employees`.`birth_date` between '1953-05-01' and '1954-05-01') and (`employees`.`employees`.`first_name` like 'A%'))"
    }
  }
}
root@employees 14:45:  explain format=json select count(*) from employees where (birth_date between '1953-05-01' and '1954-05-01') and first_name like 'A%';
{
  "query_block": {
    "select_id": 1,
    "cost_info": {
      "query_cost": "18744.56"
    },
    "table": {
      "table_name": "employees",
      "access_type": "range",
      "possible_keys": [
        "idx_birth",
        "idx_first"
      ],
      "key": "idx_first",
      "used_key_parts": [
        "first_name"
      ],
      "key_length": "58",
      "rows_examined_per_scan": 41654,
      "rows_produced_per_join": 6221,
      "filtered": "14.94",
      "index_condition": "(`employees`.`employees`.`first_name` like 'A%')",
      "cost_info": {
        "read_cost": "18122.38",
        "eval_cost": "622.18",
        "prefix_cost": "18744.56",
        "data_read_per_join": "874K"
      },
      "used_columns": [
        "birth_date",
        "first_name"
      ],
      "attached_condition": "(`employees`.`employees`.`birth_date` between '1953-05-01' and '1954-05-01')"
    }
  }
}

可以看出Cost值从30214.45降到了18744.56,扫描行数从299822降到了41654,性能有所提升。

参考资料:

https://dev.mysql.com/doc/refman/8.0/en/analyze-table.html#analyze-table-histogram-statistics-analysis

https://mysqlserverteam.com/histogram-statistics-in-mysql/

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
消息中间件 NoSQL 关系型数据库
redis事务和异步连接
redis事务和异步连接
225 1
|
人工智能 算法 BI
第十四届蓝桥杯省赛大学C组(C/C++)三国游戏
第十四届蓝桥杯省赛大学C组(C/C++)三国游戏
|
11月前
|
人工智能 JSON 自然语言处理
智能化AI工具-语言翻译与本地化
在全球化发展的背景下,语言翻译与本地化需求日益增长。无论是跨境电商、国际合作,还是本地化应用开发,都需要高效、准确的翻译解决方案。阿里云通义千问作为一款强大的大语言模型,不仅具备出色的自然语言理解能力,还能够在多语言翻译和本地化场景中发挥重要作用。本博客将详细介绍如何基于阿里云通义千问开发语言翻译与本地化工具,包括产品介绍、程序代码以及阿里云相关产品的具体使用流程。
474 10
|
12月前
|
存储 缓存 Ubuntu
Ubuntu Linux目录结构
理解Ubuntu Linux的目录结构对系统管理、维护和故障排除至关重要。每个目录都有其特定的用途和存放内容,通过了解这些目录,可以更高效地管理系统文件,确保系统的稳定运行。希望本文对你深入理解Ubuntu的目录结构有所帮助。
445 1
|
弹性计算 监控 安全
阿里云服务器自带多少DDoS防护?小编为你详细揭秘!
阿里云服务器自带多少DDoS防护?小编为你详细揭秘!
|
存储 关系型数据库 分布式数据库
PolarDB,阿里云的云原生分布式数据库,以其存储计算分离架构为核心,解决传统数据库的扩展性问题
【7月更文挑战第3天】PolarDB,阿里云的云原生分布式数据库,以其存储计算分离架构为核心,解决传统数据库的扩展性问题。此架构让存储层专注数据可靠性,计算层专注处理SQL,提升性能并降低运维复杂度。通过RDMA加速通信,多副本确保高可用性。资源可独立扩展,便于成本控制。动态添加计算节点以应对流量高峰,展示了其灵活性。PolarDB的开源促进了数据库技术的持续创新和发展。
595 2
|
安全 Java 应用服务中间件
【小白误闯】这可能是对 Tomcat 工作原理解释最详细的文章
脑子一闪而过,当年 V 哥在面试 Java 开发时,被问到让你写一个 Tomcat 服务器,你有什么想法?尼码,面试官摆明是在压工资了,你得逞了,我回答不上来,当时也没研究过 Tomcat 的源码,饮恨被拒。今天想想看,当时尴尬的表情,蛮逗的嘞。 今天V 哥有空把这个问题整理出来,干脆写成文章吧,放到资料库里,也分享给大家。Tomcat 是一个流行的 Java Servlet 和 JSP 容器,用于运行 Java Web 应用程序。它的核心组件主要包括:
444 1
|
移动开发 开发工具 数据安全/隐私保护
iOS APP 版本更新升级教程:如何打包上架新的 APP 版本?
iOS APP 版本更新升级教程:如何打包上架新的 APP 版本?
|
消息中间件 缓存 算法
一、RapidIO背景介绍(1)
一、RapidIO背景介绍(1)
702 0
一、RapidIO背景介绍(1)
|
人工智能 数据可视化 算法
9种常见思维导图种类,引领创意风暴!
除了树状图的形式,思维导图还有其它表现形式激发创意,整理思绪
9种常见思维导图种类,引领创意风暴!