博客
关于我
Mysql 知识回顾总结-索引
阅读量:794 次
发布时间:2023-02-11

本文共 2966 字,大约阅读时间需要 9 分钟。

数据库索引优化指南

在数据库应用中,索引是提升查询性能的关键因素。本文将从多个维度深入探讨索引的影响、不同索引类型的性能表现以及实际应用中的优化技巧。


1. 索引的影响

索引能显著提升数据库查询性能,但其背后也隐藏着许多影响因素。例如,在MySQL环境下,表数据量达到60万行时,索引对查询性能的提升尤为明显。

1.1 查询执行计划

  • 不使用索引:在没有索引的情况下,查询需要从头到尾扫描所有行数据,这会导致较高的时间消耗。

  • 唯一索引:使用唯一索引后,查询在找到第一条匹配记录后会立即停止,从而大幅减少扫描次数。

  • 普通索引:普通索引的性能介于上述两者之间,但在大多数情况下,使用唯一索引会更高效。

通过实际测试可以发现,索引的引入能够显著降低查询时间。例如,当对一个非索引字段进行查询时,执行时间从0.198秒降低到0.000秒。


2. 普通索引、唯一索引与主键索引的性能比较

2.1 主键索引与非主键索引

在InnoDB存储引擎中,主键索引会被优化为聚集索引,这对数据插入和查询性能有重要影响。

  • 主键索引:几乎所有数据操作(如插入、更新和查询)都会经过主键索引,因此其性能优势尤为突出。

  • 非主键索引:通常用于查询时的筛选条件,性能表现依赖于索引的选择和数据分布。

2.2 查询性能

  • 普通索引:查询操作需要从索引中找到满足条件的记录,并继续扫描下一页数据,直到找到目标记录。

  • 唯一索引:由于索引定义了唯一性,查询一旦找到第一条匹配记录就会立即停止。

两者的性能差异微乎其微,尤其是在索引页刚好位于索引块的最后一条记录时,唯一索引的性能优势会更明显。

2.3 插入与更新性能

在插入和更新操作中,索引的选择会影响性能表现。

  • 唯一索引:插入或更新操作需要检查索引是否存在冲突。如果目标记录不在内存中,可能需要读取数据页并进行判断。

  • 普通索引:对于普通索引,更新操作可以利用缓存机制(如Change Buffer)减少磁盘读取次数,从而提升性能。

在实际应用中,如果业务逻辑确保数据唯一性,使用普通索引会比唯一索引更高效。相反,如果需要确保数据唯一性,仍需使用唯一索引。


3. 字符串类型的索引

在处理字符串类型数据时,选择合适的索引策略至关重要。

3.1 前缀索引

前缀索引通过只存储字符串的前缀部分来减少索引占用的空间。例如,可以选择存储前6位字符作为索引键。

  • 优点:减少索引页面的大小,从而提高每个索引页存储的数据量。

  • 缺点:前缀的区分度较低可能导致更多的回表扫描。

建议根据实际业务需求合理选择前缀长度,通常可以覆盖95%以上的数据。

3.2 倒序索引

倒序索引通过对字符串进行逆序处理,用于解决前缀索引的区分度不足的问题。

  • 优点:避免了直接处理字符串的性能消耗。

  • 缺点:需要额外的CPU资源来进行倒序操作。

倒序索引通常用于解决字符串本身区分度不足的问题。

3.3 Hash索引

Hash索引通过计算字符串的哈希值来加速查询。

  • 优点:哈希冲突概率较低,平均每个查询只能访问一行数据。

  • 缺点:需要在每次查询时计算哈希值,增加CPU消耗。

建议在哈希冲突概率较高的情况下,结合唯一索引和哈希索引共同使用。


4. 为什么有时候不使用索引

尽管索引能显著提升查询性能,但在某些情况下使用索引反而可能带来更高的性能成本。

4.1 Order by 查询

在对数据进行排序查询时,优化器可能不选择使用索引。例如,当使用ORDER BY sale_time时,如果优化器认为索引的回表成本比全表扫描更高,就会选择全表扫描再排序。

解决方法是通过LIMIT语句限制返回的数据量,或者在查询条件中添加排序索引。

4.2 多条件过滤

当查询条件中包含多个非索引字段时,优化器可能选择全表扫描。

例如,以下查询可能因为使用了非索引字段进行过滤而导致索引未被使用:

SELECT t1.f1, t1.f2, t2.f1, t2.f2FROM t1 LEFT JOIN t2 ON t1.index_1 = t2.index_2WHERE t1.index1 = 'xxxx' AND t1.f3 = 'xxx' AND t1.f4 = 'xxxx'AND t2.f3 = 'xxxx'ORDER BY t2.f4LIMIT 100

解决方法是检查查询条件中的字段是否需要回表查询,并确保索引设计合理。

4.3 多索引或部分非索引where条件

在使用多个索引或部分非索引where条件时,优化器可能选择错误的索引。

例如,以下查询可能因为优化器误判索引选择而导致性能下降:

SELECT * FROM tWHERE (a BETWEEN 1 AND 1000) AND (b BETWEEN 50000 AND 100000)ORDER BY b, aLIMIT 1

解决方法包括:

  • 使用FORCE INDEX强制使用特定索引。
  • 通过排序或重新设计查询逻辑优化索引选择。

5. 字符串类型字段操作

在处理字符串字段时,避免在索引字段上直接进行函数操作,否则可能破坏索引的有序性。

5.1 直接函数操作

例如,以下查询会破坏索引的有序性:

SELECT COUNT(*) FROM tradelogWHERE MONTH(t_modified) = 7

解决方法是通过间接方式(如使用日期范围查询)来避免直接函数操作。

5.2 隐式类型转换

在查询中使用隐式类型转换时,确保转换后的值能够正确匹配索引字段。

例如:

SELECT * FROM tradelogWHERE TRADEID = 110717

实际等价于:

SELECT * FROM tradelogWHERE CAST(TRADEID AS SIGNED INT) = 110717

5.3 隐式编码集转换

在使用特定编码集转换时,确保转换后的值能够正确匹配索引字段。

例如:

SELECT * FROM trade_detailWHERE CONVERT(TRADEID USING utf8mb4) = $L2.tradeid.value

6. 随机取行的优化

在某些场景下,需要随机取数据库中的行数据。以下是常见方法及其优化建议:

方法一:使用内存临时表

  • 创建一个内存临时表,用于存储随机抽取的数据。
  • 使用RAND()函数生成随机值,并将其存入临时表。

方法二:一次获取多个随机行

  • 使用COUNT(*)获取表中数据总数。
  • 生成多个随机行号,并使用LIMIT语句一次性获取多个随机行。

方法三:利用缓存机制

  • 将数据库数据缓存到内存(如Redis),然后从缓存中随机读取所需数据。

7. 数据类型选择

在选择数据类型时,需要根据业务需求和数据范围选择合适的类型。

  • BIGINT(1)BIGINT(19)都能存储2^64-1范围内的值。
  • INT类型存储范围为2^32-1。

8. 事务隔离性问题

在数据库事务管理中,建议使用RC事务隔离级别作为默认设置。

  • MySQL默认事务隔离级别为RR(读取共享)。
  • RC隔离级别提供更严格的数据一致性。

通过以上优化策略,可以显著提升数据库的查询性能和稳定性。在实际应用中,需要根据具体业务需求选择合适的索引设计,并通过测试和优化不断改进数据库性能。

转载地址:http://ubbfk.baihongyu.com/

你可能感兴趣的文章
MySQL 聚簇索引&&二级索引&&辅助索引
查看>>
Mysql 脏页 脏读 脏数据
查看>>
mysql 自增id和UUID做主键性能分析,及最优方案
查看>>
Mysql 自定义函数
查看>>
mysql 行转列 列转行
查看>>
Mysql 表分区
查看>>
mysql 表的操作
查看>>
mysql 视图,视图更新删除
查看>>
MySQL 触发器
查看>>
mysql 让所有IP访问数据库
查看>>
mysql 记录的增删改查
查看>>
MySQL 设置数据库的隔离级别
查看>>
MySQL 证明为什么用limit时,offset很大会影响性能
查看>>
Mysql 语句操作索引SQL语句
查看>>
MySQL 误操作后数据恢复(update,delete忘加where条件)
查看>>