《一起学mysql》3
索引和查询优化
为什么要索引?
想想我们上小学的时候是怎么查字典的,比方查 理想的 “理”,首先在索引里找到声母 “l”,再找到 “li”
找到 “li”所在的页数,
我们之前建的所有mysql 表都是没有索引的,找数据就要全表扫描,想象如果字典里的字都是乱序的,我们
要找一个字的话可能需要翻遍整个字典,
同样在msyql 中也有索引,mysql 中的索引有四种:主键,唯一索引,全文索引,普通索引
主键
主键是不可重复,且不能包含null 的索引
创建主键的方式:
法儿一:
create table pk_test(id int,primary key(id));
法儿二:
alter table test add primary key(f1);
主键不可重复指的是主键的组合不重复即可,组成主键的单个字段可能是重复的,例如
MariaDB [jason]> show create table pk_test;
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| pk_test | CREATE TABLE `pk_test` (
`f1` int(11) NOT NULL,
`f2` int(11) NOT NULL,
`f3` char(10) DEFAULT NULL,
PRIMARY KEY (`f1`,`f2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
MariaDB [jason]> insert into pk_test (f1,f2) values(1,1),(1,2);
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
MariaDB [jason]> select * from pk_test;
+----+----+------+
| f1 | f2 | f3 |
+----+----+------+
| 1 | 1 | NULL |
| 1 | 2 | NULL |
+----+----+------+
2 rows in set (0.00 sec)
普通索引
普通索引是可以重复的
创建方式如下:
法儿一:
create table index_test(id int,name char(5),index(name));
法儿二:
alter table index_test add index(id);
我们来看下建表语句
MariaDB [jason]> show create table index_test \G;
*************************** 1. row ***************************
Table: index_test
Create Table: CREATE TABLE `index_test` (
`id` int(11) DEFAULT NULL,
`name` char(5) DEFAULT NULL,
KEY `name` (`name`),
KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
1 row in set (0.01 sec)
怎么就冒出来个 “KEY”,KEY 就是我们刚才建的index ,key 和index 是同义词,不过我一般习惯用index
全文索引
全文索引是对表中的大文本进行索引的,包括 char,varchar,text,关于全文索引的一些介绍可以看
创建全文索引的方法如下
法儿一:
MariaDB [jason]> create table ft_test(f1 char(200),f2 varchar(200),f3 text,f4 int,fulltext(f1));
法儿二:
alter table ft_test add fulltext(f2,f3);
现在我们往表里插入两条数据玩玩儿
insert into ft_test(f1,f2,f3) values
('Brian and his two friends are hanging','out at a bar','They are talking about life'),
('sports and other','guy things when the conversation','finally gets around to to their marriages'),
('His first friend says','You know what','under the bed and it was not mine');
看看fulltext 的使用方法
MariaDB [jason]> select f1 from ft_test where match(f1) against('two');
+---------------------------------------+
| f1 |
+---------------------------------------+
| Brian and his two friends are hanging |
+---------------------------------------+
我们来看看match against 是个啥玩意儿
MariaDB [jason]> select f1 ,match(f1) against('two') as aa from ft_test;
+---------------------------------------+---------------------+
| f1 | aa |
+---------------------------------------+---------------------+
| Brian and his two friends are hanging | 0.22764469683170319 |
| sports and other | 0 |
| His first friend says | 0 |
+---------------------------------------+---------------------+
他是一个关联系数,where 条件只过滤系数大于0的记录
噪声单词
尝试下面的语句
MariaDB [jason]> select f1 from ft_test where match(f1) against('are');
Empty set (0.00 sec)
有什么异样?are 明明在f1 中是存在的,但是结果却是empty,innodb 维持了一个stopword 表,stopword
默认是不被索引的,所以用are 做索引会被忽略
唯一索引
唯一索引与普通索引类似,区别是唯一索引不可以重复
创建唯一索引的方法
法儿一:
create table uq_test(f1 char(20),f2 char(20),f3 int,unique(f1));
法儿二:
alter table uq_test add unique(f2);
部分索引
对于char,varchar,blob,text 等字符串类型的值,其存储的内容可能很长,如果对整个字段做索引
则索引回很大,且效率很低,这时可以采用部分索引,也叫前缀索引,看例子
建表
create table part_index(city char(10));
插入数据
insert into part_index values('hebei'),('beijing'),('tianjin'),('henan'),('anhui');
到底选择前缀的几个字符效果最佳呢?可以采用下面的方法计算
MariaDB [jason]> select count(distinct(left(city,1)))/count(*) as c1,
-> count(distinct(left(city,2)))/count(*) as c2,
-> count(distinct(left(city,3)))/count(*) as c3,
-> count(distinct(left(city,4)))/count(*) as c4,
-> count(distinct(left(city,5)))/count(*) as c5,
-> count(distinct(city))/count(*) as c6
-> from part_index;
+--------+--------+--------+--------+--------+--------+
| c1 | c2 | c3 | c4 | c5 | c6 |
+--------+--------+--------+--------+--------+--------+
| 0.8000 | 0.8000 | 1.0000 | 1.0000 | 1.0000 | 1.0000 |
+--------+--------+--------+--------+--------+--------+
可以看到当选用前3个字符的时候就和使用全部字符比例相当了,所以可以选用前3个字符做前缀索引。
那么我们来给上面的表添加前缀索引
alter table part_index add index(city(3))
欢迎转载,不必注明出处