MySQL基础之索引

基础

索引介绍

​ 索引(在MySQL中也叫做“键(key)”)是存储引擎用于快速找到记录的一种数据结构。索引是进行SQL优化时最常用的工具,但是不合理的索引不仅对性能提升没有帮助可能还会造成负担。

索引的分类

  • 按功能分类

    • 主键索引:一张表只能有一个主键索引,不允许重复、不允许为 NULL。
    • 外键索引:一张表可以有多个外键,允许重复、允许为 NULL。
    • 唯一索引:一张表可以有多个唯一索引,索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。
    • 普通索引:一张表可以创建多个普通索引,一个普通索引可以包含多个字段,允许数据重复,允许 NULL 值插入。
    • 全文索引:它查找的是文本中的关键词,主要用于全文检索。
    • 空间索引:
      • 空间索引是对空间数据类型的字段建立的索引,MySQL中的空间数据类型有4种,分别是GEOMETRY、POINT、LINESTRING和POLYGON。MySQL使用SPATIAL关键字进行扩展,使得能够用于创建正规索引类似的语法创建空间索引。
  • 按列数分类
    • 单例索引:一个索引只包含一个列,一个表可以有多个单例索引。
    • 组合索引:一个组合索引包含两个或两个以上的列。
  • 存储方式分类
    • 聚簇索引:聚簇索引(clustered index)不是单独的一种索引类型,而是一种数据存储方式。这种存储方式是依靠B+树来实现的,根据表的主键构造一棵B+树且B+树叶子节点存放的都是表的行记录数据时,方可称该主键索引为聚簇索引。聚簇索引也可理解为将数据存储与索引放到了一块,找到索引也就找到了数据。
    • 非聚簇索引:非聚簇索引数据和索引是分开的,B+树叶子节点存放的不是数据表的行记录而是主键值。首先通过辅助索引找到主键值,然后到主键索引树中通过主键值找到数据行。
  • 数据结构分类:
    • B+Tree:支持范围查询(InnoDB和MyISAM存储引擎都只支持B+Tree)。
    • Hash:Hash结构的优点是只需要经过一次算法即可找到相应的键值,速度比较快,但是不支持范围查询(InnoDB和MyISAM引擎都不支持Hash索引,MEMORY引擎支持)。

创建索引

建表时建立索引

CREATE TABLE `index_test` (`id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '主键',`int_hash_key` int DEFAULT NULL COMMENT '数值类型的hash索引',`int_tree_key` int DEFAULT NULL COMMENT '数值类型的tree索引',`str_hash_key` varchar(32) DEFAULT NULL COMMENT '字符串hash索引',`str_tree_key` varchar(32) DEFAULT NULL COMMENT '字符串tree索引',`time_hash_key` datetime DEFAULT NULL COMMENT '日期hash索引',`time_tree_key` datetime DEFAULT NULL COMMENT '日期tree索引',`unite_hash_1` varchar(32) DEFAULT NULL COMMENT '联合索引',`unite_hash_2` varchar(32) DEFAULT NULL COMMENT '联合索引',`not_index_str` varchar(255) DEFAULT NULL COMMENT '没有索引',PRIMARY KEY (`id`) USING BTREE,UNIQUE KEY `index_int_hash_key` (`int_hash_key`),UNIQUE KEY `index_int_tree_key` (`int_tree_key`) USING BTREE,UNIQUE KEY `inde_str_hash_key` (`str_hash_key`),UNIQUE KEY `inde_str_tree_key` (`str_tree_key`) USING BTREE,UNIQUE KEY `inde_unite` (`unite_hash_1`,`unite_hash_2`) USING BTREE,KEY `inde_time_hash_key` (`time_hash_key`) USING BTREE,KEY `inde_time_tree_key` (`time_tree_key`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

添加索引语法一

  • CREATE INDEX 不能创建主键索引。
-- 完整语法
CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX index_name[index_type]ON tbl_name (key_part,...)[index_option][algorithm_option | lock_option]
-- 示例
CREATE UNIQUE INDEX index_int_hash_key USING BTREE ON index_test(`int_tree_key`);

添加索引语法二

-- 完整语法-添加索引
ALTER TABLE tbl_name ADD {FULLTEXT | SPATIAL | PRIMARY} [INDEX | KEY] [index_name] (key_part,...) [index_option]
-- 完整语法-添加外键
ALTER TABLE tbl_nameADD [CONSTRAINT [symbol]] FOREIGN KEY[index_name] (col_name, ...)REFERENCES tbl_name (col_name,...)[ON DELETE reference_option][ON UPDATE reference_option]
-- 示例-添加主键索引
ALTER TABLE tbl_name ADD PRIMARY KEY (`id`);
-- 示例-添加外键索引
ALTER TABLE tbl_name_child ADD FOREIGN KEY fk_index_name(col_name) REFERENCES tbl_name_father (id);
-- 示例-添加主键索引
ALTER TABLE index_test ADD UNIQUE index_test(`int_tree_key`);

删除索引

-- 删除普通索引
DROP INDEX {index_name} ON {table_name};
-- 删除普通索引
ALTER TABLE {table_name} DROP INDEX {index_name};
-- 删除主键索引
ALTER TABLE {index_name} DROP PRIMARY KEY;

聚簇索引

  • 聚簇索引

    • 聚簇索引(clustered index)不是单独的一种索引类型,而是一种数据存储方式。这种存储方式是依靠B+树来实现的,根据表的主键构造一棵B+树且B+树叶子节点存放的都是表的行记录数据时,方可称该主键索引为聚簇索引。聚簇索引也可理解为将数据存储与索引放到了一块,找到索引也就找到了数据。
    • 优点:
      • 数据访问更快,因为聚簇索引将索引和数据保存在同一个B+树中,因此从聚簇索引中获取数据比非聚簇索引更快。
      • 聚簇索引对于主键的排序查找和范围查找速度非常快。
    • 缺点:
      • 插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于InnoDB表,我们一般都会定义一个自增的ID列为主键。
      • 更新主键的代价很高,因为将会导致被更新的行移动。因此,对于InnoDB表,我们一般定义主键为不可更新。
      • 二级索引访问需要两次索引查找,第一次找到主键值,第二次根据主键值找到行数据。
  • 非聚簇索引
    • 非聚簇索引:数据和索引是分开的,B+树叶子节点存放的不是数据表的行记录而是主键值。首先通过辅助索引找到主键值,然后到主键索引树中通过主键值找到数据行。

虽然InnoDB和MyISAM存储引擎都默认使用B+树结构存储索引,但是只有InnoDB的主键索引才是聚簇索引,InnoDB中的辅助索引以及MyISAM使用的都是非聚簇索引。每张表最多只能拥有一个聚簇索引。

全文索引

​ InnoDB和MyISAM引擎表支持全文索引,全文索引只能加在 CHARVARCHATEXT 类型列。MySQL5.7版本提供了一个内置的ngram解析器,支持中文、日文、韩文(MeCab日文解析器可以单独安装)。

创建表

DROP TABLE IF EXISTS `opening_lines`;
CREATE TABLE `opening_lines` (id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,opening_line TEXT ( 500 ),author VARCHAR ( 200 ),title VARCHAR ( 200 ),FULLTEXT idx ( opening_line ) WITH PARSER ngram
) ENGINE = INNODB;
-- 单独创建索引
ALTER TABLE opening_lines ADD FULLTEXT INDEX ft_index (author) WITH PARSER ngram;
-- 单独创建索引
CREATE FULLTEXT INDEX ft_index ON opening_lines (title) WITH PARSER ngram;

插入数据

INSERT INTO opening_lines(`opening_line`,`author`,`title`) VALUES ('床前明月光,疑是地上霜','李白','唐·李白');
INSERT INTO opening_lines(`opening_line`,`author`,`title`) VALUES ('志不立,天下无可成之事','王阳明','理智名言');

搜索匹配


-- 1条数据
SELECT * FROM opening_lines WHERE MATCH(opening_line) AGAINST('志不立');
-- 0条数据
SELECT * FROM opening_lines WHERE (MATCH(opening_line) AGAINST('-志不立' IN boolean MODE));
-- 1条数据
SELECT * FROM opening_lines WHERE (MATCH(opening_line) AGAINST('+志不立' IN boolean MODE));

注意:中文内容需要指定ngram分析器,不然可能匹配不到数据(默认解析器对中文及其不友好)。

建议:如果数据量比较大,并且需要复杂搜索,搜索结果高亮,自定义过滤,自定义停用词,近义词等复杂需求时建议使用ES替代。

空间索引

讲空间索引之前,我们需要先了解一下空间数据类型,MySQL支持的空间数据类型有 pointlinestringpolygongeometry 以及它们的集合形式 multipointmultilinestringmultipolygongeometrycollectionn。这些类型支持一些特殊的空间集合函数,可以应用在地图、绘画、用户行为监控等场景。对于InnoDB和MyISAM引擎的表,MySQL可以使用创建普通索引的语法创建空间索引。空间索引的列必须声明为NOT NULL。

创建表

DROP TABLE IF EXISTS `space`;
CREATE TABLE `space` (`id` int NOT NULL,`geometry` geometry DEFAULT NULL COMMENT '几何',`point` point DEFAULT NULL COMMENT '点',`linestring` linestring DEFAULT NULL COMMENT '线',`polygon` polygon DEFAULT NULL COMMENT '多边形',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

插入数据

INSERT INTO `space`(id,`linestring`) VALUES (1,ST_GeomFromText('linestring(1 1,1 2)'));
INSERT INTO `space`(id,`linestring`) VALUES (2,ST_GeomFromText('linestring(2 1,2 5)'));
INSERT INTO `space`(id,`linestring`) VALUES (3,ST_GeomFromText('linestring(3 3,3 6)'));

数据应用

-- MBRContains函数:查询与参数边界重合的记录。
SELECT * FROM space WHERE MBRContains(ST_GeomFromText('linestring(1 1,1 2)'),`linestring`);

创建空间索引

-- 创建索引-1
CREATE SPATIAL INDEX {index_name} ON {index_name} (col_name);
-- 创建索引-2
ALTER TABLE {index_name} ADD SPATIAL INDEX(col_name);

应用

建立原则

  • 建议创建索引的列

    • 当列在 WHERE 子句中经常使用时,建议添加索引。
    • 当列值重复率比较低且比较有规律时,建议添加索引(例如:身份证、手机号、订单编号、优惠券码、创建时间)。
    • 当列经常用来排序时,建议添加索引(索引已经排序,这样在查询时可以利用索引的排序,加快排序查询时间)。
  • 不建议创建索引的列

    • 当列很少参与到查询中,不建议加索引(因为有无索引都不会提高查询速度,反而增加了索引维护和存储的开销)。
    • 当列值重复率比较高时,不建议加索引(例如:性别、年龄、民族)。
    • 当列的数据类型为 textimagebit 等数据类型时,不建议加索引(这些列一般数据量比较大)。
    • 当列的修改操作远远大于检索性能时,不建议增加索引(增加索引对数据编辑会有性能损耗)。

索引失效

  • like:当 % 在后索引生效,在前索引失效。
  • 范围查询:当命中的数据范围较小或者需要操作的数据较小时应用索引。
  • 负向查询:除主键列外,其它索引列的负向查询都不走索引。
  • ORDER BY:对主键索引排序会用到索引,其他的索引失效(覆盖索引除外)。
  • 类型不一致:隐式类型转换会引发索引失效,在进行比较是要确保类型正确,严重的情况会直接报错。
  • 联合索引:违背最左匹配原则,会导致索引失效。
  • OR:索引列与非索引列进行 OR 会造成索引失效。
  • Hash索引:Hash类型的索引不支持范围查询,如果使用范围查询则导致索引失效(注意:InnoDB和MyISAM存储引擎不支持Hahs索引)。

MySQL基础之索引相关推荐

  1. MySQL基础(六)-索引(index)详解

    目录 一.什么是索引? 二.索引的实现原理 三.在MySQL中,主键.unique字段上会自动添加索引. 四.索引的创建与删除 创建索引: 删除索引: 五.查看SQL语句是否使用了索引 六.索引的失效 ...

  2. mongo 唯一约束索引_Java:MySQL 基础知识+索引相关

    阅读本文前,请您先点击上面的蓝色字体,再点击"关注",这样您就可以继续免费收到最新文章了.每天都有分享.完全是免费订阅,请放心关注.注:本文转载自网络,不代表本平台立场,仅供读者参 ...

  3. Mysql基础知识—索引

    公司最近开始尝试进行改革,如何活跃团队气氛.开发就给我们说了一些算是科普类的数据库知识,下面参杂自己的理解,方便自己后续翻看. 1.什么是索引 索引在MySQL中也叫做"键",是存 ...

  4. MySQL基础(三):视图、存储过程、事务与索引

    一:视图 视图是虚拟的表: 它们包含的不是数据而是根据需要检索数据的查询: 视图提供了一种封装SELECT语句的层次,可用来简化数据处理以及重新格式化基础数据或保护基础数据. 视图的作用: 1,重用S ...

  5. MySQL基础(二十八)索引优化与查询优化

    都有哪些维度可以进行数据库调优?简言之: 索引失效.没有充分利用到索引--索引建立 关联查询太多JOIN (设计缺陷或不得已的需求)--SQL优化 服务器调优及各个参数设置(缓冲.线程数等)---调整 ...

  6. MySQL基础下篇[表的创建/约束的使用/事务和范式以及索引的使用]~

    创建表: 建表的语法格式:(建表属于DDL语句,DDL包括: create, drop, alter) 方式1: create table 表名(字段名1 数据类型,字段名2,数据类型,字段名3,数据 ...

  7. MySQL基础: 索引, 优化, 锁

    一. mysql的架构介绍 ​ 从几年前实习开始, 陆陆续续写了好多的markdown笔记, 早期的笔记大多是在B站和一些大牛博客分享而自己整理的笔记, 早期的笔记体系比较清晰,也是我的学习成长路线. ...

  8. MySQL基础篇:子查询

    文章目录 概述 where型子查询 from型子查询 EXISTS型子查询 复制表子查询 概述 在某些情况下,当进行一个查询时,需要的条件或数据要用另一个select语句的结果,这个时候,就要用到** ...

  9. mysql 存储引擎 面试_搞定PHP面试 - MySQL基础知识点整理 - 存储引擎

    MySQL基础知识点整理 - 存储引擎 0. 查看 MySQL 支持的存储引擎 可以在 mysql 客户端中,使用 show engines; 命令可以查看MySQL支持的引擎: mysql> ...

最新文章

  1. 白话 Session 与 Cookie:从经营杂货店开始
  2. 矿泉水功能突破口-丰收节交易会·李喜贵:遵义谋定水产业
  3. 二十万字C/C++、嵌入式软开面试题全集宝典七
  4. IT 行业的创新 - 创新的迷思 (5-6)
  5. ios html 调试,使用iframe和vconsole调试ios网页
  6. 计算机二级c语言填空题怎么算分,计算机二级C语言题型和评分标准
  7. 前端学习(3287):Aop2
  8. windows下hadoop的单机伪分布式部署(3)
  9. 记忆化搜索 codevs 2241 排序二叉树
  10. python内置对象是什么_#【Python】【基础知识】【内置对象常用方法】
  11. 测试必备:单元测试测试类,以帮助匿名管理调查的类为例详解--白盒测试
  12. 树形结构 —— 优先队列
  13. Vultr CentOS下后台跑node
  14. Ansible详解(五)——Ansible其他模块使用详解
  15. Flutter6,移动设备开发网易云音乐app开发说明
  16. 1.3.1 互联网的边缘部分(资源子网)
  17. 两个方法告诉你如何将qlv格式的腾讯视频转换为mp4格式
  18. 窗宽窗位与其处理方法
  19. 培训三天敏捷我懂了这些
  20. Redis淘汰机制(Eviction policies)

热门文章

  1. 利用 Andorid 手机连接 Arduino 并控制 LED灯开关
  2. 大理石在哪里?(Where is the Marble?,UVa 10474 )
  3. ezuikit-js萤石云
  4. 哈希表解决冲突的方式
  5. ffmpeg里转场transition
  6. C语言谭浩强第三版第九章例题及课后题:预处理命令
  7. 中国十大垃圾软件网站
  8. 多模态AI浪潮来袭,或造福数亿视障人群
  9. TGRS2022/云检测:Unsupervised Domain Adaptation for Cloud Detection Based on Grouped Features Alignment
  10. Python编程学习视频