【SQL】索引的创建与设计原则

news2025/7/9 5:59:02

【SQL】索引的创建与设计原则

  • 索引的声明与使用
    • 索引的创建
    • 删除索引
  • 索引设计原则
    • 数据准备:
    • 哪些情况适合创建索引
  • 不适合创建索引的情况

索引的声明与使用

索引的创建

# 索引的创建
#法1:create table
# 隐式方式创建索引.在声明有主键约束、唯一性约束、外键约束的字段上,会自动添加相关索引,
CREATE DATABASE dbtest2;
USE dbtest2;
CREATE TABLE dept(
dept_id INT PRIMARY KEY AUTO_INCREMENT,
dept_name VARCHAR(20)
);

CREATE TABLE emp(
emp_id INT PRIMARY KEY AUTO_INCREMENT,
emp_name VARCHAR(20) UNIQUE,
dept_id INT,
CONSISTENT  emp_dept_id_fk FOREIGN KEY(dept_id) REFERENCES dept(dept_id)
);

# 法2:显式方式创建
# ① 创建普通索引
CREATE TABLE book(
book_id INT,
book_name VARCHAR(100),
AUTHORS VARCHAR(100),
info VARCHAR(100),
COMMENT VARCHAR(100),
year_publication YEAR,
# 声明索引
INDEX idx_bname(book_name)
);

# 通过命令查看索引
#方式1:
SHOW CREATE TABLE book;
#方式2:
SHOW INDEX FROM book;

# 性能分析工具:
EXPLAIN SELECT * FROM book WHERE book_name = 'mysql';

# ② 创建唯一索引
# 声明有唯一索引的字段,在添加数据时,要保证唯一性,但是可以添加null值
CREATE TABLE book1(
book_id INT,
book_name VARCHAR(100),
AUTHORS VARCHAR(100),
info VARCHAR(100),
COMMENT VARCHAR(100),
year_publication YEAR,
# 声明索引
UNIQUE INDEX uk_idx_cmt(COMMENT)
);

SHOW INDEX FROM book1;

INSERT INTO book1(book_id,book_name,COMMENT)
VALUES(1,'MYSQL高级','适合有数据库开发经验的人员学习');

SELECT * FROM book1;

# ③ 主键索引
# 通过定义主键约束的方式定义主键索引
CREATE TABLE book2(
book_id INT PRIMARY KEY,
book_name VARCHAR(100),
AUTHORS VARCHAR(100),
info VARCHAR(100),
COMMENT VARCHAR(100),
year_publication YEAR
);

SHOW INDEX FROM book2;

# 通过删除主键约束的方式删除主键索引
ALTER TABLE book2
DROP PRIMARY KEY;

# ④ 创建单列索引
CREATE TABLE book3(
book_id INT,
book_name VARCHAR(100),
AUTHORS VARCHAR(100),
info VARCHAR(100),
COMMENT VARCHAR(100),
year_publication YEAR,
# 声明索引
UNIQUE INDEX idx_bname(book_name)
);

SHOW INDEX FROM book3;

# ⑤ 创建联合索引
CREATE TABLE book4(
book_id INT,
book_name VARCHAR(100),
AUTHORS VARCHAR(100),
info VARCHAR(100),
COMMENT VARCHAR(100),
year_publication YEAR,
# 声明索引
INDEX mul_bid_bname_info(book_id,book_name,info)
);

SHOW INDEX FROM book4;

# ⑥ 创建全文索引
CREATE TABLE test4(
id INT NOT NULL,
NAME CHAR(30) NOT NULL,
age INT NOT NULL,
info VARCHAR(255),
FULLTEXT INDEX futxt_idx_info(info(50))
);

SHOW INDEX FROM test4;

删除索引

# 索引删除
# 方式1:
SHOW INDEX FROM book1;

ALTER TABLE book1
DROP INDEX uk_idx_cmt;
# 添加auto_increment约束字段的唯一索引不能被删除

# 方式2:
SHOW INDEX FROM test4;
DROP INDEX futxt_idx_info ON test4;

# 联合索引中的某个字段删除
SHOW INDEX FROM book4;

ALTER TABLE book4
DROP COLUMN book_name;

ALTER TABLE book4
DROP COLUMN book_id;

ALTER TABLE book4
DROP COLUMN info;

索引设计原则

数据准备:

CREATE DATABASE atguigudb1;
USE atguigudb1;
#1.创建学生表和课程表
CREATE TABLE `student_info` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`student_id` INT NOT NULL ,
`name` VARCHAR(20) DEFAULT NULL,
`course_id` INT NOT NULL ,
`class_id` INT(11) DEFAULT NULL,
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
CREATE TABLE `course` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`course_id` INT NOT NULL ,
`course_name` VARCHAR(40) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

#函数1:创建随机产生字符串函数
DELIMITER //
CREATE FUNCTION rand_string(n INT)
RETURNS VARCHAR(255) #该函数会返回一个字符串
BEGIN
DECLARE chars_str VARCHAR(100) DEFAULT
'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
DECLARE return_str VARCHAR(255) DEFAULT '';
DECLARE i INT DEFAULT 0;
WHILE i < n DO
SET return_str =CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*52),1));
SET i = i + 1;
END WHILE;
RETURN return_str;
END //
DELIMITER ;
# 创建时报错,进行下面的设置:
SELECT @@log_bin_trust_function_creators;
SET GLOBAL log_bin_trust_function_creators=1;

#函数2:创建随机数函数
DELIMITER //
CREATE FUNCTION rand_num (from_num INT ,to_num INT) RETURNS INT(11)
BEGIN
DECLARE i INT DEFAULT 0;
SET i = FLOOR(from_num +RAND()*(to_num - from_num+1)) ;
RETURN i;
END //
DELIMITER ;

# 存储过程1:创建插入课程表存储过程
DELIMITER //
CREATE PROCEDURE insert_course( max_num INT )
BEGIN
DECLARE i INT DEFAULT 0;
SET autocommit = 0; #设置手动提交事务
REPEAT #循环
SET i = i + 1; #赋值
INSERT INTO course (course_id, course_name ) VALUES
(rand_num(10000,10100),rand_string(6));
UNTIL i = max_num
END REPEAT;
COMMIT; #提交事务
END //
DELIMITER ;
# 存储过程2:创建插入学生信息表存储过程
DELIMITER //
CREATE PROCEDURE insert_stu( max_num INT )
BEGIN
DECLARE i INT DEFAULT 0;
SET autocommit = 0; #设置手动提交事务
REPEAT #循环
SET i = i + 1; #赋值
INSERT INTO student_info (course_id, class_id ,student_id ,NAME ) VALUES
(rand_num(10000,10100),rand_num(10000,10200),rand_num(1,200000),rand_string(6));
UNTIL i = max_num
END REPEAT;
COMMIT; #提交事务
END //
DELIMITER ;

CALL insert_course(100);
CALL insert_stu(1000000);

SELECT COUNT(*) FROM student_info;

哪些情况适合创建索引

① 字段的数值有唯一性的限制
② 频繁作为where查询条件的字段
③ 经常group by和order by的列
④ UPDATE、DELETE 的 WHERE 条件列
⑤ DISTINCT 字段需要创建索引

# 哪些情况适合创建索引
# ① 字段的数值有唯一性的限制
# ② 频繁作为where查询条件的字段
# 查看当前student_info表中的情况
SHOW INDEX FROM student_info;
# student_id 字段上没有索引
SELECT course_id,class_id,NAME,create_time,student_id
FROM student_info
WHERE student_id = 123110;	#829ms

#给student_id字段添加索引
ALTER TABLE student_info
ADD INDEX idx_sid(student_id);

# student_id字段上有索引的
SELECT course_id,class_id,NAME,create_time,student_id
FROM student_info
WHERE student_id = 123110;	#4ms

# ③ 经常group by和order by的列
# 有索引
SELECT student_id,COUNT(*) AS num
FROM student_info
GROUP BY student_id LIMIT 100;	#3ms

# 删除索引idx_sid
DROP INDEX idx_sid ON student_info;

#无索引
SELECT student_id,COUNT(*) AS num
FROM student_info
GROUP BY student_id LIMIT 100;	#1300ms

# 对于两个字段有无索引的对比
SHOW INDEX FROM student_info;

# 添加单列索引
ALTER TABLE student_info
ADD INDEX idx_sid(student_id);

ALTER TABLE student_info
ADD INDEX idx_cre_time(create_time);

EXPLAIN SELECT student_id,COUNT(*) AS num FROM student_info
GROUP BY student_id
ORDER BY create_time DESC
LIMIT 100;	# 6min 用了idx_sid

SELECT @@sql_mode;

# 添加联合索引
# 当我们使用 GROUP BY 对数据进行分组查询,或者使用 ORDER BY 对数据进行排序的时候,
# 就需要对分组或者排序的字段进行索引。
ALTER TABLE student_info
ADD INDEX idx_sid_cre_time(student_id,create_time DESC);

EXPLAIN SELECT student_id,COUNT(*) AS num FROM student_info
GROUP BY student_id
ORDER BY create_time DESC
LIMIT 100;	#608ms  	查询速度更快,使用了联合索引

#
ALTER TABLE student_info
ADD INDEX idx_cre_time_sid(create_time DESC,student_id);	# 改变联合索引字段顺序

DROP INDEX idx_sid_cre_time ON student_info;	
# 删除之前创建的sid打头的联合索引,再次执行select操作,发现实际使用的仍是idx_sid索引,
# 并非新创建的联合索引idx_cre_time_sid

# ④ UPDATE、DELETE 的 WHERE 条件列
UPDATE student_info SET student_id = 10002
WHERE NAME = '462eed7ac6e791292a79'; 	#2.274s

SHOW INDEX FROM student_info;
# 添加索引
ALTER TABLE student_info
ADD INDEX idx_name(NAME);

UPDATE student_info SET student_id = 10001
WHERE NAME = '462eed7ac6e791292a79'; 	#0.002s

# ⑤ DISTINCT 字段需要创建索引
# 索引会按顺序对数据排序,所以在去重时会快很多

# ⑥ 多表 JOIN 连接操作时,创建索引注意事项
# 连接表的数量尽量不要超过 3 张,因为每增加一张表就相当于增加了一次嵌套的循环,数量级增长会非常快,严重影响查询的效率。
# 对 WHERE 条件创建索引,因为 WHERE 才是对数据条件的过滤。如果在数据量非常大的情况下,没有 WHERE 条件过滤是非常可怕的。
# 对用于连接的字段创建索引,并且该字段在多张表中的类型必须一致。比如 course_id 在student_info 表和 course 表中都为 int(11) 类型,而不能一个为 int 另一个为 varchar 类型。

EXPLAIN SELECT student_info.course_id, NAME, student_info.student_id, course_name
FROM student_info JOIN course
ON student_info.course_id = course.course_id
WHERE NAME = '462eed7ac6e791292a79';

# ⑦ 使用列的类型小的创建索引
# ⑧ 使用字符串前缀创建索引
# ⑨ 区分度高(散列性高)的列适合作为索引
# ⑩ 使用最频繁的列放到联合索引的左侧
# 补充:在多个字段都要创建索引的情况下,联合索引优于单值索引

注意:
在这里插入图片描述

不适合创建索引的情况

  1. 在where中使用不到的字段,不要设置索引
  2. 数据量小的表最好不要使用索引
  3. 大量重复数据的列上不要建立索引
    当数据重复度大,比如高于 10% 的时候,也不需要对这个字段使用索引。
  4. 避免对经常更新的表创建过多的索引
  5. 不建议用无序的值作为索引
    例如身份证、UUID(在索引比较时需要转为ASCII,并且插入时可能造成页分裂)、MD5、HASH、无序长字
    符串等。
  6. 删除不再使用或者很少使用的索引
  7. 不要定义冗余或重复的索引
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/18417.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java项目-第146期ssm人事工资管理系统(spring+springmvc+mybatis+jsp)_java毕业设计_计算机毕业设计

java项目-第146期ssm人事工资管理系统(springspringmvcmybatisjsp)_java毕业设计_计算机毕业设计 【源码请到资源专栏下载】 今天分享的项目是《ssm人事工资管理系统》 该项目分为2个角色&#xff0c;管理员和用户。 用户可以浏览前台,包含功能有&#xff1a; 个人中心、公告信…

gin binding方法汇总

为了能够更方便的获取请求相关参数&#xff0c;提高开发效率&#xff0c;gin框架提供了Bind系列方法。 分类 Bind系列方法大致分两类&#xff1a; Should类型Must类型 二者的区别就是&#xff1a;should和must的区别&#xff0c;即must绑定失败会报错 关系图 Should类型 …

【licheePi-dock】驱动一个OLED-SSD1306

【licheePi-dock】驱动一个OLED-SSD1306OLED驱动修改设备树向内核添加驱动1.找到一个合适的位置&#xff0c;创建oled驱动文件&#xff1a;修改当前目录下的Kconfig和Makefile把驱动添加进内核编译编写应用程序编译我使用的是cmakeOLED驱动 本文使用的是i2c驱动的OLED【Lichee…

【PowerQuery】在Excel中手动刷新数据连接

将数据通过PowerQuery 导入进来后,这里将进行数据分组运算,最终的数据计算结果将保存在Excel 表格中,图1为数据导入结果。 图1 使用PowerQuery 加载导入的数据 在Excel中,如果我们希望进行销售统计的手动更新可以使用几种不同的方法来进行刷新这些数据。 1.刷新单一数据连…

UJNOJ_1000-1007_python

1000: AB Problem 内存限制&#xff1a;128 MB时间限制&#xff1a;10 S 评测方式&#xff1a;文本比较命题人&#xff1a;jiangyan 提交&#xff1a;109解决&#xff1a;87 提交提交记录统计 题目描述 Calculate ab result 输入 Two integer a,b (0<a,b<10) …

青少年python系列 46.文件操作2

青少年python教学视频ppt源码 青少年ptyhon可以参加的主流比赛大全_老程序员115的博客-CSDN博客 在上节课我们学习了如何查询文本信息内容&#xff0c;那我们能否使用Python来往文本中保存数据信息呢&#xff1f;当然也是可以的。Python可以完成将数据信息写入文件&#xff0c…

【机器学习】主成分分析

有任何的书写错误、排版错误、概念错误等&#xff0c;希望大家包含指正。 维数灾难 在高维情形下出现的数样本稀疏、距离计算困难等问题&#xff0c;是所有机器学习方法共同面临的的严重障碍&#xff0c;被称为“维数灾难”或“维数危机”&#xff08;curse of dimensionality…

MongoDB的安装配置及使用(WIndows/Java)

Hi&#xff0c;I‘m Shendi 下面主要介绍使用 Windows安装 MongoDB 和使用 Java 操作 文章目录MongoDB下载创建数据目录运行配置安装服务创建用户用户角色列表Java使用查询数据插入数据修改数据删除数据设置数据过期时间其他问题MongoClient是否需要关闭&#xff1f;内存为什么…

2022.11组队学习——跨模态视频搜索VCED

文章目录一、环境配置&#xff08;1.2章节可跳过&#xff09;1.1 docker启动本项目1.1.1 win10下安装docker1.1.2 配置容器1.1.3 启动项目1.2 使用vmware下的liunx启动本项目1.2.1 升级python3.91.2.2 安装其他包1.3 使用WSL下的linux启动本项目1.3.1 安装WSL1.3. 2安装Ubuntu1…

预测市场赛道新机遇:Moonquiz生态基于FIFA WORLD CUP推出首个预测应用

对未来事件的预测始终有着较为重要的意义&#xff0c;无论是对天气、地质灾害等的预测&#xff0c;还是对金融市场、事件走势等的预测&#xff0c;都有望让个人和组织对潜在的风险进行对冲&#xff0c;并获得最大化收益。 从Web3领域看&#xff0c;预测市场是活跃于加密行业早期…

M1 在VMware里安装Centos8

本文档主要介绍Mac M1芯片如何通过Vmware虚拟机&#xff0c;安装Centos系统。 安装准备 安装之前需要下载虚拟机安装包和Centos8镜像。 百度云自取链接: https://pan.baidu.com/s/19bPaU5Vf8HG6sv3C_jZDXw 提取码: 6jen 链接内容如下&#xff0c;centos8镜像&#xff0c;vm…

Linux零拷贝解析

目录 先备知识 物理内存 虚拟内存 内核空间和用户空间 内核空间 用户空间 DMA传输 上下文切换 传统IO执行流程 零拷贝实现的几种方式 用户态直接I/O mmapwrite实现的零拷贝 sendfile实现的零拷贝&#xff08;用户不可见&#xff09; sendfileDMA scatter/gather实…

kubernetes(K8S)学习笔记P1:基本概念和架构

kubernetes&#xff08;K8S&#xff09;学习笔记1.基本概念和架构1.1K8s概述和特性1.1.1概述1.1.2特性1.2K8s架构组件1.3平台规划1.4服务器硬件配置要求1.4.1测试环境1.4.2开发环境 (要求更高)1.5搭建k8s集群部署方式1.5.1 kubeadm 方式&#xff08;简单&#xff09;1.5.2二进制…

数据结构---串(整个部分)

串基本概念&#xff1a;串是由零个或者多个字符组成的有限序列&#xff0c;一半记作Sa1,a2,a3,a4.......&#xff08;n>0&#xff0c;串的长度&#xff09; 1.S 串的名字 n 串当中字符串的个数&#xff0c;称为串的长度。 串的常用术语 1.空串&#xff08;null stri…

[附源码]计算机毕业设计JAVA红河旅游信息服务系统

[附源码]计算机毕业设计JAVA红河旅游信息服务系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM my…

Swin Transformer代码实现部分细节重点

swin transformer 1.patch-merging部分 代码&#xff1a;【amazing】 x0 x[:, 0::2, 0::2, :] # [B, H/2, W/2, C] 对应图片所有 1 的位置x1 x[:, 1::2, 0::2, :] # [B, H/2, W/2, C] 对应图片所有 3 的位置x2 x[:, 0::2, 1::2, :] # [B, H/2, W/2, C] 对应图片所有…

pve独显直连

目录折腾初步工作安装配置源去除订阅提示安装vim开启iommu屏蔽显卡驱动创建虚拟机体验折腾 买了个新笔记本&#xff0c;老的笔记本也没啥用了&#xff0c;挂二手平台也出不了多少钱。就想着自己折腾的新东西。之前有个PVE虚拟机感觉很不错&#xff0c;现在尝试一下怎么使用 初…

用HTML+CSS6音乐吧 7页

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 音乐网页设计 | 仿网易云音乐 | 各大音乐官网网页 | 明星音乐演唱会主题 | 爵士乐音乐 | 民族音乐 | 等网站的设计与制作 | HTML期末大学生网页设计作…

[附源码]SSM计算机毕业设计在线购物系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…