展开
拓展 关闭
订阅号推广码
GitHub
视频
公告栏 关闭

索引的声明和使用

  • 索引的类型
从功能逻辑上说,索引主要有4种,分别是普通索引、唯一索引、主键索引、全文索引
按照物理实现方式,索引可以分为2种:聚簇索引和非聚簇索引
按照作用字段个数进行划分,分成单列索引和联合索引

1.1 普通索引
在创建普通索引时,不附加任何限制条件,只是用于提高查询效率。这类索引可以创建在任何数据类型中,其值是否唯一和非空,要由字段本身的完整性约束条件决定。
建立索引以后,可以通过索引进行查询。例如,在表student的字段name上建立一个普通索引,查询记录时就可以根据该索引进行查询。

1.2 唯一性索引
使用UNIQUE参数可以设置索引为唯一性索引,在创建唯一性索引时,限制该索引的值必须是唯一的,但允许空值。在一张数据表里可以有多个唯一索引。

1.3 主键索引
主键索引就是一种特殊的唯一性索引,在唯一索引的基础上增加了不为空的约束,也就是NOT NULL+UNIQUE,一张表里最多只有一个主键索引。

1.4 单列索引
在表中的单个字段上创建索引。单列索引只根据该字段进行索引。单列索引可以是普通索引,也可以是唯一性索引,还可以是全文索引。只要保证该索引只对应一个字段即可。
一个表可以有多个单列索引。

1.5 多列索引
多列索引是在表的多个字段组合上创建一个索引。该索引指向创建时对应的多个字段,可以通过这几个字段进行查询,但是只有查询条件中使用了这些字段中的第一个字段时才会被使用。
例如,在表中的字段id、name和gender上建立一个多列索引idx_id_name_gender,只有在查询条件中使用了字段id时该索引才会被使用。使用组合索引时遵循最左前缀集合。

1.6 全文索引
全文索引(也称全文检索)是目前搜索引擎使用的一种关键技术。它能够利用【分词技术】等多种算法智能分析出文本文字中关键词的频率和重要性,然后按照一定的算法规则智能地筛选出
我们想要的搜索结果。全文索引非常适合大型数据集,对于小的数据集,它的用处比较小。

1.7 空间索引
使用参数SPATIAL可以设置索引为空间索引。空间索引只能建立在空间数据类型上,这样可以提高系统获取空间数据的效率。MySQL中的空间数据类型包括GEOMETRY、POINT、LINESTRING
和POLYGON等。目前只有MyISAM存储引擎支持空间检索,而且索引的字段不能为空值。对于初学者来说,这类索引很少会用到。
  • 隐式的方式创建索引。在声明有主键约束、唯一性约束、外键约束的字段上,会自动的添加相关的索引
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,
CONSTRAINT emp_dept_id_fk FOREIGN KEY(dept_id) REFERENCES dept(dept_id)
);
  • 创建索引格式(显示)
CREATE TABLE table_name [col_name data_type]
[UNIQUE | FULLTEXT | SPATIAL] [INDEX | KEY] [index_name] (col_name [length]) [ASC |
DESC]

UNIQUE 、 FULLTEXT 和 SPATIAL 为可选参数,分别表示唯一索引、全文索引和空间索引;
INDEX 与 KEY 为同义词,两者的作用相同,用来指定创建索引;
index_name 指定索引的名称,为可选参数,如果不指定,那么MySQL默认col_name为索引名;
col_name 为需要创建索引的字段列,该列必须从数据表中定义的多个列中选择;
length 为可选参数,表示索引的长度,只有字符串类型的字段才能指定索引长度;
ASC 或 DESC 指定升序或者降序的索引值存储
  • 创建普通的索引
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
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;

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

INSERT INTO book1(book_id,book_name,COMMENT)
VALUES(2,'Mysql高级',NULL);
  • 主键索引
# 通过定义主键约束的方式定义主键索引
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;

# 分析
EXPLAIN SELECT * FROM book4 WHERE book_id = 1001 AND book_name = 'mysql';

EXPLAIN SELECT * FROM book4 WHERE book_name = 'mysql';
  • 创建全文索引
# 案例1
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;

# 案例2
CREATE TABLE articles (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR (200),
body TEXT,
FULLTEXT index (title, body)
) ENGINE = INNODB ;

# 在MySQL5.7及之后版本中可以不指定最后的ENGINE了,因为在此版本中InnoDB支持全文索引

# 案例3
CREATE TABLE `papers` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(200) DEFAULT NULL,
`content` text,
PRIMARY KEY (`id`),
FULLTEXT KEY `title` (`title`,`content`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

# 使用全文索引查询
SELECT * FROM papers WHERE MATCH(title,content) AGAINST (‘查询字符串’);

1. 使用全文索引前,搞清楚版本支持情况;
2. 全文索引比 like + % 快 N 倍,但是可能存在精度问题;
3. 如果需要全文索引的是大量数据,建议先添加数据,再创建索引。
  • 创建空间索引
# 空间索引创建中,要求空间类型的字段必须为非空
CREATE TABLE test5(
geo GEOMETRY NOT NULL,
SPATIAL INDEX spa_idx_geo(geo)
) ENGINE=MyISAM;
  • 表已经创建时,创建索引
# 方式1 ALTER TABLE ... ADD ...
CREATE TABLE book5(
book_id INT ,
book_name VARCHAR(100),
AUTHORS VARCHAR(100),
info VARCHAR(100) ,
COMMENT VARCHAR(100),
year_publication YEAR
);

SHOW INDEX FROM book5;

ALTER TABLE book5 ADD INDEX idx_cmt(COMMENT);

ALTER TABLE book5 ADD UNIQUE uk_idx_bname(book_name);

ALTER TABLE book5 ADD INDEX mul_bid_bname_info(book_id,book_name,info);

# 方式2 CREATE INDEX ... ON ...
CREATE TABLE book6(
book_id INT ,
book_name VARCHAR(100),
AUTHORS VARCHAR(100),
info VARCHAR(100) ,
COMMENT VARCHAR(100),
year_publication YEAR
);

SHOW INDEX FROM book6;

CREATE INDEX idx_cmt ON book6(COMMENT);

CREATE UNIQUE INDEX  uk_idx_bname ON book6(book_name);

CREATE INDEX mul_bid_bname_info ON book6(book_id,book_name,info);
  • 删除索引
# 方式1:ALTER TABLE .... DROP INDEX ....
ALTER TABLE book5 
DROP INDEX idx_cmt;

# 方式2:DROP INDEX ... ON ...
DROP INDEX uk_idx_bname ON book5;

# 测试:删除联合索引中的相关字段,索引的变化
ALTER TABLE book5
DROP COLUMN book_name;
  • UPDATE、DELETE 的 WHERE 条件列
对数据按照某个条件进行查询后再进行 UPDATE 或 DELETE 的操作,如果对 WHERE 字段创建了索引,就能大幅提升效率。
原理是因为我们需要先根据 WHERE 条件列检索出来这条记录,然后再对它进行更新或删除。如果进行更新的时候,更新的
字段是非索引字段,提升的效率会更明显,这是因为非索引字段更新不需要对索引进行维护
  • DISTINCT 字段需要创建索引
有时候我们需要对某个字段进行去重,使用 DISTINCT,那么对这个字段创建索引,也会提升查询效率。
  • 多表 JOIN 连接操作时
连接表的数量尽量不要超过 3 张
对 WHERE 条件创建索引 
对用于连接的字段创建索引 ,并且该字段在多张表中的 类型必须一致
  • 使用列的类型小的创建索引

  • 使用字符串前缀创建索引

# 创建一张商户表,因为地址字段比较长,在地址字段上建立前缀索引
create table shop(address varchar(120) not null);

alter table shop add index(address(12));

# 截切合适的长度作为前缀
count(distinct left(列名, 索引长度))/count(*)

select count(distinct address) / count(*) from shop;

# 数值越接近1越合适
select count(distinct left(address,10)) / count(*) as sub10, -- 截取前10个字符的选择度
count(distinct left(address,15)) / count(*) as sub11, -- 截取前15个字符的选择度
count(distinct left(address,20)) / count(*) as sub12, -- 截取前20个字符的选择度
count(distinct left(address,25)) / count(*) as sub13 -- 截取前25个字符的选择度
from shop;
  • 区分度高(散列性高)的列适合作为索引

  • 使用最频繁的列放到联合索引的左侧

  • 在多个字段都要创建索引的情况下,联合索引优于单值索引

  • 索引数量不应创建过多

  • 不适合创建索引的情况

  • 在where中使用不到的字段,不要设置索引

  • 数据量小的表最好不要使用索引

  • 有大量重复数据的列上不要建立索引

  • 避免对经常更新的表创建过多的索引

  • 不建议用无序的值作为索引

  • 删除不再使用或者很少使用的索引

  • 不要定义冗余或重复的索引

posted @ 2022-06-11 08:49  DogLeftover  阅读(50)  评论(0编辑  收藏  举报