目录
索引 ( index)是帮助MysqL 高效获取数据 的 数据结构 (有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。
| |
![]() | ![]() |
注意:上述二叉树索引结构的只是一个示意图,并不是真实的索引结构。
| 优势 | 劣势 |
|
|
MySQL的索引是在存储引擎层实现的,不同的存储引擎有不同的结构,主要包含以下几种:
| 索引结构 | 描述 |
| B+Tree索引 | 最常见的索引类型,大部分引擎都支持B+树索引。 |
| Hash索引 | 底层数据结构是用哈希表实现的,只有精确匹配索引列的查询才有效,不支持范围查询。 |
| R-tree (空间索引) | 空间索引是MyISAM引擎的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少 |
| Full-text (全文索引) | 是一种通过建立倒排索引,快速匹配文档的方式。类似于Lucene,Solr,ES。 |
MySQL索引数据结构对经典的B+Tree进行了优化。在原B+Tree的基础上,增加一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的B+Tree,提高区间访问的性能。

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

① Hash索引特点:
② 存储引擎支持:在MsaL中,支持hash索引的是Memory引擎,而innoD8中具有自适应hash功能,hash索引是存储引擎根据B+Tree索引在指定条件下自动构建的。
思考:为什么InnoDB存储引擎选择使用B+Tree索引结构?(面试题)
- 相对于二叉树,层级更少,搜索效率越高。
- 对于B-tree,无论是叶子节点还是非叶子节点,都会保存数据,这样导致一页中存储的键值减少,指针跟着减少,要同样保存大量数据,只能增加树的高度,导致性能降低。
- 相对Hash索引,B+Tree支持范围匹配以及排序操作。
| 分类 | 含义 | 特点 | 关键字 |
| 主键索引 | 针对于表中主键创建的索引 | 默认自动创建,只能有一个 | PRIMARY |
| 唯一索引 | 避免同一个表中某数据列中的值重复 | 可以有多个 | UNIQUE |
| 常规索引 | 快速定位特定数据 | 可以有多个 | |
| 全文索引 | 全文索引查找的是文本中的关键词,而不是比较索引中的值 | 可以有多个 | FULLTEXT |
在InnoDB存储引擎中,根据索引的存储形式,又可以分为以下两种:
| 分类 | 含义 | 特点 |
| 聚集索引 (Clustered lndex) | 将数据存储与索引放到一块,索引结构的叶子节点保存了行数据 | 必须有而且只有一个 |
| 二级索引(Secondary lndex) | 将数据与索引分开存储,索引结构的叶子节点关联的是对应主键 | 可以存在多个 |
聚集索引选取规则:
![]() |
| 回表查询:先根据二级索引拿到主键值,再根据主键值走聚集索引拿到这一行的数据。 |
思考:以下SQL语句中,哪个执行效率高?为什么?
解答:第一个执行效率高。根据 id 直接找聚集(主键)索引构造的B+Tree,直接找到行数据返回;根据 name字段 需要先到二级索引的B+Tree上查找name对应的 primary key 的值,然后再回表查询去聚集索引的B+Tree上查找对应的行数据。
示例练习:根据下列的需求,完成索引的创建
- name 字段为姓名字段,该字段的值可能会重复,为该字段创建索引。
- phone 手机号字段的值,是非空,且唯一的,为该字段创建唯一索引。
- 为 profession、age、status 创建联合索引。
- 为 email 建立合适的索引来提升查询效率。
show index from tb_user;

-- 1. name 字段为姓名字段,该字段的值可能会重复,为该字段创建索引。
create index idx_user_name on tb_user (name);
-- 2. phone 手机号字段的值,是非空,且唯一的,为该字段创建唯一索引。
create unique index idx_user_phone on tb_user(phone);
-- 3. 为 profession、age、status 创建联合索引。
create index idx_user_pro_age_stu on tb_user(profession,age,status);
-- 4. 为 email 建立合适的索引来提升查询效率。
create index idx_user_email on tb_user(email);

MySQL客户端连接成功后,通过show [ session|global ] status 命令可以提供服务器状态信息。通过如下指令,可以查看当前数据库的INSERT、UPDATE、DELETE、SELECT的访问频次: SHOW GLOBAL STATUS LIKE ' Com_ _ _ _ _ ';(一个下划线一个字符)

通过这种方式查看SQL执行频率,为SQL优化提供支撑。

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

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

![]() | ![]() |

EXPLAIN 或者 DESC 命令获取MySQL 如何执行 SELECT语句的信息,包括在SELECT语句执行过程中表如何连接和连接的顺序。语法:


EXPLAIN执行计划各字段含义:
> 多对多的多表关联:id相同,执行顺序从上到下
> 子查询( 查询选修了"MySQL"课程的学生 ):id不同,值越大,越先执行

我们发现执行一条数据的查询用时20.78秒,效率极低,原因在于:因为表中 id 为主键,默认主键索引,而 sn字段没有索引,所以效率低。


PS:以上证明了索引对于查询效率的提升。
示例:联合索引idx_user_pro_age_sta

explain select * from tb_user
where profession = '软件工程' and age = 31 and status = '0' ;

explain select * from tb_user
where profession = '软件工程';

explain select * from tb_user where age = 31 and status = '10';

explain select * from tb_user
where age = 31 and status = '0' and profession = '软件工程';

联合索引中,出现范围查询(>,<),范围查询右侧的列索引失效。
explain select * from tb_user
where profession = '软件工程'and age > 30 and status = '0';

explain select * from tb_user
where profession = '软件工程'and age >= 30 and status = '0';

explain select * from tb_user where substring(phone,10,2) = '15';

explain select * from tb_user
where profession='软件工程' and age = 31 and status = 0;

explain select * from tb_user where profession like '软件%';

explain select * from tb_user where profession like '%工程';

explain select * from tb_user where id = 10 or age = 23;

由于age没有索引,即使id有索引,索引也会失效,索引需要针对于age也要建立索引。
通过小例子了解SQL提示:
已知profession查询会用到复合索引,那么如果我们再创建单列索引。
create index idx_user _pro on tb_user (profession);那么当我们再次查询时,那么将会选择用复合索引还是单列索引呢?
因此:SQL提示,是优化数据库的一个重要手段,简单来说,就是在SQL语句中加入一些人为的提示来达到优化操作的目的。



之前我们在基础篇中提到,尽量不要使用select * ,一方面不直观,可读性差,另一方面效率低下。所以尽量使用覆盖索引(查询使用了索引,并且需要返回的列,在该索引中已经全部能够找到) 。
explain select id,pofession,age,status from tb_user
where profession = '软件工程' and age = 31 and status = '0';
解释:id,pofession,age之间存在联合索引,属于二级索引,可以拿到我们想要找到的数据直接返回,不需要再查找聚集索引。

explain select id,profession,age,status, name from tb_user
where profession = '软件工程' and age = 31 and status = '0';
解释:id,profession,age,status通过二级索引都可以查询到,但是name字段不可以,需要通过id再到聚集索引中进行查找name字段即回表查询。

知识小贴纸:
- using index condition ;查找使用了索引,但是需要回表查询数据。
- using where; using index:查找使用了索引,但是需要的数据都在索引列中能找到,所以不需要回表查询数据。
当字段类型为字符串(varchar, text等)时,有时候需要索引很长的字符串,这会让索引变得很大,查询时,浪费大量的磁盘lO,影响查询效率。此时可以只将字符串的一部分前缀,建立索引,这样可以大大节约索引空间,从而提高索引效率。
| select count(distinct ermail) / count(*) from tb_user ; | ![]() |
| select coint(distinct substring(email,1,5)) / count(*) from tb_user ; | ![]() |
-- 创建前缀索引 长度为5
create index idx_email_5 on tb_user (email(5));
explain select * from tb_user where email = 'daqiao666@sina.com' ;

单列索引情况:
explain select id, phone, name from tb_user
where phone = '123456789' and name = '张三';

多条件联合查询时,MySQL优化器会评估哪个字段的索引效率更高,会选择该索引完成本次查询。
而我们想要使用我们创建联合索引,不使用单列索引:
create unqiue index idx_user_phone_name on tb_user (phone, name) ;
explain select id,phone, name from tb_user use index(idx_user_phone_name)
where phone = '123456789' and name = '张三';

我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最
我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01 客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02 数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit
文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co
我正在尝试在Rails上安装ruby,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf
文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,