目录
索引定义
索引优缺点
优点
缺点
索引类型
按功能逻辑划分
普通索引
唯一索引
主键索引
全文索引
按物理实现划分
聚集索引(clustered index)
非聚集索引(non-clustered index)
按字段个数划分
单一索引
联合索引
最左匹配原则
按索引结构划分
使用总结
推荐使用" >推荐使用
不推荐使用或索引失效情况" >不推荐使用或索引失效情况
首页 数据库 mysql教程 MySQL索引给拿捏住了

MySQL索引给拿捏住了

Mar 29, 2022 pm 05:28 PM
mysql

<p>本篇文章给大家带来了关于<a href="https://www.php.cn/course/list/51.html" target="_blank" textvalue="mysql视频教程">mysql</a>的相关知识,其中主要介绍了关于mysql索引的相关问题,包括了索引按照逻辑功能划分、按照物理实现划分、按照字段个数划分等索引类型问题,希望对大家有帮助。</p> <p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/6242cfce991a1216.jpg" class="lazy" alt="MySQL索引给拿捏住了" ></p> <p>推荐学习:<a href="https://www.php.cn/course/list/51.html" target="_blank" textvalue="mysql视频教程">mysql教程</a></p> <p>在 SQL 优化中,索引是至关重要的一环,能给查询效率带来质的飞跃,但是索引并不是万能的,不合理的索引设计甚至会拖慢查询效率。</p> <h2 id="索引定义">索引定义</h2> <p>索引是一种专门用于帮助 SQL 高效获取数据的数据结构,一个常用的例子是,索引类似于一本书的目录,可以快速对特定值进行定位和查找,从而大大加快数据查询的效率。实际上,索引也是一张表,这张表保存了主键与索引字段,并指向实体表的记录(类似指针)。</p> <h2 id="索引优缺点">索引优缺点</h2> <h3 id="strong-优点-strong"><strong>优点</strong></h3> <ul> <li>索引大大减小了服务器需要扫描的数据量</li> <li>索引可以帮助服务器避免排序和临时表</li> <li>索引可以将随机IO变成顺序IO</li> <li>索引对于InnoDB(对索引支持行级锁)非常重要,InnoDB仅对需要访问的元组加锁,而索引能够减少InnoDB访问的元组数。如果查询不能使用索引,MySQL会进行全表扫描,并锁住每一个元组,不管是否真正需要。</li> </ul> <h3 id="strong-缺点-strong"><strong>缺点</strong></h3> <ul> <li>虽然索引大大提高了查询速度,同时却会降低更新表的速度。因为更新表时,MySQL不仅要保存数据,还要保存索引文件。因此,对应更新非常频繁的字段,通常不建议使用索引。</li> <li>建立索引会占用磁盘空间。</li> <li>如果某个数据列包含许多重复的内容,为它建立索引效果就很差,这个性质称为索引的选择性:不重复的索引值和数据表中的记录总数的比值。索引的选择性越高则查询效率越高。比如对性别字段建立索引,一百万条数据,只有男女两种可能,索引选择性为五十万分之一,索引效果就很差</li> <li>对于非常小的表,索引意义不大,大部分情况下简单的全表扫描更高效。</li> </ul> <p>因此应该只为最经常查询和最经常排序的数据列建立索引。MySQL里同一个数据表里的索引总数限制为16个。</p> <h2 id="索引类型">索引类型</h2> <h2 id="按功能逻辑划分">按功能逻辑划分</h2> <p>从功能逻辑来划分,索引主要分为 普通索引、唯一索引、主键索引和全文索引</p> <h3 id="strong-普通索引-strong"><strong>普通索引</strong></h3> <p>最基本的索引,它没有任何限制。普通索引(由关键字KEY或INDEX定义的索引)的唯一任务是加快对数据的访问速度。因此,应该只为那些最经常出现在查询条件(WHERE column = …)或排序条件(ORDER BY column)中的数据列创建索引。</p> <p>普通索引的创建有三种方式。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"># 创建索引CREATE INDEX idx_username ON user_tbl(username);# 对于字符串字段,可以手动指定长度,如 user_tbl(username(5)),表示只用前五个字符来做索引,可以进一步加快查询效率,索引长度要小于字段长度# 修改表结构ALTER TABLE user_tbl ADD INDEX idx_username (username)# 创建表的时候直接指定,如CREATE TABLE user_tbl(  ID INT NOT NULL,  username VARCHAR(16) NOT NULL,  INDEX idx_username (username) );</pre><div class="contentsignin">登录后复制</div></div> <p>删除索引</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">DROP INDEX idx_username ON user_tbl;</pre><div class="contentsignin">登录后复制</div></div> <p>查看索引</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">SHOW INDEX FROM user_tbl;</pre><div class="contentsignin">登录后复制</div></div> <h3 id="strong-唯一索引-strong"><strong>唯一索引</strong></h3> <p>它与前面的普通索引类似,不同的就是:普通索引允许被索引的数据列包含重复的值。而唯一索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。</p> <p>唯一索引的创建跟普通索引类似:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">#创建索引 CREATE UNIQUE INDEX idx_username ON user_tbl(username); # 修改表结构 ALTER TABLE user_tbl ADD UNIQUE idx_username (username) # 创建表的时候直接指定 CREATE TABLE user_tbl(  ID INT NOT NULL,  username VARCHAR(16) NOT NULL,  UNIQUE idx_username (username)  );</pre><div class="contentsignin">登录后复制</div></div> <h3 id="strong-主键索引-strong"><strong>主键索引</strong></h3> <p>它是一种特殊的唯一索引,不允许有空值。一张表只能有一个主键,一般是在建表的时候同时创建。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">CREATE TABLE user_tbl(  ID INT NOT NULL,  username VARCHAR(16) NOT NULL,  PRIMARY KEY(ID)  );</pre><div class="contentsignin">登录后复制</div></div> <p>与之类似的是外键索引,如果为某个外键字段定义了一个外键约束条件,MySQL就会定义一个内部索引来帮助自己以最有效率的方式去管理和使用外键约束条件。</p> <h3 id="strong-全文索引-strong"><strong>全文索引</strong></h3> <p>在上一篇文章 MySQL 基础语法 中,我们说过如果使用了 LIKE + % 开头,就索引会失效,那么当我们需要前后都模糊搜索的需求(如 LIKE ‘%hello%’),就需要使用全文索引,需要注意的是,Innodb 只有在 5.6 版本之后才支持全文索引。</p> <p>全文索引的创建和删除:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"># 创建的两种方法 CREATE FULLTEXT INDEX idx_name ON tbl_name(field_name); ALTER TABLE tbl_name ADD FULLTEXT INDEX idx_name(field_name); # 删除的两种方法 DROP INDEX idx_name ON tbl_name; ALTER TABLE tbl_name DROP INDEX idx_name;</pre><div class="contentsignin">登录后复制</div></div> <p>使用全文索引进行全模糊匹配的语法为:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">SELECT XXX FROM tbl_name WHERE match(field_name) against('xxx'); # 比如对 user_tbl 的 user_name 字段加了全文索引 # 查询结果等效于 SELECT user_name, user_id FROM user_tbl WHERE user_name LIKE '%hello%'; SELECT user_name, user_id FROM user_tbl WHERE match(user_name) against('hello');</pre><div class="contentsignin">登录后复制</div></div> <p>使用 explain 检查,可以发现 fulltext 索引生效。<br><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/681b26f4de7f637e6cc2370039b2ea38-0.png" class="lazy" alt="在这里插入图片描述"></p> <h2 id="按物理实现划分">按物理实现划分</h2> <p>按物理实现方式来划分,通常可以分为聚集索引和非聚集索引。</p> <h3 id="strong-聚集索引-clustered-index-strong"><strong>聚集索引(clustered index)</strong></h3> <p>存储内容是按照聚集索引排序的,聚集索引的顺序和行记录的顺序一致,一张表只能有一个聚集索引。聚集索引的叶子节点直接储存聚集索引指向的内容,因此查询的时候只需要进行一次查找。</p> <p>聚集索引在创建主键时自动生成,如果没有主键,则根据第一个不为空的唯一索引自动生成,如果还没有,则自动生成一个隐式的聚集索引。</p> <p>需要注意的是,在进行查询操作的时候,聚集索引的效率更高,因为少了一次查找;但是进行修改操作的时候,效率比非聚集索引低,因为直接修改了数据内容,为了标准数据内容的顺序和聚集索引顺序一致,会对数据页重新排序。</p> <h3 id="strong-非聚集索引-non-clustered-index-strong"><strong>非聚集索引(non-clustered index)</strong></h3> <p>非聚集索引虽然索引项是顺序存储的,但是索引项对应的内容是随机存储的,系统会维护单独的索引表来存储索引。</p> <p>非聚集索引的叶子节点存储的是数据的地址,查询非聚集索引的时候,系统会进行两次查找,先查找索引,再查找索引对应位置的数据。因此非聚集索引也叫二级索引或者辅助索引。</p> <h2 id="按字段个数划分">按字段个数划分</h2> <p>按字段个数可以把索引分为单一索引和联合索引。</p> <h3 id="strong-单一索引-strong"><strong>单一索引</strong></h3> <p>索引字段只有一列时为单一索引,上述所有索引都是单一索引。</p> <h3 id="strong-联合索引-strong"><strong>联合索引</strong></h3> <p>将多个字段组合在一起创建的索引叫联合索引。如下:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">ALTER TABLE user_tbl ADD INDEX idx_name_city_age (username,city,age);</pre><div class="contentsignin">登录后复制</div></div> <h4 id="最左匹配原则">最左匹配原则</h4> <p>建立这样的联合索引,其实是相当于分别建立了下面三组联合索引:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">usernname,city,age usernname,city usernname</pre><div class="contentsignin">登录后复制</div></div> <p>为什么没有 city,age 这样的联合索引呢?这是因为MySQL联合索引的<strong>最左匹配原则</strong>,只会按照最左优先的顺序进行索引匹配,也就是说,(x,y,z) 和 (z,y,x) 是不同的索引,即使是使用联合索引中的字段查询,联合索引也有可能失效。</p> <p>对于 (x,y,z),只有在以下查询条件联合索引会生效:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">WHERE x = 1WHERE x = 1 AND y = 1WHERE x = 1 AND y = 1 AND z = 1</pre><div class="contentsignin">登录后复制</div></div> <p>对于其他情况,比如 <code>WHERE y = 1</code> 、<code>WHERE y = 1 AND z = 1</code> 等,就不会匹配联合索引,索引失效,注意对于 <code>WHERE x = 1 AND z = 1</code>,联合索引会对 x 生效,但是对 z 不生效。</p> <p>可以扩展了解一下,理论上最左匹配原则中索引对 where 中子句的顺序也是敏感的,但是由于MySQL的查询优化器会自动调整 where 子句的条件顺序以使用适合的索引,所以实际上 where 子句顺序不影响索引的效果。</p> <p>要注意的是,如果联合索引查询过程中有范围查询,就会停止匹配,比如下面的语句中, z 字段不能使用到索引:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">WHERE x = 1 AND y > 2 AND z = 3</pre><div class="contentsignin">登录后复制</div></div> <p>顺便提一下,可以用 <code>explain</code> 命令来查看在某个查询语句中索引是否生效,具体用法请参考官网文档。</p> <p>如果分别在 x, y, z 上建立单列索引,让该表有3个单列索引,索引效率也会大不一样,在联合索引生效的情况下,单个索引的效率远远低于联合索引。这是由 MySQL 查询优化器的执行顺序决定的,在执行一条查询 sql 时,针对索引的选择大致有如下步骤:</p> <ol> <li>MySQL 优化器根据搜索条件,找出所有可能使用的索引</li> <li>计算全表扫描的代价</li> <li>计算使用不同索引执行查询的代价</li> <li>对比各种执行方案的代价,找出成本最低的那一个</li> </ol> <p>因此,虽然有多个单列索引,但 MySQL 只能用到其中的那个系统认为似乎是最有效率的,其他的就会失效。</p> <h2 id="按索引结构划分">按索引结构划分</h2> <p>不同的 mysql 数据引擎支持不同结构的索引,按结构划分,常用的索引为 B+树索引、Hash 索引、FULLTEXT索引 等,将在下一篇文章 MySQL 索引结构 中介绍。</p> <h2 id="使用总结">使用总结</h2> <p>接下来我们来简单总结一下在什么场景下推荐使用索引。</p> <h2 id="span-style-font-size-px-推荐使用-span"><span style="font-size: 16px;">推荐使用</span></h2> <ul style="list-style-type: disc;"> <li><p>WHERE, GROUP BY, ORDER BY 子句中的字段</p></li> <li> <p>多个单列索引在多条件查询是只会有一个最优的索引生效,因此多条件查询中最好创建联合索引。</p> <p>联合索引的时候必须满足最左匹配原则,并且最好考虑到 sql 语句的执行顺序,比如 <code>WHERE a = 1 GROUP BY b ORDER BY c</code>, 那么联合索引应该设计为 <code>(a,b,c)</code>,因为在上一篇文章 MySQL 基础语法 中我们介绍过,mysql 查询语句的执行顺序 WHERE > GROUP BY > ORDER BY。</p> </li> <li><p>多张表 JOIN 的时候,对表连接字段创建索引。</p></li> <li><p>当 SELECT 中有不在索引中的字段时,会先通过索引查询出满足条件的主键值,然后通过主键<code>回表</code>查询出所有的 SELECT 中的字段,影响查询效率。因此如果 SELECT 中的内容很少,为了避免回表,可以把 SELECT 中的字段都加到联合索引中,这也就是宽索引的概念。但是需要注意,如果索引字段过多,存储和维护索引的成本也会增加。</p></li> </ul> <h2 id="span-style-font-size-px-不推荐使用或索引失效情况-span"><span style="font-size: 16px;">不推荐使用或索引失效情况</span></h2> <ul style="list-style-type: disc;"> <li><p>数据量很小的表</p></li> <li><p>有大量重复数据的字段</p></li> <li><p>频繁更新的字段</p></li> <li><p>如果对索引字段使用了函数或者表达式计算,索引失效</p></li> <li><p>innodb OR 条件没有对所有条件创建索引,索引失效</p></li> <li><p>大于小于条件 <code><</code> <code>></code>,索引是否生效取决于命中的数量比例,如果命中数量很多,索引生效,命中数量很小,索引失效</p></li> <li><p>不等于条件 <code>!=</code> <code><></code>,索引失效</p></li> <li><p>LIKE 值以 <code>%</code> 开头,索引失效</p></li> </ul> <p>推荐学习:<a href="https://www.php.cn/course/list/51.html" target="_blank" textvalue="mysql视频教程">mysql视频教程</a></p>

以上是MySQL索引给拿捏住了的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

mysql:简单的概念,用于轻松学习 mysql:简单的概念,用于轻松学习 Apr 10, 2025 am 09:29 AM

MySQL是一个开源的关系型数据库管理系统。1)创建数据库和表:使用CREATEDATABASE和CREATETABLE命令。2)基本操作:INSERT、UPDATE、DELETE和SELECT。3)高级操作:JOIN、子查询和事务处理。4)调试技巧:检查语法、数据类型和权限。5)优化建议:使用索引、避免SELECT*和使用事务。

phpmyadmin怎么打开 phpmyadmin怎么打开 Apr 10, 2025 pm 10:51 PM

可以通过以下步骤打开 phpMyAdmin:1. 登录网站控制面板;2. 找到并点击 phpMyAdmin 图标;3. 输入 MySQL 凭据;4. 点击 "登录"。

MySQL:世界上最受欢迎的数据库的简介 MySQL:世界上最受欢迎的数据库的简介 Apr 12, 2025 am 12:18 AM

MySQL是一种开源的关系型数据库管理系统,主要用于快速、可靠地存储和检索数据。其工作原理包括客户端请求、查询解析、执行查询和返回结果。使用示例包括创建表、插入和查询数据,以及高级功能如JOIN操作。常见错误涉及SQL语法、数据类型和权限问题,优化建议包括使用索引、优化查询和分表分区。

为什么要使用mysql?利益和优势 为什么要使用mysql?利益和优势 Apr 12, 2025 am 12:17 AM

选择MySQL的原因是其性能、可靠性、易用性和社区支持。1.MySQL提供高效的数据存储和检索功能,支持多种数据类型和高级查询操作。2.采用客户端-服务器架构和多种存储引擎,支持事务和查询优化。3.易于使用,支持多种操作系统和编程语言。4.拥有强大的社区支持,提供丰富的资源和解决方案。

redis怎么使用单线程 redis怎么使用单线程 Apr 10, 2025 pm 07:12 PM

Redis 使用单线程架构,以提供高性能、简单性和一致性。它利用 I/O 多路复用、事件循环、非阻塞 I/O 和共享内存来提高并发性,但同时存在并发性受限、单点故障和不适合写密集型工作负载的局限性。

MySQL和SQL:开发人员的基本技能 MySQL和SQL:开发人员的基本技能 Apr 10, 2025 am 09:30 AM

MySQL和SQL是开发者必备技能。1.MySQL是开源的关系型数据库管理系统,SQL是用于管理和操作数据库的标准语言。2.MySQL通过高效的数据存储和检索功能支持多种存储引擎,SQL通过简单语句完成复杂数据操作。3.使用示例包括基本查询和高级查询,如按条件过滤和排序。4.常见错误包括语法错误和性能问题,可通过检查SQL语句和使用EXPLAIN命令优化。5.性能优化技巧包括使用索引、避免全表扫描、优化JOIN操作和提升代码可读性。

MySQL的位置:数据库和编程 MySQL的位置:数据库和编程 Apr 13, 2025 am 12:18 AM

MySQL在数据库和编程中的地位非常重要,它是一个开源的关系型数据库管理系统,广泛应用于各种应用场景。1)MySQL提供高效的数据存储、组织和检索功能,支持Web、移动和企业级系统。2)它使用客户端-服务器架构,支持多种存储引擎和索引优化。3)基本用法包括创建表和插入数据,高级用法涉及多表JOIN和复杂查询。4)常见问题如SQL语法错误和性能问题可以通过EXPLAIN命令和慢查询日志调试。5)性能优化方法包括合理使用索引、优化查询和使用缓存,最佳实践包括使用事务和PreparedStatemen

使用 Redis Exporter 服务监控 Redis Droplet 使用 Redis Exporter 服务监控 Redis Droplet Apr 10, 2025 pm 01:36 PM

有效监控 Redis 数据库对于保持最佳性能、识别潜在瓶颈和确保整体系统可靠性至关重要。 Redis Exporter Service 是一个强大的实用程序,旨在使用 Prometheus 监控 Redis 数据库。 本教程将指导您完成 Redis Exporter Service 的完整设置和配置,确保您无缝建立监控解决方案。通过学习本教程,您将实现完全可操作的监控设置

See all articles