MySQL调优(二):创建高性能的索引

目录

1、索引基础

索引有效的查询类型

索引的限制

2、索引的优点

3、高性能的索引策略

3.1、独立的列

3.2、前缀索引和索引选择性

3.3、多列索引

3.4、选择合适的索引列顺序

3.5、聚簇索引

3.6、覆盖索引

3.7、使用索引扫描来做排序

3.8、冗余和重复索引

3.9、未使用的索引


1、索引基础

索引有效的查询类型

  • 全值匹配:和索引中的所有列进行匹配。
  • 匹配最左前缀:只匹配前面几列。
  • 匹配列前缀:只匹配某一列的值的开头部分。
  • 匹配范围值
  • 精确匹配某一列并范围匹配另外一列
  • 只访问索引的查询:查询只需要访问索引,而无须访问数据行,即覆盖索引。

因为索引树中的节点是有序的,所以除了按值查找之外,索引还可以用于查询中的ORDER BY和GROUP BY操作。

索引的限制

  • 如果不是按照索引的最左列开始查找,则无法使用索引。
  • 不能跳过索引中的列。
  • 如果查询中有某个列的范围查询,则其右边所有列都无法使用索引优化查找。

2、索引的优点

  • 索引大大减少了服务器需要扫描的数据量。
  • 索引可以帮助服务器避免排序和临时表。
  • 索引可以将随机I/O变为顺序I/O。

3、高性能的索引策略

3.1、独立的列

独立的列是指索引列不能是表达式的一部分,也不能是函数的参数。

3.2、前缀索引和索引选择性

通常可以索引开始的部分字符,这样可以大大节约索引空间,从而提高索引效率。但这样也会降低索引的选择性。索引的选择性是指,不重复的索引值(也称为基数)和数据表的记录总数(#T)的比值,范围1/#T到1之间。索引的选择性越高则查询效率越高,因为选择性高的索引可以让MySQL在查找时过滤掉更多的行。唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。

一般情况下某个列前缀的选择性也是足够高的,足以满足查询性能。对于BLOB、TEXT或者很长的VARCHAR类型的列,必须使用前缀索引,因为MySQL不允许索引这些列的完整长度。

诀窍在于要选择足够长的前缀以保证较高的选择性,同时又不能太长(以便节约空间)。前缀应该足够长,以使得前缀索引的选择性接近于索引整个列。换句话说,前缀的基数应该接近于完整列的基数。

3.3、多列索引

在多个列上建立独立的单列索引大部分情况下并不能提高MySQL的查询性能。MySQL5.0和更新版本引入了一种叫“索引合并”的策略,一定程度上可以使用表上的多个单列索引来定位指定的行。

索引合并策略有时候是一种优化的结果,但实际上更多时候说明了表上的索引建的很糟糕:

  • 当出现服务器对多个索引做相交操作时(通常有多个AND条件),通常意味着需要一个包含所有相关列的多列索引,而不是多个独立的单列索引。
  • 当服务器需要对多个索引做联合操作时(通常有多个OR条件),通常需要耗费大量CPU和内存资源在算法的缓存、排序和合并操作上。特别是当其中有些索引的选择性不高,需要合并扫描返回的大量数据的时候。
  • 更重要的是,优化器不会把这些计算到“查询成本”中,优化器只关心随机页面读取。这会使得查询的成本被低估,导致该执行计划还不如直接走全表扫描。这样做不但会消耗更多的CPU和内存资源,还可能会影响查询的并发性,但如果是单独运行这样的查询则往往会忽略对并发性的影响。

3.4、选择合适的索引列顺序

当不需要考虑排序和分组时,将选择性最高的列放在前面通常是很好的。这时候索引的作用只是用于优化WHERE条件的查找。在这种情况下,这样设计的索引确实能够最快的过滤出需要的行,对于在WHERE子句中只使用了索引部分前缀列的查询来说选择性也更高。然而,性能不只是依赖于所有索引列的选择性(整体基数),也和查询条件的具体值有关,也就是和值的分布有关。

3.5、聚簇索引

聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。

当表有聚簇索引时,它的数据行实际上存放在索引的叶子页中。因为无法同时把数据行存放在两个不同的地方,所以一个表只能有一个聚簇索引。

如果没有定义主键,InnoDB会选择一个唯一的非空索引代替。如果没有这样的索引,InnoDB只聚集在同一个页面中的记录。包含相邻键值的页面可能会相距甚远。

聚簇索引的优点:

  • 可以把相关数据保存在一起。
  • 数据访问更快。
  • 使用覆盖索引扫描的查询可以直接使用页节点中的主键值

聚簇索引的缺点:

  • 聚簇数据最大限度的提高了I/O密集型应用的性能,但如果数据全部都放在内存中,那访问得顺序就没那么重要了,聚簇索引也就没什么优势了。
  • 插入速度严重依赖于插入顺序。
  • 更新聚簇索引列的代价很高,因为会强制InnoDB将每个被更新的行移动到新的位置。
  • 基于聚簇索引的表在插入新行,或者主键被更新导致需要移动行的时候,可能面临“页分裂”的问题。当行的主键值要求必须将这一行插入到某个已满的页中时,存储引擎会将该页分裂成两个页面来容纳该行,这就是一次页分裂操作。页分裂会导致表占用更多的磁盘空间。
  • 聚簇索引可能导致全表扫描变慢,尤其是行比较稀疏,或者由于页分裂导致数据存储不连续的时候。
  • 二级索引(非聚簇索引)可能比想象的要更大,因为在二级索引的叶子节点包含了引用行的主键列。
  • 二级索引访问两次索引查找,而不是一次。

二级索引叶子节点保存的不是指向行的物理位置的指针,而是行的主键值。这意味着通过二级索引查找行,存储引擎需要找到二级索引的叶子节点获得对应的主键值,然后根据这个值去聚簇索引中查找对应的行。这里做了重复的工作:两次B-Tree查找而不是一次。对于InnoDB,自适应哈希索引能够减少这样的重复工作。

3.6、覆盖索引

覆盖索引可以使查询只需要扫描索引而无须回表。

优点:

  • 索引条目通常远小于数据行大小,所以如果只需要读取索引,那MySQL就会极大地减少数据访问量。这对缓存的负载非常重要,因为这种情况下响应时间大部分花费在数据拷贝上。覆盖索引对于I/O密集型的应用也有帮助,因为索引比数据更小,更容易全部放入内存中。
  • 因为索引是按照列值顺序存储的(至少在单个页内是如此),所以对于I/O密集型的范围查询会比随机从磁盘读取每一行数据的I/O要少得多。
  • 由于InnoDB的聚簇索引,覆盖索引对InnoDB表特别有用。InnoDB的二级索引在叶子节点中保存了行的主键值,所以如果二级主键能够覆盖查询,则可以避免对主键索引的二次查询。

不是所有类型的索引都可以成为覆盖索引。覆盖索引必须要存储索引列的值,而哈希索引、空间索引和全文索引等都不存储索引列的值,所以MySQL只能使用B-Tree索引做覆盖索引。

3.7、使用索引扫描来做排序

MySQL有两种方式可以生成有序的结果:通过排序操作或者按索引顺序扫描。

MySQL可以使用同一个索引既满足排序,又用于查找行。因此,如果可能,设计索引时应该尽可能地同时满足这两种任务,这样是最好的。

只有当索引的列顺序和ORDER BY子句的顺序完全一致,并且所有列的排序方向(倒序或正序)都一样时,MySQL才能够使用索引来对结果做排序。如果查询需要关联多张表,则只有当ORDER BY子句引用的字段全部为第一个表时,才能使用索引做排序。ORDER BY子句和查找型查询的限制是一样的:需要满足索引的最左前缀的要求;否则,MySQL都需要执行排序操作,而无法利用索引排序。

有一种情况下ORDER BY子句可以不满足索引的最左前缀的要求,就是前几列为常量的时候。如果WHERE子句或者JOIN子句中对这些列指定了常量,就可以“弥补”索引的不足。

例如:索引为(A,B,C),查询为SELECT A,B,C FROM T WHERE A=1 ORDER BY B,C

即使ORDER BY子句不满足索引的最左前缀的要求,也可以用于查询排序,这是因为索引的第一列被指定为一个常数。

3.8、冗余和重复索引

重复索引是指在相同的列上按照相同的顺序创建的相同类型的索引。应该避免这样创建重复索引,发现以后也应该立即移除。

例如:ID做主键、ID做唯一索引、ID做普通索引,这三个同时存在则为三个重复的索引。

冗余索引和重复索引有一些不同。如果创建了索引(A,B),再创建索引(A)就是冗余索引,因为这只是前一个索引的前缀索引。因此索引(A,B)也可以当作索引(A)来使用(这种冗余只是对B-Tree索引来说的)。但是如果再创建索引(B,A),则不是冗余索引,索引(B)也不是,因为B不是索引(A,B)的最左前缀列。另外,其他不同类型的索引(例如哈希索引或者全文索引)也不会是B-Tree索引的冗余索引,而无论覆盖的索引列是什么。

大多数情况下都不需要冗余索引,应该尽量扩展已有的索引而不是创建新的索引。但也有时候出于性能方面的考虑需要冗余索引,因为扩展已有的索引会导致其变得太大,从而影响其他使用该索引的查询的性能。

3.9、未使用的索引

可能还会有一些服务器永远不用的索引,建议考虑删除。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL性能调优是指通过优化数据库的配置、索引设计、查询语句以及缓存利用等技术手段,提升MySQL数据库的性能。根据引用中提到的内容,可以从以下几个方面进行MySQL性能调优: 1. 索引优化:合理设计和使用索引可以大大提高查询速度。可以使用适当的索引类型、合理选择索引列和优化查询语句来提高索引的效率。 2. 查询优化:通过优化查询语句的写法、避免全表扫描、减少不必要的连接操作等方式,提升查询的效率。可以使用EXPLAIN命令分析查询语句的执行计划,找出慢查询的原因,并进行相应的优化。 3. 缓存利用:使用MySQL的查询缓存可以将查询结果缓存起来,减少重复查询的开销。此外,还可以使用Redis等内存数据库作为缓存,提高访问速度。 4. 数据库扩展:根据业务需求,可以采用垂直扩展和水平扩展两种方式来扩展数据库的性能。垂直扩展是通过提升服务器硬件性能来增加数据库的处理能力,如增加内存、CPU等资源。水平扩展是通过增加数据库实例或分片来分散负载,提高并发处理能力。 5. 高可用性和负载均衡:为了提高数据库的可用性和负载均衡能力,可以使用主从复制和读写分离等技术。主从复制可以将数据从主数据库同步到多个从数据库,提供数据冗余和故障恢复能力。读写分离可以将读操作分发到多个从数据库,减轻主数据库的负载压力。 通过以上的性能调优方法,可以提升MySQL数据库的响应速度、并发处理能力和可用性,从而提高应用系统的整体性能。<span class="em">1</span> #### 引用[.reference_title] - *1* [MySQL学习笔记5-数据库性能优化与扩展.md](https://download.csdn.net/download/weixin_52057528/88244498)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值