索引和查詢優化
爲何要索引?
想一想咱們上小學的時候是怎麼查字典的,比方查 理想的 「理」,首先在索引裏找到聲母 「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))