找到 mysql 数据库中的不良索引

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介:

为了演示,首先建两个包含不良索引的表,并弄点数据。


 
 
  1. mysql> show create table test1\G
  2. *************************** 1. row ***************************
  3. Table: test1
  4. Create Table: CREATE TABLE `test1` (
  5. `id` int(11) NOT NULL,
  6. `f1` int(11) DEFAULT NULL,
  7. `f2` int(11) DEFAULT NULL,
  8. `f3` int(11) DEFAULT NULL,
  9. PRIMARY KEY (`id`),
  10. KEY `k1` (`f1`,`id`),
  11. KEY `k2` (`id`,`f1`),
  12. KEY `k3` (`f1`),
  13. KEY `k4` (`f1`,`f3`),
  14. KEY `k5` (`f1`,`f3`,`f2`)
  15. ) ENGINE=InnoDB DEFAULT CHARSET=latin1
  16. 1 row in set (0.00 sec)
  17. mysql> show create table test2\G
  18. *************************** 1. row ***************************
  19. Table: test2
  20. Create Table: CREATE TABLE `test2` (
  21. `id1` int(11) NOT NULL DEFAULT '0',
  22. `id2` int(11) NOT NULL DEFAULT '0',
  23. `b` int(11) DEFAULT NULL,
  24. PRIMARY KEY (`id1`,`id2`),
  25. KEY `k1` (`b`)
  26. ) ENGINE=InnoDB DEFAULT CHARSET=latin1
  27. 1 row in set (0.00 sec)
  28. mysql> select count(*) from test2 group by b;
  29. +----------+
  30. | count(*) |
  31. +----------+
  32. | 32 |
  33. | 17 |
  34. +----------+
  35. 2 rows in set (0.00 sec)

1. 包含主键的索引

innodb 本身是聚簇表,每个二级索引本身就包含主键,类似 f1, id 的索引实际虽然没有害处,但反映了使用者对 mysql 索引不了解。而类似 id, f1 的是多余索引,会浪费存储空间,并影响数据更新性能。包含主键的索引用这样一句 sql 就能全部找出来。


 
 
  1. mysql> select c.*, pk from
  2. -> (select table_schema, table_name, index_name, concat('|', group_concat(column_name order by seq_in_index separator '|'), '|') cols
  3. -> from INFORMATION_SCHEMA.STATISTICS
  4. -> where index_name != 'PRIMARY' and table_schema != 'mysql'
  5. -> group by table_schema, table_name, index_name) c,
  6. -> (select table_schema, table_name, concat('|', group_concat(column_name order by seq_in_index separator '|'), '|') pk
  7. -> from INFORMATION_SCHEMA.STATISTICS
  8. -> where index_name = 'PRIMARY' and table_schema != 'mysql'
  9. -> group by table_schema, table_name) p
  10. -> where c.table_name = p.table_name and c.table_schema = p.table_schema and c.cols like concat('%', pk, '%');
  11. +--------------+------------+------------+---------+------+
  12. | table_schema | table_name | index_name | cols | pk |
  13. +--------------+------------+------------+---------+------+
  14. | test | test1 | k1 | |f1|id| | |id| |
  15. | test | test1 | k2 | |id|f1| | |id| |
  16. +--------------+------------+------------+---------+------+
  17. 2 rows in set (0.04 sec)

2. 重复索引前缀

包含重复前缀的索引,索引能由另一个包含该前缀的索引完全代替,是多余索引。多余的索引会浪费存储空间,并影响数据更新性能。这样的索引同样用一句 sql 可以找出来。


 
 
  1. mysql> select c1.table_schema, c1.table_name, c1.index_name,c1.cols,c2.index_name, c2.cols from
  2. -> (select table_schema, table_name, index_name, concat('|', group_concat(column_name order by seq_in_index separator '|'), '|') cols
  3. -> from INFORMATION_SCHEMA.STATISTICS
  4. -> where table_schema != 'mysql' and index_name!='PRIMARY'
  5. -> group by table_schema,table_name,index_name) c1,
  6. -> (select table_schema, table_name,index_name, concat('|', group_concat(column_name order by seq_in_index separator '|'), '|') cols
  7. -> from INFORMATION_SCHEMA.STATISTICS
  8. -> where table_schema != 'mysql' and index_name != 'PRIMARY'
  9. -> group by table_schema, table_name, index_name) c2
  10. -> where c1.table_name = c2.table_name and c1.table_schema = c2.table_schema and c1.cols like concat(c2.cols, '%') and c1.index_name != c2.index_name;
  11. +--------------+------------+------------+------------+------------+---------+
  12. | table_schema | table_name | index_name | cols | index_name | cols |
  13. +--------------+------------+------------+------------+------------+---------+
  14. | test | test1 | k1 | |f1|id| | k3 | |f1| |
  15. | test | test1 | k4 | |f1|f3| | k3 | |f1| |
  16. | test | test1 | k5 | |f1|f3|f2| | k3 | |f1| |
  17. | test | test1 | k5 | |f1|f3|f2| | k4 | |f1|f3| |
  18. +--------------+------------+------------+------------+------------+---------+
  19. 4 rows in set (0.02 sec)

3. 低区分度索引

这样的索引由于仍然会扫描大量记录,在实际查询时通常会被忽略。但是在某些情况下仍然是有用的。因此需要根据实际情况进一步分析。这里是区分度小于 10% 的索引,可以根据需要调整参数。


 
 
  1. mysql> select p.table_schema, p.table_name, c.index_name, c.car, p.car total from
  2. -> (select table_schema, table_name, index_name, max(cardinality) car
  3. -> from INFORMATION_SCHEMA.STATISTICS
  4. -> where index_name != 'PRIMARY'
  5. -> group by table_schema, table_name,index_name) c,
  6. -> (select table_schema, table_name, max(cardinality) car
  7. -> from INFORMATION_SCHEMA.STATISTICS
  8. -> where index_name = 'PRIMARY' and table_schema != 'mysql'
  9. -> group by table_schema,table_name) p
  10. -> where c.table_name = p.table_name and c.table_schema = p.table_schema and p.car > 0 and c.car / p.car < 0.1;
  11. +--------------+------------+------------+------+-------+
  12. | table_schema | table_name | index_name | car | total |
  13. +--------------+------------+------------+------+-------+
  14. | test | test2 | k1 | 4 | 49 |
  15. +--------------+------------+------------+------+-------+
  16. 1 row in set (0.04 sec)

4. 复合主键

由于 innodb 是聚簇表,每个二级索引都会包含主键值。复合主键会造成二级索引庞大,而影响二级索引查询性能,并影响更新性能。同样需要根据实际情况进一步分析。


 
 
  1. mysql> select table_schema, table_name, group_concat(column_name order by seq_in_index separator ',') cols, max(seq_in_index) len
  2. -> from INFORMATION_SCHEMA.STATISTICS
  3. -> where index_name = 'PRIMARY' and table_schema != 'mysql'
  4. -> group by table_schema, table_name having len>1;
  5. +--------------+------------+-----------------------------------+------+
  6. | table_schema | table_name | cols | len |
  7. +--------------+------------+-----------------------------------+------+
  8. | test | test2 | id1,id2 | 2 |
  9. +--------------+------------+-----------------------------------+------+
  10. 1 rows in set (0.01 sec)
  11. 本文来自云栖社区合作伙伴“Linux中国”,原文发布日期:2015-08-18
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
8天前
|
缓存 关系型数据库 MySQL
MySQL索引策略与查询性能调优实战
在实际应用中,需要根据具体的业务需求和查询模式,综合运用索引策略和查询性能调优方法,不断地测试和优化,以提高MySQL数据库的查询性能。
|
11天前
|
数据库 索引
数据库索引
数据库索引 1、索引:建立在表一列或多列的辅助对象,目的是加快访问表的数据。 2、索引的优点: (1)、创建唯一性索引,可以确保数据的唯一性; (2)、大大加快数据检索速度; (3)、加速表与表之间的连接; (4)、在查询过程中,使用优化隐藏器,提高系统性能。 3、索引的缺点: (1)、创建和维护索引需要耗费时间,随数据量增加而增加; (2)、索引占用物理空间; (3)、对表的数据进行增删改时,索引需要动态维护,降低了数据的维护速度。
27 2
|
13天前
|
SQL 关系型数据库 MySQL
12 PHP配置数据库MySQL
路老师分享了PHP操作MySQL数据库的方法,包括安装并连接MySQL服务器、选择数据库、执行SQL语句(如插入、更新、删除和查询),以及将结果集返回到数组。通过具体示例代码,详细介绍了每一步的操作流程,帮助读者快速入门PHP与MySQL的交互。
27 1
|
15天前
|
SQL 关系型数据库 MySQL
go语言数据库中mysql驱动安装
【11月更文挑战第2天】
29 4
|
22天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
108 1
|
10天前
|
运维 关系型数据库 MySQL
安装MySQL8数据库
本文介绍了MySQL的不同版本及其特点,并详细描述了如何通过Yum源安装MySQL 8.4社区版,包括配置Yum源、安装MySQL、启动服务、设置开机自启动、修改root用户密码以及设置远程登录等步骤。最后还提供了测试连接的方法。适用于初学者和运维人员。
99 0
|
16天前
|
存储 关系型数据库 数据库
Postgres数据库BRIN索引介绍
BRIN索引是PostgreSQL提供的一种高效、轻量级的索引类型,特别适用于大规模、顺序数据的范围查询。通过存储数据块的摘要信息,BRIN索引在降低存储和维护成本的同时,提供了良好的查询性能。然而,其适用场景有限,不适合随机数据分布或频繁更新的场景。在选择索引类型时,需根据数据特性和查询需求进行权衡。希望本文对你理解和使用PostgreSQL的BRIN索引有所帮助。
26 0
|
23天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第26天】数据库作为现代应用系统的核心组件,其性能优化至关重要。本文主要探讨MySQL的索引策略与查询性能调优。通过合理创建索引(如B-Tree、复合索引)和优化查询语句(如使用EXPLAIN、优化分页查询),可以显著提升数据库的响应速度和稳定性。实践中还需定期审查慢查询日志,持续优化性能。
53 0
|
SQL Java 数据库连接
MySQL---数据库从入门走向大神系列(十五)-Apache的DBUtils框架使用
MySQL---数据库从入门走向大神系列(十五)-Apache的DBUtils框架使用
192 0
MySQL---数据库从入门走向大神系列(十五)-Apache的DBUtils框架使用
|
SQL 关系型数据库 MySQL
MySQL---数据库从入门走向大神系列(六)-事务处理与事务隔离(锁机制)
MySQL---数据库从入门走向大神系列(六)-事务处理与事务隔离(锁机制)
141 0
MySQL---数据库从入门走向大神系列(六)-事务处理与事务隔离(锁机制)
下一篇
无影云桌面