MySQL 索引(入門): 一、介紹 1.什麼是索引? 一般的應用系統,讀寫比例在10:1左右,而且插入操作和一般的更新操作很少出現性能問題,在生產環境中,我們遇到最多的,也是最容易出問題的,還是一些複雜的查詢操作,因此對查詢語句的優化顯然是重中之重。說起加速查詢,就不得不提到索引了。 2.為什麼要 ...
MySQL 索引(入门):
一、介绍
1.什么是索引?
一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句的优化显然是重中之重。说起加速查询,就不得不提到索引了。
2.为什么要有索引呢?
引在MySQL中也叫做“键”,是存储引擎用于快速找到记录的一种数据结构。索引对于良好的性能
非常关键,尤其是当表中的数据量越来越大时,索引对于性能的影响愈发重要。
索引优化应该是对查询性能优化最有效的手段了。索引能够轻易将查询性能提高好几个数量级。
索引相当于字典的音序表,如果要查某个字,如果不使用音序表,则需要从几百页中逐页去查。
3.主要优点:
索引大大减小了服务器需要扫描的数据量,从而大大加快数据的检索速度,这也是创建索引的最主要的原因。
可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
4.缺点:
创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加
索引需要占物理空间,除了数据表占用数据空间之外,每一个索引还要占用一定的物理空间。
表中的数据进行增、删、改的时候,索引也要动态的维护,这就降低了整数的维护速度
对于非常小的表,大部分情况下简单的全表扫描更高效
二、索引的本质
索引原理:索引的目的在于提高查询效率,与我们查阅图书所用的目录是一个道理:先定位到章,然后定位到该章下的一个小节,然后找到页数。相似的例子还有:查字典,查火车车次,飞机航班等
索引本质:通过不断地缩小想要获取数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件,也就是说,有了这种索引机制,我们可以总是用同一种查找方式来锁定数据。
三、MySQL的索引分类
1.普通索引 index :加速查找
2.唯一索引 与普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须是唯一的,创建方法和普通索引类似。 主键索引:primary key :加速查找+约束(不为空且唯一) 唯一索引:unique:加速查找+约束 (唯一)
3.联合索引(组合索引) 平时用的SQL查询 语句一般都有比较多的限制条件,所以为了进一步榨取MySQL的效率,就要考虑建立组合索引。
-primary key(id,name):联合主键索引
-unique(id,name):联合唯一索引
-index(id,name):联合普通索引
4.全文索引 fulltext :用于搜索很长一篇文章的时候,效果最好。
5.空间索引 spatial :了解就好,几乎不用
案例:
CREATE DATABASE IF NOT EXISTS info DEFAULT CHARSET utf8; USE info; # 创建表 CREATE TABLE IF NOT EXISTS emp(emp_id INT PRIMARY KEY AUTO_INCREMENT, emp_name VARCHAR(20), salary INT, dept_id INT, manager_id INT ); # 插入数据 INSERT INTO emp (emp_name,salary,dept_id,manager_id)VALUES ("张三",1000,1,1), ("李四",2000,1,1), ("王五",5000,2,3), ("林青霞",8000,3,6), ("风清扬",6000,5,4), ("花无缺",10000,5,5), ("景天",14000,8,7), ("赵敏",17000,8,7); # 给一个列的每个值 创建单独标记 利用索引创建的这些标记可以进行一个排序,更快查询 SELECT * FROM emp WHERE emp_name = "李四"; # 1.1 创建索引:单独创建索引 CREATE INDEX index_name ON emp(emp_name); SELECT * FROM emp WHERE emp_name = "李四"; # 1.2 创建索引:修改表结构创建索引 ALTER TABLE emp ADD INDEX index_salary(salary); # 1.3 创建索引:创建表时,创建索引 CREATE TABLE IF NOT EXISTS article(id INT NOT NULL AUTO_INCREMENT, title VARCHAR(30) NOT NULL, content VARCHAR(50), dt DATE, PRIMARY KEY(id), INDEX index_title(title) ); # 2 删除索引 DROP INDEX index_name ON emp; # 3.1 唯一索引:索引标记的列的值必须唯一 CREATE UNIQUE INDEX index_name ON emp(emp_name); # 3.2 修改表时创建唯一索引 ALTER TABLE article ADD UNIQUE INDEX index_content(content); # 3.3 创建表时创建唯一索引 CREATE TABLE IF NOT EXISTS test (id INT NOT NULL AUTO_INCREMENT , tname VARCHAR(20) NOT NULL, age INT NOT NULL, s_id INT NOT NULL, PRIMARY KEY (id), UNIQUE INDEX index_id(s_id) ) # 4.1 单独创建组合索引 CREATE INDEX index_ct ON article(content,dt); SELECT * FROM article WHERE content='123' AND dt = "2020-10-10" # 4.2 修改表结构时创建组合结构 ALTER TABLE test ADD INDEX index_to(tname,age); # 4.3 创建表时创建组合索引 CREATE TABLE IF NOT EXISTS test02(id INT NOT NULL AUTO_INCREMENT, tname VARCHAR(20) NOT NULL, age INT NOT NULL, s_id INT NOT NULL, PRIMARY KEY (id), UNIQUE INDEX index_to(s_id,id) )
四、复合索引
一列的索引称为单列索引,多列的称为复合索引,因为BTREE索引是顺序排列的,所以比较适合范围查询,但是在复合索引中,还应注意列数目、列的顺序以及前面范围查询的列对后边列的影响。
# 建表
create table staffs( id int primary key auto_increment, name varchar(24) not null default '' comment '姓名', age int not null default 0 comment '年龄', pos varchar(20) not null default '' comment '职位', add_time timestamp not null default current_timestamp comment '入职时间' ) charset utf8 comment '员工记录表';
# 添加三列的复合索引
alter table staffs add index idx_nap(name, age, pos);
#1. 全值匹配
select * from staffs where name = 'July' and age = '23' and pos = 'dev' ;
#2. 匹配最左列 对于复合索引来说,不总是匹配所有字段列,但是可以匹配索引中靠左的列。
select * from staffs where name = 'July' and age = '23';
# key字段显示用到了索引,注意,key_len字段(表示本次语句使用的索引长度)数值比上一条小了,意思是它并未使用全部索引列,事实上只用到了name和age列
#3. 匹配列前缀
select * fromstaffs where name like 'J%';
# 即一个索引中列的前一部分,主要用在模糊匹配
#4. 匹配范围
select * from staffs where name > 'Mary';
#5. 精确匹配一列并范围匹配右侧相邻列
select * from staffs where name = 'July' and age > 25;
# 即前一列是固定值,后一列是范围值,它用了name与age两个列的索引(key_len推测)
#6. 只访问索引的查询
select name,age,pos from staffs where name = 'July' and age = 25 and pos = 'dev';
select name,age from staffs where name = July and age > 25;
# 比如staffs表的情况,索引建立在(name,age,pos)上面,前面一直是读取的全部列,如果我们用到了哪些列的索引,查询时也只查这些列的数据,就是只访问索引的查询