索引和查询优化
为何要索引?
想一想咱们上小学的时候是怎么查字典的,比方查 理想的 “理”,首先在索引里找到声母 “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))