索引设计—高并发场景微服务实战(六)

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,118元/月
云原生网关 MSE Higress,422元/月
简介: 你好,我是程序员Alan,很高兴遇见你.我在上一篇文章《 表结构设计—高并发场景微服务实战(五)》中,详细的写了如何选择合适的类型创建一张表,但表结构设计只是设计数据库最初的环节之一,我们还缺少数据库设计中最为重要的一个环节——索引设计,只有正确设计索引,业务才能达到上线的初步标准。 索引如果展开来讲有很多需要关注的地方,例如索引设计、业务应用与调优等等,本篇文章我会重点讲一下索引设计相关知识

你好,我是程序员Alan.

我在上一篇文章《 表结构设计—高并发场景微服务实战(五)》中,详细的写了如何选择合适的类型创建一张表,但表结构设计只是设计数据库最初的环节之一,我们还缺少数据库设计中最为重要的一个环节——索引设计,只有正确设计索引,业务才能达到上线的初步标准。  

索引如果展开来讲有很多需要关注的地方,例如索引设计、业务应用与调优等等,本篇文章我会重点讲一下索引设计相关知识。

索引是什么?

索引是一门排序的艺术,索引是提升查询速度的一种数据结构。有效的设计并创建索引,会提升数据库系统的整体性能。索引之所以能提升查询速度,在于它在插入时对数据进行了排序(显而易见,它的缺点是影响插入或者更新的性能)。索引是对记录进行排序

在目前的 MySQL 8.0 版本中,InnoDB 存储引擎支持的索引有 B+ 树索引、全文索引、R 树索引。这里我们先关注使用最为广泛的 B+ 树索引。  

B+树索引结构

B+ 树索引是数据库系统中最为常见的一种索引数据结构,几乎所有的关系型数据库都支持它。

那你知道为什么关系型数据库都热衷支持 B+树索引吗?因为B+数是目前为止排序最有效率的数据结构。

B+树索引的特点是: 基于磁盘的平衡树,但树非常矮,通常为 3~4 层,能存放千万到上亿的排序数据。树矮意味着访问效率高,从千万或上亿数据里查询一条数据,只用 3、4 次 I/O。  

又因为现在的固态硬盘每秒能执行至少 10000 次 I/O ,所以查询一条数据,哪怕全部在磁盘上,也只需要 0.003 ~ 0.004 秒。另外,因为 B+ 树矮,在做排序时,也只需要比较 3~4 次就能定位数据需要插入的位置,排序效率非常不错。  

优化 B+ 树索引的插入性能

B+ 树在插入时就对要对数据进行排序,但排序的开销其实并没有你想象得那么大,因为排序是 CPU 操作(当前一个时钟周期 CPU 能处理上亿指令)。

真正的开销在于 B+ 树索引的维护,保证数据排序,这里存在两种不同数据类型的插入情况

  • 数据顺序(或逆序)插入: B+ 树索引的维护代价非常小,叶子节点都是从左往右进行插入,比较典型的是自增 ID 的插入、时间的插入(若在自增 ID 上创建索引,时间列上创建索引,则 B+ 树插入通常是比较快的)。
  • 数据无序插入: B+ 树为了维护排序,需要对页进行分裂、旋转等开销较大的操作,另外,即便对于固态硬盘,随机写的性能也不如顺序写,所以磁盘性能也会收到较大影响。

你不可能要求所有插入的数据都是有序的,因为索引的本身就是用于数据的排序,插入数据都已经是排序的,那么你就不需要 B+ 树索引进行数据查询了。

所以对于 B+ 树索引,在 MySQL 数据库设计中,仅要求主键的索引设计为顺序,比如使用自增,或使用排序的 UUID,而不用无序值做主键。

二级索引

InnoDB 存储引擎的数据是根据主键索引排序存储的,除了主键索引外,其他的索引都称之为二级索引(Secondeary Index), 或非聚集索引(None Clustered Index)。  二级索引也是一颗 B+ 树索引,但它和主键索引不同的是叶子节点存放的是索引键值、主键值。  下面的表User 中的 idx_name 就是二级索引。

CREATETABLE User (    id BIGINT AUTO_INCREMENT,    name VARCHAR(128)NOTNULL,    sex CHAR(6)NOTNULL,    registerDate DATETIMENOTNULL,    ...
    PRIMARY KEY(id),-- 主键索引    KEY idx_name(name)-- 二级索引)

如果用户通过列 name 进行查询,比如下面的 SQL:  

SELECT*FROM User WHERE name ='Alan'

通过二级索引 idx_name 只能定位主键值,需要额外再通过主键索引进行查询,才能得到最终的结果。这种“二级索引通过主键索引进行再一次查询”的操作叫作“回表”

你知道二级索引这样设计的一大好处是什么吗?如果记录发生了修改,那么其他索引无需进行维护,除非记录的主键发生了修改。

考虑额外创二级索引的开销

二级索引虽好,但不可以忽略了使用它带来的开销。创建二级索引的开销,主要表现在二级索引的维护、空间开销和回表开销三个方面。接下来,我们详细分析一下。

首先是二级索引的维护开销。创建 N 个二级索引,就需要再创建 N 棵 B+ 树,新增数据时不仅要修改聚簇索引,还需要修改这 N 个二级索引。

其次是空间开销。虽然二级索引不保存原始数据,但需要保存索引列的数据,所以会占用更多的空间。这样除了数据存储本身空间的开销,还额外增加了索引数据存储的开销。

最后是回表的代价。二级索引不保存原始数据,通过索引找到主键后需要再查询聚簇索引,才能得到我们要的数据。

函数索引

从 MySQL 5.7 版本开始,MySQL 就开始支持创建函数索引 (即索引键是一个函数表达式)。 函数索引有两大用处:

  • 优化业务 SQL 性能;
  • 配合虚拟列(Generated Column)。

先来看第一个, 优化业务 SQL 性能。

假设last_date建立了二级索引,下面这条SQL语句里仍有一个常见的错误,你知道是什么吗?

SELECT*FROM user  WHERE DATE_FORMAT(last_date,'%Y-%m')='2022-10'

DATE_FORMAT(last_date)不是索引,因此上述 SQL 无法使用二级索引last_date,会导致全表扫描。数据库规范要求查询条件中函数写在等式右边,而不能写在左边,就是这个原因。

要尽快解决这个问题,可以使用函数索引, 创建一个DATE_FORMAT(register_date) 的索引  

ALTERTABLE user 
ADD INDEX 
idx_func_last_date((DATE_FORMAT(last_date,'%Y-%m')));

覆盖索引

创建一个user表。

createtable T (ID int primary key,k intNOTNULL DEFAULT 0,index k(k))engine=InnoDB;

我们执行一条SQL语句

select ID from user where k between66and99,

此时只需要查询ID的值,  而ID的值已经在K索引树上了,因此可以直接提供查询结果,不需要回表。也就是说在这个查询里面,索引K已经“覆盖了”我们的查询需求,我们称之为覆盖索引。

从上面的例子我们可以看到,覆盖索引可以显著提升查询性能,索引使用覆盖索引是一个常用的性能优化手段。

最左前缀原则

以最左边的为起点任何连续的索引都能匹配上。

当创建(a,b,c)复合索引时,想要索引生效的话,只能使用 a和ab、ac和abc三种组合!

站在巨人的肩膀上:

  • 姜承尧——MySQL实战宝典
  • 林晓斌——MySQL实战45讲
  • Java业务开发常见错误100例

如果对您有帮助,欢迎关注我的微信公众号和我交流:ProgrammerAlan

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
17天前
|
Dubbo Java 应用服务中间件
微服务框架Dubbo环境部署实战
微服务框架Dubbo环境部署的实战指南,涵盖了Dubbo的概述、服务部署、以及Dubbo web管理页面的部署,旨在指导读者如何搭建和使用Dubbo框架。
68 17
微服务框架Dubbo环境部署实战
|
22天前
|
NoSQL 关系型数据库 MySQL
排行榜系统设计:高并发场景下的最佳实践
本文由技术分享者小米带来,详细介绍了如何设计一个高效、稳定且易扩展的排行榜系统。内容涵盖项目背景、技术选型、数据结构设计、基本操作实现、分页显示、持久化与数据恢复,以及高并发下的性能优化策略。通过Redis与MySQL的结合,确保了排行榜的实时性和可靠性。适合对排行榜设计感兴趣的技术人员参考学习。
46 7
排行榜系统设计:高并发场景下的最佳实践
|
3天前
|
缓存 分布式计算 Hadoop
HBase在高并发场景下的性能分析
HBase在高并发场景下的性能受到多方面因素的影响,包括数据模型设计、集群配置、读写策略及性能调优等。合理的设计和配置可以显著提高HBase在高并发环境下的性能。不过,需要注意的是,由于项目和业务需求的不同,性能优化并没有一劳永逸的解决方案,需要根据实际情况进行针对性的调整和优化。
22 8
|
14天前
|
自然语言处理 Java 网络架构
解锁跨平台微服务新纪元:Micronaut与Kotlin联袂打造的多语言兼容服务——代码、教程、实战一次打包奉送!
【9月更文挑战第6天】Micronaut是一款轻量级、高性能的Java框架,适用于微服务开发。它支持Java、Groovy和Kotlin等多种语言,提供灵活的多语言开发环境。本文通过创建一个简单的多语言兼容服务,展示如何使用Micronaut及其注解驱动特性实现REST接口,并引入国际化支持。无论是个人项目还是企业应用,Micronaut都能提供高效、一致的开发体验,成为跨平台开发的利器。通过简单的配置和代码编写,即可实现多语言支持,展现其强大的跨平台优势。
28 2
|
15天前
|
运维 监控 持续交付
深入浅出:微服务架构的设计与实战
微服务,一个在软件开发领域如雷贯耳的名词,它代表着一种现代软件架构的风格。本文将通过浅显易懂的语言,带领读者从零开始了解微服务的概念、设计原则及其在实际项目中的运用。我们将一起探讨如何将一个庞大的单体应用拆分为灵活、独立、可扩展的微服务,并分享一些实践中的经验和技巧。无论你是初学者还是有一定经验的开发者,这篇文章都将为你提供新的视角和深入的理解。
43 3
|
22天前
|
存储 缓存 监控
函数计算产品使用问题之调用sd生图时,怎么保证高并发场景正常运行
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
|
22天前
|
弹性计算 监控 Serverless
函数计算产品使用问题之如何处理银行转账场景遇到的高并发问题
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
|
24天前
|
消息中间件 缓存 Kafka
go-zero微服务实战系列(八、如何处理每秒上万次的下单请求)
go-zero微服务实战系列(八、如何处理每秒上万次的下单请求)
|
24天前
|
缓存 NoSQL Redis
go-zero微服务实战系列(七、请求量这么高该如何优化)
go-zero微服务实战系列(七、请求量这么高该如何优化)
|
24天前
|
缓存 NoSQL 数据库
go-zero微服务实战系列(五、缓存代码怎么写)
go-zero微服务实战系列(五、缓存代码怎么写)