广告
返回顶部
首页 > 资讯 > 数据库 >MySQL优化之索引
  • 406
分享到

MySQL优化之索引

MySQL优化之索引 2021-02-14 02:02:59 406人浏览 绘本
摘要

sql为什么需要优化? 对于初学者来说,能够写出实现功能的SQL语句而不出错,查询出所需要的结果,就已经能够满足日常使用了。但在某些场景,对性能的要求比较高,因此,要求SQL的执行响应速度快,就需要对SQL进行一定程度的优化。 在

MySQL优化之索引

sql为什么需要优化

对于初学者来说,能够写出实现功能的SQL语句而不出错,查询出所需要的结果,就已经能够满足日常使用了。但在某些场景,对性能的要求比较高,因此,要求SQL的执行响应速度快,就需要对SQL进行一定程度的优化。
在实际应用场景中,Mysql经常会存在诸如性能低、执行时间过长、等待时间过长、SQL语句欠佳(尤其是连接查询)、索引失效、服务器参数设置不合理等问题,这时候就需要对SQL进行优化,从而达到我们所需要的的性能需求。

SQL解析过程

要对SQL进行优化,首先需要知道SQL的解析过程是什么样子的。在此之前,我们要明确SQL编写过程和解析过程的区别。

SQL编写过程

select [distinct] ... from ... join ... on ... where ... group by ... having ... order by ... limit ...;

SQL解析过程

from ... on ... join ... where ... group by ... having ... select [distinct] ... order by ... limit ...;

以上语法中sql关键字的含义,不是本文的重点,网络上有很多教程,此处不再说明,我们只需要知道,SQL的编写过程和实际解析过程并不是一致的。这点在后续的相关优化中将会进一步说明。

索引

索引相当于字典的目录,其目的是帮助在mysql中更快的查询到所需要的数据。其本质是一种BTREE的数据结构
所以可以得出一个结论:索引是一种数据结构。 如果您对数据结构有所了解,可以更明白的讲,索引是一种叫树的数据结构。树有很多种,如二叉树,哈希树等。索引是B树(和二叉树比较类似)。

举个例子说明:
假设我们有一张表student,其结构及其中的数据如下:

id name score
1 zs 75
2 ls 82
3 ww 62
4 ll 88
5 wq 77
6 wb 53

其中,score列是索引。那么,该索引的大致结构是如下图所示的样子:

因此,如果有这样一条SQL:

select score from student where score = 77;

如果没有索引,那么需要全表扫描,从第一条数据开始,需要到第5次才能查找到我们所需要的数据;而如果有了索引,则只需要3次就能查找到(75->62->77),由此可见,索引确实能够提升查询效率,尤其是当表中的数据量特别大,达到了百万级别,甚至千万级别的时候,索引的优势就更加明显。

Btree除了常见的二叉树,还有三叉树,三叉树的结构如下所示:

Btree一般指的都是B+树。实际上,索引的数据全部存储在叶节点中,这也就意味着,对于Btree中,查询任意数据的次数都是n次(n为树的深度)。

由于客户端和服务器之间主要是通过io,所以索引会大大降低IO的使用率,并且能一定程度的降低CPU的使用率。(比如SQL语句中有order by,由于索引的数据结构本身就是排好序的,所以直接省去了这一步,从而降低CPU使用率)。

索引固然有诸多好处,但也有一定的弊端:

  • 索引本身很大,因为它本身也是数据结构,存储时必然要占空间;
  • 索引不是所有情况均适用
    • 少量数据(数据量少,比如只有一条数据,没有必要通过索引查询)
    • 频繁更新的字段(因为索引是B树,频繁更新的字段除了要更新该字段本身,还得更新索引的值,甚至会引起索引结构的变动)
    • 很少使用的列(很少使用,意味着不经常查询,设置索引意义不大)
  • 索引确实可以提高查询的效率,但会降低增删改的效率(因为对数据增删改,同时会引起索引的变动,需要额外对索引进行增删改。而实际应用中,因为查询使用到的场景远远多于增删改,所以索引还是有存在的必要的)。

索引分类:

  • 单值索引:单列的值,一张表可以有多个单值索引。
  • 唯一索引:不能重复(unique index)
  • 复合索引:多个列构成的索引,相当于书的二级目录。(不是100%多个索引同时用)
  • 主键索引:如果一个字段设置为主键(primary key),则默认是主键索引,因此主键索引也不能重复。

主键索引和唯一索引的区别是:主键索引列的值不能为null,唯一索引列的值可以为null。

索引常见操作

创建索引:

create 索引类型 索引名 on 表(字段)
alter table 表明 add 索引类型 索引名(字段)

删除索引:

drop index 索引名 on 表名

查询索引:

show index from 表名

以本文中的student表为例,加以说明:

mysql> desc student;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| id    | int(4)   | NO   | PRI | NULL    | auto_increment |
| name  | char(20) | YES  |     | NULL    |                |
| score | double   | YES  |     | NULL    |                |
+-------+----------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

在student表上对name字段创建单值索引stu_idx1:

mysql> create index stu_idx1 on student(name);
Query OK, 0 rows affected (0.17 sec)
Records: 0  Duplicates: 0  Warnings: 0

在student表上对id字段创建唯一索引stu_idx2:

mysql> create unique index stu_idx2 on student(id);
Query OK, 0 rows affected (0.20 sec)
Records: 0  Duplicates: 0  Warnings: 0

在student表上对name,score字段创建复合索引stu_idx3:

mysql> create index stu_idx3 on student(name,score);
Query OK, 0 rows affected (0.17 sec)
Records: 0  Duplicates: 0  Warnings: 0

使用alter的方式对student表的score字段创建单值索引stu_idx4:

mysql> alter table student add index stu_idx4(score);
Query OK, 0 rows affected (0.17 sec)
Records: 0  Duplicates: 0  Warnings: 0

查看创建的索引:

mysql> show index from student;
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table   | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| student |          0 | PRIMARY  |            1 | id          | A         |           6 |     NULL | NULL   |      | BTREE      |         |
     |
| student |          0 | stu_idx2 |            1 | id          | A         |           6 |     NULL | NULL   |      | BTREE      |         |
     |
| student |          1 | stu_idx1 |            1 | name        | A         |           6 |     NULL | NULL   | YES  | BTREE      |         |
     |
| student |          1 | stu_idx3 |            1 | name        | A         |           6 |     NULL | NULL   | YES  | BTREE      |         |
     |
| student |          1 | stu_idx3 |            2 | score       | A         |           6 |     NULL | NULL   | YES  | BTREE      |         |
     |
| student |          1 | stu_idx4 |            1 | score       | A         |           6 |     NULL | NULL   | YES  | BTREE      |         |
     |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
6 rows in set (0.00 sec)

从以上表格,可以读出以下信息:

  • 第一条数据,索引名是PRIMARY,这条索引不是手动创建的,而是建表时因为指定了id为primary key,因此自动创建的主键索引;
  • 第11列Index_type可以看出索引的数据结构均为BTREE;
  • 第4、5条数据索引名都为stu_idx3,索引序号Seq_in_index分别为1和2,因此,这两个是一对,代表是一个复合索引。
  • Non_unique值为0,代表是唯一索引(或主键索引),为1代表不是唯一索引,也就是说该索引列的值可以重复。

假如要删除索引stu_idx2和stu_idx4,则执行如下语句:

mysql> drop index stu_idx2 on student;
Query OK, 0 rows affected (0.10 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> drop index stu_idx4 on student;
Query OK, 0 rows affected (0.09 sec)
Records: 0  Duplicates: 0  Warnings: 0

再次查询:

mysql> show index from student;
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table   | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| student |          0 | PRIMARY  |            1 | id          | A         |           6 |     NULL | NULL   |      | BTREE      |         |
     |
| student |          1 | stu_idx1 |            1 | name        | A         |           6 |     NULL | NULL   | YES  | BTREE      |         |
     |
| student |          1 | stu_idx3 |            1 | name        | A         |           6 |     NULL | NULL   | YES  | BTREE      |         |
     |
| student |          1 | stu_idx3 |            2 | score       | A         |           6 |     NULL | NULL   | YES  | BTREE      |         |
     |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
4 rows in set (0.00 sec)

索引的一些注意事项

创建索引需要注意的事项:

  • 选择表关联(JOIN)的关联条件列;
  • 数据查询(WHERE)过滤条件列;
  • 重复键值数少的列;
  • 复合索引应该将重复键值数少的列放在首字段;
  • 如果表的数据比较少(如少于1000行),应根据实际情况评估是否需要创建索引;
  • 复合索引字段的个数不建议超过3个;
  • 不建议在大字段(如char(100)等字段类型)上创建索引;
  • 对于频繁访问的业务表,索引数量不建议超过5个;
  • 对于数据很少变化的静态表、历史表,索引数量不建议超过8个;

使用索引需要注意的事项:

  • 避免在索引上进行运算;
  • 避免使用 in 和 not in;
  • 尽量不适用like;
  • 避免在索引列上使用函数;
  • 避免在索引上使用 is null或 is not null;
  • 避免使用 !=, >, < 等符号;
  • 避免改变索引列的类型;
  • 避免使用having子句;
  • 对于复合索引,应按照索引中字段的顺序编制查询条件 ;
    以上这些已经涉及到后面的索引优化范畴,这里大概有个印象,在下一篇文章中会详细讲述。

唯一索引和主键的区别:

  • 一张表里可以有多个唯一索引,但只能有一个主键;
  • 主键保证记录唯一且非空(null),唯一索引只能保证记录唯一,可以为空(null);
  • 主键一定是唯一索引,但唯一索引可以不是主键;
  • 主键可以被其他表引为外键,唯一索引不可以;
  • 主键是约束,不占空间,唯一索引是数据结构,是表的冗余结构,占存储空间,这是二者的本质区别。
您可能感兴趣的文档:

--结束END--

本文标题: MySQL优化之索引

本文链接: https://www.lsjlt.com/news/5235.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • MySQL优化之索引
    SQL为什么需要优化? 对于初学者来说,能够写出实现功能的SQL语句而不出错,查询出所需要的结果,就已经能够满足日常使用了。但在某些场景,对性能的要求比较高,因此,要求SQL的执行响应速度快,就需要对SQL进行一定程度的优化。 在...
    99+
    2021-02-14
    MySQL优化之索引
  • mysql织梦索引优化之MySQL Order By索引优化
    在一些情况下,MySQL可以直接使用索引来满足一个ORDER BY 或GROUP BY 子句而无需做额外的排序。尽管ORDER BY 不是和索引的顺序准确匹配,索引还是可以被用到,只要不用的索引部分和所有的额外的ORDER B...
    99+
    2022-10-20
  • MySQL优化之索引解析
    索引的本质 MySQL索引或者说其他关系型数据库的索引的本质就只有一句话,以空间换时间。 索引的作用 索引关系型数据库为了加速对表中行数据检索的(磁盘存储的)数据结构 索引的分类 数据结构上面的分类 HASH 索引 等值匹配效率...
    99+
    2019-07-07
    MySQL优化之索引解析
  • MySQL优化之联合索引
    1.表结构 (root@localhost) [test]> show create table t_demo\G; *************************** 1. row ******...
    99+
    2022-10-18
  • Mysql性能优化之索引下推
    索引下推(index condition pushdown )简称ICP,在Mysql5.6的版本上推出,用于优化查询。 在不使用ICP的情况下,在使用非主键索引(又叫普通索引或者二级索引)进行查询时,存储引擎通过索...
    99+
    2022-05-19
    Mysql 索引下推
  • MySQL索引优化
    一、单表 创建索引之前:type=ALL全表扫描,Extra里面的Using filesort(文件内部排序) 根据where后面的条件创建:CREATE INDEX idx_article_ccv ON articl...
    99+
    2019-01-06
    MySQL索引优化
  • MYSQL性能故障优化利器之索引优化
                     &...
    99+
    2022-10-18
  • MySQL优化(3):索引
    MySQL优化中,最重要的优化手段就是索引,也是最常用的优化手段   索引简介: 索引:关键字与数据位置之间的映射关系 关键字:从数据中提取,用于标识,检索数据的特定内容 目的:加快检索   索引检索为什么快: (1)关键字相对于...
    99+
    2014-05-17
    MySQL优化(3):索引
  • MySQL索引优化EXPLAIN
    日常在CURD的过程中,都避免不了跟数据库打交道,大多数业务都离不开数据库表的设计和SQL的编写,那如何让你编写的SQL语句性能更优呢? 先来整体看下MySQL逻辑架构图: MySQL整体逻辑架构图可以分为Server和存储引擎层。...
    99+
    2015-10-24
    MySQL索引优化EXPLAIN
  • MySQL 5.7 索引优化
    提升查询性能最好的方法就是创建索引。索引项就像指向表中行的指针,让查询通过WHERE条件快速找到所要查询的行。MySQL所有的数据类型都可以创建索引。 不必要的索引会消耗系统的空间和MySQL在判断...
    99+
    2022-10-18
  • centos7-mysql-索引优化
    索引优化,优化查询速度-------------------------------------------------------count,统计一个表总计行数myisam储存引擎有自带计数器,使用cou...
    99+
    2022-10-18
  • mysql优化和索引
    表的优化1.定长与变长分离    如 int,char(4),time核心且常用字段,建成定长,放在一张表;    而varchar,text,blob这种...
    99+
    2022-10-18
  • MySQL索引优化之分页探索详细介绍
    目录​​MySQL​​索引优化之分页探索案例一案例二​​MySQL​​索引优化之分页探索 表结构 CREATE TABLE `demo` ( `id` int(11) NOT...
    99+
    2022-11-12
  • MySQL索引优化深入
    创建 test 测试表 CREATE TABLE `test` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `c1` varchar(10) DEFAULT NULL,  `c2`...
    99+
    2016-11-27
    MySQL索引优化深入
  • MySQL索引优化分享
    2,explain的作⽤ 查看表的读取顺序,读取操作类型,有哪些索引可用,表之间关联,每张表中有哪些索引被优化器执⾏ 3,索引命中策略略分析     最左匹配原则 在索引字段上加入函数(不匹配索引)     is null/is not n...
    99+
    2016-09-28
    MySQL索引优化分享
  • MySQL如何优化索引
    1.  MySQL如何使用索引 索引用于快速查找具有特定列值的行。如果没有索引,MySQL必须从第一行开始,然后遍历整个表以找到相关的行。表越大,花费越多。如果表中有相关列的索引,MySQL可以快速确定要在...
    99+
    2022-05-27
    MySQL 索引 MySQL 优化索引
  • MySQL 索引优化案例
    目录数据准备联合索引的首字段用范围查询强制走索引覆盖索引优化in和or什么时候会走索引like xx% 一般都会走索引,和数据量无关索引下推为什么范围查找没有用索引下推优化?如何选择索引Trace 工具深入优化order...
    99+
    2022-08-19
    MySQL索引优化 MySQL索引
  • MySQL--索引优化原则
    索引优化原则 1、最左前缀匹配原则,联合索引,mysql会从做向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3...
    99+
    2022-10-18
  • Mysql索引如何优化
    小编给大家分享一下Mysql索引如何优化,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!编程沉思录     &...
    99+
    2022-10-18
  • MySQL优化之避免索引失效的方法
    在上一篇文章中,通过分析执行计划的字段说明,大体说了一下索引优化过程中的一些注意点,那么如何才能避免索引失效呢?本篇文章将来讨论这个问题。 避免索引失效的常见方法 1.对于复合索引的使用,应按照索引建立的顺序使用,尽量不要跨列(最...
    99+
    2018-05-25
    MySQL优化之避免索引失效的方法
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作