当前位置: 首页 > article >正文

MySQL--》如何在MySQL中打造高效优化索引

目录

初识索引

索引结构

性能分析

索引使用

最左前缀法则

SQL提示使用

覆盖索引使用

前缀索引使用

索引失效情况


初识索引

索引(index):是帮助MySQL高效获取数据的数据结构(有序),在数据之外数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。

以下是有索引和没有索引查找数据的区别,没有索引就进行全表扫描,有索引就可以借助类似二叉查找树的方式进行查询数据,可以看到有索引查找的效率是十分高效的:

索引优缺点:可以通过以下表格的展示进行了解:

优势

劣势

提高数据检索的效率,降低数据库的IO成本

索引列也是要占用空间的

通过索引列对数据进行排序,降低数据排序的成本,降低CPU的消耗

索引大大提高了查询效率,同时却也降低更新表的速度,如对表进行INSERT、UPDATE、DELETE时,效率降低。

索引结构:MySQL的索引是在存储引擎层实现的,不同的存储引擎有不同的结构,场景的索引结构主要包含以下几种:

索引结构

描述

B+Tree索引

最常见的索引类型,大部分引擎都支持B+树索引

Hash索引

底层数据结构是用哈希表实现的,只有精确匹配索引列的查询才有效,不支持范围查询

R-tree(空间索引)

空间索引是MyISAM引擎的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少

Full-text(全文索引l)

是一种通过建立倒排索引l,快速匹配文档的方式。类似于Lucene,Solr,ES

索引支持:而不同的索引结构在存储引擎中的支持度也是不同的,在MySQL数据库当时,存储引擎的支持情况如下所示:

索引

InnDB

MyISAM

Memory

B+tree索引

支持

支持

支持

Hash索引

不支持

不支持

支持

R-tree索引

不支持

支持

不支持

Full-text

5.6版本之后支持

支持

不支持

索引分类:索引的常见分类如下所示:

分类

含义

特点

关键字

主键索引

针对于表中主键创建的索引

默认自动创建,只能有一个

PRIMARY

唯一索引

避免同一个表中某数据列中的值重复

可以有多个

UNIQUE

常规索引

快速定位特定数据

可以有多个

全文索引

全文索引查找的是文本中的关键词,而不是比较索引中的值

可以有多个

FULLTEXT

在InnoDB存储引擎中,根据索引的存储形式,又可以分为以下两种:

分类

含义

特点

聚集索引l(Clustered Index)

将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据

必须有,而且只有一个

二级索引(Secondary Index)

将数据与索引分开存储,索引结构的叶子节点关联的是对应的主键

可以存在多个

聚集索引选取规则:

1)如果存在主键,主键索引就是聚集索引

2)如果不存在主键,将使用第一个唯一(UNIQUE)索引作为聚集索引

3)如果表没有主键或没有合适的唯一索引,则lnnoDB会自动生成一个rowid作为隐藏的聚集索引

索引语法:索引操作语法及其基本案例如下所示:

-- 创建索引
create [unique | fulltext] index index_name on table_name (index_col_name,...);-- 查看索引
show index from table_name;-- 删除索引
drop index index_name on table_name;

索引结构

接下来我们开始讲解索引中常见的数据结构,如下所示:

B-Tree:多路平衡查找树,以一颗最大度数(max-degree)为5(5阶)的b-tree为例(每个节点最多存储4个key,5个指针):

我们可以通过在线网址查看b-tree的运行结果,如下所示插入100、65、169、368、900、556、780、35、215、1200、234、888、158、90、1000、88、120、268、250数据为例,得到结果如下所示:

B+Tree:所有的数据都会出现在叶子节点,并且叶子节点会形成一颗单向联表,每一个节点的指针都会指向下一颗节点的元素,非叶子节点担任索引的作用,

我们可以通过在线网址查看b-tree的运行结果,如下所示插入100、65、169、368、900、556、780、35、215、1200、234、888、158、90、1000、88、120、268、250数据为例,得到结果如下所示:

MySQL索引数据结构对经典的B+Tree进行了优化,在原B+Tree的基础上增加了一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的B+Tree,提高区间访问的性能:

Hash:哈希索引就是采用一定的hash算法,将键值换算成新的hash值映射到对应的槽位上然后存储在hash表中,如果两个(或多个)键值映射到一个相同的槽位上,它们就产生了hash冲突,也成为hash碰撞,可以通过链表来解决:

Hash索引特点:只能用于对等比较(=,in),不支持范围查询(between,>,<…);无法利用索引完成排序操作,查询效率高,通常只需要一次检索就可以了,效率通常要高于B+Tree索引。

性能分析

通过对SQL进行性能分析可以全面了解查询性能瓶颈,优化数据库设计,提升应用性能和可扩展性,节省资源改善用户体验并避免潜在的系统问题,定期进行性能分析是保证数据库健康支持业务扩展和优化开发的关键步骤,接下来开始讲解如何在SQL中进行性能分析:

SQL执行频率:MySQL客户端连接成功后,通过如下语句可以查询服务器状态信息,即当前数据库进行增删改查的访问频次:

show global status like 'Com_______';

慢查询日志:慢查询日志记录了所有执行时间超过指定参数(long_query_time,单位:秒,默认10秒)的所有SQL语句的日志,MySQL的慢查询日志默认没有开启,需要在MySQL的配置文件(/etc/my.cnf) 中配置如下信息,执行如下语句进行查看:

-- 查询MySQL慢日志查询
show variables like 'slow_query_log';-- 开启慢查询
slow_query_log=1;-- 设置慢日志的时间为2秒,SQL语句执行时间超过2秒就会视为慢查询,记录慢查询日志
long_query_time=2;

配置完毕之后,通过以下指令重新启动MysQL服务器进行测试查看慢日志文件中记录的信息/var/lib/mysql/localhost-slow.log。

profile详情:show profiles语句能够在做SQL优化时帮助我们了解时间都耗费到哪里去了,通过have_profiling参数,能够看到当前MysQL是否支持,执行语句如下:

-- 查看当前profile是否开启
select @@have_profiling;-- 默认profile关闭,可以通过如下开启
set profiling = 1;-- 查看每一条SQL的耗时基本情况
show profiles;-- 查看指定query_id的SQL语句各个阶段的耗时情况
show profile for query query_id;-- 查看指定query_id的SQL语句CPU的使用情况
show profile cpu for query query_id;

explain执行计划:explain或desc命令获取mysql如何执行select语句信息,包括在select语句执行过程中表如何连接和连接的顺序,语句如下:

-- 直接在select语句之前加上关键字explain/desc
explain select 字段列表 from 表名 where 条件;

explain执行计划各字段含义:

1)id:select查询的序列号表示查询中执行select子句或者是操作表的顺序,id相同执行顺序从上到下;id不同值越大越先执行。

2)select_type:表示select的类型,常见的取值有simple(简单表,即不使用表连接或者子查询)、primary(主查询,即外层的查询)、union(union中的第二个或者后面的查询语句)、subquery(select/where之后包含了子查询)等

3)type:表示连接类型,性能由好到差的连接类型为null、system、const、eq_ref、ref、range、index、all

4)possible_key:显示可能应用在这张表上的索引,一个或多个。

5)key:实际使用的索引,如果为null则没有使用索引。

6)key_len:表示索引中使用的字节数,该值为索引字段最大可能长度并非实际使用长度,在不损失精确性的前提下长度越短越好。

7)rows:mysql认为必须要执行查询的行数,在innodb引擎的表中是一个估计值可能并不总是准确的。

8)filtered:表示返回结果的行数占需读取行数的百分比,filtered的值越大越好。

索引使用

在使用索引之前,可以在未建立索引之前执行如下语句来验证SQL的耗时,以及创建索引之后再执行相同的SQL语句再看SQL的耗时:

-- 在未建立索引之前执行如下语句查看SQL的耗时
select * from 表名 where 条件='123';-- 针对字段创建索引
create index idx_sku_sn(任意创建) on 表名(字段);-- 然后再执行相同的SQL语句,再次查看SQL耗时
select * from 表名 where 条件='123';

索引的设计原则如下所示:

1)针对于数据量较大且查询比较频繁的表建立索引

2)针对于常作为查询条件(where)、排序(orderby)、分组(group by)操作的字段建立索引

3)尽量选择区分度高的列作为索引,尽量建立唯一索引区分度越高,使用索引的效率越高

4)如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点建立前缀索引

5)尽量使用联合索引减少单列索引,查询时联合索引很多时候可以覆盖索引,节省存储空间避免回表提高查询效率

6)要控制索引的数量,索引并不是多多益善,索引越多护索引结构的代价也就越大会影响增删改的效率

7)如果索引列不能存储NULL值请在创建表时使用NOTNULL约束它,当优化器知道每列是否包含NULL值时它可以更好地确定哪个索引最有效地用于查询

最左前缀法则

最左前缀法则:如果索引了多列(联合索引)是要遵守最左前缀法则的,最左前缀法则指的是查询从索引的最左列开始并且不跳过索引中的列,如果跳跃某一列索引部分将部分失效(后面的字段索引失效):

如下我们查看我们的员工表可以看到我们的员工表的索引情况,其中有主键索引和单个索引和联合索引:

如果我们进行联合索引的查询的时候,必须把最左侧的索引带上进行查询,如下才能得到结果:

如果我们把最左侧的索引删掉然后进行查询的话,查询的就不再是索引查询而是全表扫描了,当然如果是三个字段的联合查询,删除中间的那个,最后一个字段的查询也会失效的,并且联合查询的字段位置是没有关系的,只要有最左侧的字段,就是联合查询,还有一点就是要注意,如果要使用范围索引的联合查询,尽量使用>=这种带等于的进行判断,避免索引失效:

SQL提示使用

SQL提示是优化数据库的一个重要手段,简单来讲就是在SQL语句中加入一些人为的提示来达到优化操作的目的,如下所示:

-- use index 使用idx_user_name索引
explain select * from emp use index(idx_user_name) where name = '张翠山';-- ignore index 忽略idx_user_name索引
explain select * from emp ignore index(idx_user_name) where name = '张翠山';-- force index 强制使用idx_user_name索引
explain select * from emp force index(idx_user_name) where name = '张翠山';

如下我们设置的job是有两个索引的,一个联合索引,一个单个索引:

我们可以手动设置,让数据库走我们设置的单个索引:

覆盖索引使用

尽量使用覆盖索引(查询使用了索引,并且返回需求的列,在该索引中已经全部能够找到),减少select *,对于庞大数据来讲,如果采用select * 查询的话,可能会将没有设置索引的字段包含进去进行查询,可能会导致回表查询,造成不必要的性能浪费:

如果设置查询的数据列都能在索引列中找到,就可以一定程度上避免回表查询:

前缀索引使用

当字段类型为字符串(varchar,text等)时,有时候需要索引很长的字符串,这会让索引变得很大,查询的时候会浪费大量的磁盘IO从而影响查询效率,此时可以只将字符串的一部分前缀建立索引,这样就可以大大节约索引空间从而提高索引效率,语法如下所示:

create index idx_xxx on 表名(column(n));

前缀长度:可以根据索引的选择性来决定,而选择性是指不重复的索引值(基数)和数据表的记录总数的比值,索引选择性越高则查询效率越高,唯一索引的选择性是1,这是最好的索引选择性性能也是最好的,语法如下所示:

select count(distinct 字段) / count(*) from 表;
select count(distinct substring(字段, 1, 5)) / count(*) from 表;

索引失效情况

如果你在进行索引查询的时候,出现了索引失效的情况,可能是你进行了如下的误操作:

索引列运算:在索引列上进行运算操作,导致索引失效:

字符串引号:如果查询的字段是字符串类型,不加引号会触发隐式转换导致索引查询失效

模糊匹配:如果仅仅是尾部模糊匹配索引不会失效,如果是头部模糊匹配索引将失效:

or连接条件:用or分割开的条件,如果or前的条件中的列有索引而后面的列中没有索引,那么涉及的索引都不会被用到:

由于age没有索引,所以即使id有索引,索引也会失效,可以根据需要给age也建立索引:

-- id有索引而age没有索引,则整条语句就不是索引查询
explain select * from 表名 where id = 20 or age = 10

相关文章:

MySQL--》如何在MySQL中打造高效优化索引

目录 初识索引 索引结构 性能分析 索引使用 最左前缀法则 SQL提示使用 覆盖索引使用 前缀索引使用 索引失效情况 初识索引 索引(index)&#xff1a;是帮助MySQL高效获取数据的数据结构(有序)&#xff0c;在数据之外数据库系统还维护着满足特定查找算法的数据结构&…...

盛京开源社区加入 GitCode,书写东北开源生态新篇章

在数字化转型与开源技术蓬勃发展的浪潮下&#xff0c;开源社区已成为推动技术创新的核心力量。盛京开源社区&#xff08;SJOSC&#xff09;作为沈阳地区的开源交流平台&#xff0c;始终致力于连接开发者、企业及高校&#xff0c;构建区域技术生态圈。 现在&#xff0c;盛京开源…...

HTML转义和反转义工具类

HTML转义和反转义工具类 package com.common.utils;import cn.hutool.http.HTMLFilter; import org.apache.commons.lang3.StringUtils;/*** 转义和反转义工具类** author lxx*/ public class EscapeUtil {public static final String RE_HTML_MARK "(<[^<]*?>…...

网络运维学习笔记(DeepSeek优化版)005网工初级(HCIA-Datacom与CCNA-EI)链路层发现协议与VLAN技术

文章目录 一、链路层发现协议1.1 思科CDP协议1.2 华为LLDP协议 二、VLAN&#xff08;Virtual Local Area Network&#xff0c;虚拟局域网&#xff09;技术详解2.1 基本概念2.2 技术特性2.3 接口工作原理2.3.1 Access模式2.3.2 Trunk模式 2.4 厂商配置对比思科配置华为配置 2.5 …...

DeepSeek开源周Day4:三连发!突破 AI 训练瓶颈的立体解决方案,并行计算三剑客DualPipe、EPLB与Profile-data

项目地址&#xff1a; https://github.com/deepseek-ai/DualPipehttps://github.com/deepseek-ai/eplbhttps://github.com/deepseek-ai/profile-data 开源日历&#xff1a;2025-02-24起 每日9AM(北京时间)更新&#xff0c;持续五天 (4/5)&#xff01; ​ ​ 一、背景概述 …...

树莓百度百科更新!宜宾园区业务再添新篇

树莓集团宜宾园区业务不断拓展&#xff0c;主要体现在以下几个方面&#xff1a; 产业布局 -聚焦数字经济核心领域&#xff1a;涵盖软件开发、人工智能、大数据等&#xff0c;吸引众多上下游企业入驻&#xff0c;形成从芯片研发、软件开发到系统集成的完整产业链条。 -推进“双…...

RabbitMQ操作实战

1.RabbitMQ安装 RabbitMQ Windows 安装、配置、使用 - 小白教程-腾讯云开发者社区-腾讯云下载erlang&#xff1a;http://www.erlang.org/downloads/https://cloud.tencent.com/developer/article/2192340 Windows 10安装RabbitMQ及延时消息插件rabbitmq_delayed_message_exch…...

IO 和 NIO 有什么区别?

文章目录 阻塞模式与非阻塞模式数据处理方式通信模型应用场景 阻塞模式与非阻塞模式 IO&#xff1a;是阻塞式的 IO 操作。在传统的 IO 中&#xff0c;当一个线程执行读操作或者写操作时&#xff0c;该线程会被阻塞&#xff0c;直到操作完成。例如&#xff0c;在从文件读取数据…...

OpenWebUI配置异常的外部模型导致页面无法打开

一、使用Ollama关闭OpenAI OpenWebUI自带OpenAI的API设置&#xff0c;且默认是打开的&#xff0c;默认情况下&#xff0c;启动后&#xff0c;会不断的去连https://api.openai.com/v1&#xff0c;但是无法连上&#xff0c;会报错&#xff0c;但是不会影响页面&#xff0c;能正常…...

2025年度福建省职业院校技能大赛高职组“信息安全管理与评估”赛项规程样题模块二

模块二 网络安全事件响应、数字取证调查、应用程序安全 竞赛项目赛题 本文件为信息安全管理与评估项目竞赛-第二阶段样题&#xff0c;内容包括&#xff1a;网络安全事件响应、数字取证调查。 本次比赛时间为90分钟。 介绍 竞赛有固定的开始和结束时间&#xff0c;参赛队伍必须…...

鸿蒙兼容Mapbox地图应用测试

鸿蒙Next已经发布一段时间了&#xff0c;很多之前的移动端地图应用&#xff0c;纷纷都要求适配鸿蒙Next。作为开发者都清楚&#xff0c;所谓的适配其实都是重新开发&#xff0c;鸿蒙的开发语言和纯前端的Javascript不同&#xff0c;也可以Android原始开发的语言不同。鸿蒙自带的…...

java练习(45)

ps:题目来自力扣 两数相除 给你两个整数&#xff0c;被除数 dividend 和除数 divisor。将两数相除&#xff0c;要求 不使用 乘法、除法和取余运算。 整数除法应该向零截断&#xff0c;也就是截去&#xff08;truncate&#xff09;其小数部分。例如&#xff0c;8.345 将被截断…...

面试之《前端开发者如何优化页面的加载时间?》

前端开发者可以从多个方面入手优化页面的加载时间&#xff0c;以下是一些常见且有效的方法&#xff1a; 优化资源加载 压缩资源文件&#xff1a;对 HTML、CSS、JavaScript 文件进行压缩&#xff0c;去除不必要的空格、注释等&#xff0c;减小文件体积&#xff0c;加快下载速度…...

部署Flink1.20.1

1、设置环境变量 export JAVA_HOME/cluster/jdk export CLASSPATH.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jarp #export HIVE_HOME/cluster/hive export MYSQL_HOME/cluster/mysql export HADOOP_HOME/cluster/hadoop3 export HADOOP_CONF_DIR$HADOOP_HOME/etc/hadoop …...

iOS自归因详细介绍

iOS自归因详细介绍 自归因&#xff08;Self-Attribution&#xff09;是指应用或广告平台通过分析用户行为数据&#xff0c;确定用户安装应用的来源渠道。在iOS生态中&#xff0c;由于隐私政策的限制&#xff08;如App Tracking Transparency&#xff0c;ATT&#xff09;&#…...

影视后期工具学习之PR

pr剪辑之旅 第一节课 入门基础知识 1.了解影视基础术语 2.PR面板&首选项设置 首选项需要设置的选项: 自动保存: 修剪: 媒体: 媒体缓存: 经典面板设置,可以根据个人喜好做出改变: 3.展示与准备工作 新建序列:1.横板序列 2.竖版序列:</...

浏览器JS打不上断点,一点就跳到其他文件里。浏览器控制台 js打断点,指定的位置打不上断点,一打就跳到其他地方了。

关闭JavaScript 源代码映射&#xff0c;F12开发者模式 设置->偏好设置->源代码/来源->JavaScript 源代码映射。 肯定不是这个原因导致的&#xff0c;但这个办法可以暂时解决问题&#xff0c;点完这个东西就隐藏了webpack&#xff0c;有懂的来讲讲。 又浪费一个小时…...

XXE漏洞:原理、危害与修复方法详解

目录 一、XXE漏洞概述二、XXE漏洞原理三、XXE漏洞危害1. 任意文件读取2. 命令执行3. 拒绝服务攻击(DoS)4. SSRF攻击四、XXE漏洞修复方法1. 禁用外部实体JavaPythonPHP2. 输入验证和过滤3. 安全配置服务器4. 升级解析器版本五、总结一、XXE漏洞概述 XXE(XML External Entity…...

C#与AI的交互(以DeepSeek为例)

C#与ai的交互 与AI的交互使用的Http请求的方式&#xff0c;通过发送请求&#xff0c;服务器响应ai生成的文本 下面是完整的代码&#xff0c;我这里使用的是Ollama本地部署的deepseek&#xff0c;在联网调用api时&#xff0c;则url会有不同 public class OllamaRequester {[Se…...

Qt——使用QtConcurrent::run开启的线程,程序退出后仍在后台运行的解决方法(QFutureWatcher监视线程)

【系列专栏】:博主结合工作实践输出的,解决实际问题的专栏,朋友们看过来! 《项目案例分享》 《极客DIY开源分享》 《嵌入式通用开发实战》 《C++语言开发基础总结》 《从0到1学习嵌入式Linux开发》 《QT开发实战》 《Android开发实...

DeepSeek-R1:通过强化学习激发大语言模型的推理能力

注&#xff1a;此文章内容均节选自充电了么创始人&#xff0c;CEO兼CTO陈敬雷老师的新书《自然语言处理原理与实战》&#xff08;人工智能科学与技术丛书&#xff09;【陈敬雷编著】【清华大学出版社】 文章目录 DeepSeek大模型技术系列三DeepSeek大模型技术系列三》DeepSeek-…...

Xcode如何高效的一键重命名某个关键字

1.选中某个需要修改的关键字&#xff1b; 2.右击&#xff0c;选择Refactor->Rename… 然后就会出现如下界面&#xff1a; 此时就可以一键重命名了。 还可以设置快捷键。 1.打开Settings 2.找到Key Bindings 3.搜索rename 4.出现三个&#xff0c;点击一个地方设置后其…...

smolagents学习笔记系列(八)Examples - Master you knowledge base with agentic RAG

这篇文章锁定官网教程中 Examples 章节中的 Master you knowledge base with agentic RAG 文章&#xff0c;主要介绍了如何将 agent 和 RAG 结合使用。 官网链接&#xff1a;https://huggingface.co/docs/smolagents/v1.9.2/en/examples/rag&#xff1b; Agentic RAG 在之前的…...

数据挖掘工程师的技术图谱和学习路径

数据挖掘工程师的技术图谱和学习路径: 1.基础知识 数据挖掘工程师是负责从大量数据中发现潜在模式、趋势和规律的专业人士。以下是数据挖掘工程师需要掌握的基础知识: 数据库知识:熟悉关系数据库和非关系数据库的基本概念和操作,掌握SQL语言。 统计学基础:了解统计学的基…...

机器学习数学基础:37.偏相关分析

偏相关分析教程 一、偏相关分析是什么 在很多复杂的系统中&#xff0c;比如地理系统&#xff0c;会有多个要素相互影响。偏相关分析就是在这样多要素构成的系统里&#xff0c;不考虑其他要素的干扰&#xff0c;专门去研究两个要素之间关系紧密程度的一种方法。用来衡量这种紧…...

DevSecOps普及:安全与开发运维的深度融合

一、引言 随着软件开发模式的演进&#xff0c;DevOps已成为现代软件工程的主流实践。然而&#xff0c;在传统的DevOps流程中&#xff0c;安全往往被视为开发和运维之外的额外环节&#xff0c;导致安全漏洞在产品交付后才被发现&#xff0c;增加了修复成本和风险。为了解决这一…...

MySQL 8.4 SQL 全攻略:所有知识点与实战场景

一、引言 MySQL 作为一款广泛使用的开源关系型数据库管理系统&#xff0c;在数据存储和管理领域占据着重要地位。MySQL 8.4 版本在性能、功能和安全性等方面都有了显著的提升。本文将全面介绍 MySQL 8.4 中 SQL 的各种知识点&#xff0c;并结合实战场景进行详细讲解&#xff0…...

AVA面试_进阶部分_kafka面试题

1.Kafka 的设计时什么样的呢&#xff1f; Kafka 将消息以 topic 为单位进行归纳 将向 Kafka topic 发布消息的程序成为 producers. 将预订 topics 并消费消息的程序成为 consumer. Kafka 以集群的方式运行&#xff0c;可以由一个或多个服务组成&#xff0c;每个服务叫做一个…...

Redis源码剖析之GEO——Redis是如何高效检索地理位置的?

Redis GEO 用做存储地理位置信息&#xff0c;并对存储的信息进行操作。通过geo相关的命令&#xff0c;可以很容易在redis中存储和使用经纬度坐标信息。Redis中提供的Geo命令有如下几个&#xff1a; geoadd&#xff1a;添加经纬度坐标和对应地理位置名称。geopos&#xff1a;获取…...

【Java 优选算法】模拟

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 模拟算法的思路比较简单,根据题目描述列出流程,找出规律,将流程转化为代码 替换所有的问号 题目链接 解法 直接根据题目给出条件模拟 示例,找出规律 1.先找出字符?,再…...