索引的使用
索引太少返回結果很慢,可是索引太多,又會佔用空間。每次插入新記錄時,索引都會針對變化從新排序
何時使用索引
1.where 從句中用到的字段
select * from tb where f1 = 'xx' ,若是f1 進行了索引,那麼這條sql 語句的銷燬就會提升
2 max(),min()
select max(id) from tb
對id 索引很是有用,由於索引是按照順序排序的,因此直接返回最後一個值便可
3.當返回的內容是索引的一部分時
這種狀況沒必要掃描全表,只需查看索引便可
這種狀況是不行的:f1 char(20),index f1(10),select f1 from tb ,由於索引只有10個字符,返回的倒是20個
字符,必須掃描全表,掃描索引是不行的
4.order by
select * from tb order by f1,若 f1 是被索引的,則按照索引排序的順序返回便可
5.在鏈接條件處使用
select t1.c1,t1.c2,t2.c3
from t1 join t2
on t1.c4=t2.c5
where t1.c6=xx;
若是 c4 和 c5 加了索引,也能夠被使用到
6.不以% 開頭的like 語句vs
select * from tb where name like 'jas%'
name 列加了索引也會被使用到
可是這種狀況是不行的:select * from tb where name like '%jas%'
由於索引是按照第一個字符的字母順序排序的
建立索引的一些建議:
1.where 條件中的字段建立索引
2.被索引的字段內容重複率越低越好,主鍵是最好的索引,每一個id 只返回一條記錄,枚舉就比較差勁,比方
說 性別,查詢 性別‘男’,可能會返回近一半的記錄
3.使用前綴索引
4.不要建立太多的索引,太多的索引會拖慢插入和更新速度
最左原則
這個問題單純的口頭描述很難說清楚,直接看僞代碼
create table tb (f1 char(20), f2 char(20), f3 char(20), f4 char(20), index(f1,f2,f3))
對於上面的表咱們來進行下面幾個sql 查詢
1. select * from tb where f1='xx1' and f2 ='xx2' and f3='xx3'
2. select * from tb where f1='xx1' and f2 ='xx2'
3. select * from tb where f1='xx1'
4. select * from tb where f2 ='xx2' and f3='xx3'
5. select * from tb where f1='xx1' and f3='xx3'
上面的sql 中 1,2,3 的索引所有其做用
4中索引不會起做用
5中只有索引f1 起做用
也就是說複合索引使用的時候,必須是從最左側開始,且是連續的,這樣全部的索引纔會被使用到
explain
下面來講一個頗有用的東西,explain
先來建兩張表,存儲學生和老師信息,
create table student
(
stu_id int(3) zerofill,
name char(10),
majar char(10),
teacher_id int
);
create table teacher
(
teacher_id int,
name char(10)
);
insert into student values
(1,'麗麗','chemistry',1),
(2,'麗娟','english',2),
(3,'芳麗','儒學',3),
(4,'光頭強','佛學',1),
(5,'熊大','math',2),
(6,'熊二','地理',3),
(7,'陶峯','高分子',4),
(8,'波波','機電',1),
(9,'米老鼠','土木',2);
insert into teacher values
(1,'劉老師'),
(2,'王老師'),
(3,'李老師'),
(4,'柴老師');
趕忙來試試explain
MariaDB [jason]> explain select * from student where stu_id=1;
+------+-------------+---------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | student | ALL | NULL | NULL | NULL | NULL | 9 | Using where |
+------+-------------+---------+------+---------------+------+---------+------+------+-------------+
給stu_id 加上索引再來試一下
MariaDB [jason]> alter table student add index(stu_id);
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [jason]> explain select * from student where stu_id=1;
+------+-------------+---------+------+---------------+--------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+------+---------------+--------+---------+-------+------+-------+
| 1 | SIMPLE | student | ref | stu_id | stu_id | 5 | const | 1 | |
+------+-------------+---------+------+---------------+--------+---------+-------+------+-------+
有木有發現不同?下面咱們來解釋一下explain 各個字段含義
說實話,我對參考資料中的的解釋有些困惑,我想先本身造幾個例子看看
MariaDB [jason]>
show indexes from student ;
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| student | 1 |
stu_id | 1 | stu_id | A | 9 | NULL | NULL | YES | BTREE | | |
| student | 1 |
teacher_id | 1 | teacher_id | A | 9 | NULL | NULL | YES | BTREE | | |
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
MariaDB [jason]> drop index stu_id on student;
MariaDB [jason]> alter table student add
primary key(stu_id);
MariaDB [jason]> show indexes from teacher;
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| teacher | 1 | teacher_id | 1 | teacher_id | A | 1 | NULL | NULL | YES | BTREE | | |
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)
MariaDB [jason]> drop index teacher_id on teacher;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [jason]> show indexes from teacher;
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| teacher | 1 | teacher_id | 1 | teacher_id | A | 1 | NULL | NULL | YES | BTREE | | |
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)
MariaDB [jason]> drop index teacher_id on teacher;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [jason]> alter talbe teacher
add primary key(teacher_id);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'talbe teacher add primary key(teacher_id)' at line 1
MariaDB [jason]> alter table teacher add primary key(teacher_id);
咱們先把student表中的stu_id 和tercher表中的teacher_id 變成了主鍵
example1:
MariaDB [jason]> explain select * from student where stu_id = 1;
+------+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | student |
const | PRIMARY | PRIMARY | 4 | const | 1 | |
+------+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
example2:
MariaDB [jason]> explain select * from student where stu_id > 2;
+------+-------------+---------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+-------+---------------+---------+---------+------+------+-------------+
| 1 | SIMPLE | student |
range | PRIMARY | PRIMARY | 4 | NULL | 7 | Using where |
+------+-------------+---------+-------+---------------+---------+---------+------+------+-------------+
example3:
MariaDB [jason]> explain select * from student where teacher_id = 1;
+------+-------------+---------+------+---------------+------------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+------+---------------+------------+---------+-------+------+-------+
| 1 | SIMPLE | student |
ref | teacher_id | teacher_id | 5 | const | 3 | |
+------+-------------+---------+------+---------------+------------+---------+-------+------+-------+
example4:
MariaDB [jason]> explain select * from student where teacher_id>2;
+------+-------------+---------+-------+---------------+------------+---------+------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+-------+---------------+------------+---------+------+------+-----------------------+
| 1 | SIMPLE | student |
range | teacher_id | teacher_id | 5 | NULL | 3 | Using index condition |
+------+-------------+---------+-------+---------------+------------+---------+------+------+-----------------------+
example5:
ariaDB [jason]> explain select s.stu_id,s.name,s.majar,s.teacher_id,t.name
-> from student s join teacher t
-> on s.teacher_id = t.teacher_id;
+------+-------------+-------+------+---------------+------+---------+------+------+-------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------+------+---------+------+------+-------------------------------------------------+
| 1 | SIMPLE | t |
ALL | PRIMARY | NULL | NULL | NULL | 4 | |
| 1 | SIMPLE | s |
ALL | teacher_id | NULL | NULL | NULL | 9 | Using where; Using join buffer (flat, BNL join) |
+------+-------------+-------+------+---------------+------+---------+------+------+-------------------------------------------------+
example6:
MariaDB [jason]> explain select s.stu_id,s.name,s.majar,s.teacher_id,t.name
-> from student s left join teacher t
-> on s.teacher_id = t.teacher_id;
+------+-------------+-------+--------+---------------+---------+---------+--------------------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+--------+---------------+---------+---------+--------------------+------+-------+
| 1 | SIMPLE | s | ALL | NULL | NULL | NULL | NULL | 9 | |
| 1 | SIMPLE | t |
eq_ref | PRIMARY | PRIMARY | 4 | jason.s.teacher_id | 1 | |
+------+-------------+-------+--------+---------------+---------+---------+--------------------+------+-------+
example7:
MariaDB [jason]> explain select s.stu_id,s.name,s.majar,s.teacher_id,t.name
-> from student s left join teacher t
-> on s.teacher_id = t.teacher_id
-> where t.name is not null;
+------+-------------+-------+------+---------------+------+---------+------+------+-------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------+------+---------+------+------+-------------------------------------------------+
| 1 | SIMPLE | t | ALL | PRIMARY | NULL | NULL | NULL | 4 | Using where |
| 1 | SIMPLE | s | ALL | teacher_id | NULL | NULL | NULL | 9 | Using where; Using join buffer (flat, BNL join) |
+------+-------------+-------+------+---------------+------+---------+------+------+-------------------------------------------------+
example8:
MariaDB [jason]> explain select s.stu_id,s.name,s.majar,s.teacher_id,t.name
-> from student s right join teacher t
-> on s.teacher_id = t.teacher_id;
+------+-------------+-------+------+---------------+------------+---------+--------------------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------+------------+---------+--------------------+------+-------+
| 1 | SIMPLE | t | ALL | NULL | NULL | NULL | NULL | 4 | |
| 1 | SIMPLE | s
| ref | teacher_id | teacher_id | 4 | jason.t.teacher_id | 1 | |
+------+-------------+-------+------+---------------+------------+---------+--------------------+------+-------+
我嘗試過使用full outer join ,可是mysql 不支持外鏈接
example9:
MariaDB [jason]> explain select stu_id,teacher_id from student;
+------+-------------+---------+-------+---------------+------------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+-------+---------------+------------+---------+------+------+-------------+
| 1 | SIMPLE | student |
index | NULL | teacher_id | 4 | NULL | 9 | Using index |
+------+-------------+---------+-------+---------------+------------+---------+------+------+-------------+
example10:
MariaDB [jason]> explain select max(teacher_id) from student;
+------+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Select tables optimized away |
+------+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
example11:
MariaDB [jason]> explain select * from student order by teacher_id desc;
+------+-------------+---------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+------+---------------+------+---------+------+------+----------------+
| 1 | SIMPLE | student | ALL | NULL | NULL | NULL | NULL | 9 | Using filesort |
+------+-------------+---------+------+---------------+------+---------+------+------+----------------+
example12:
MariaDB [jason]> explain select * from student force index(teacher_id) order by teacher_id desc;
+------+-------------+---------+-------+---------------+------------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+-------+---------------+------------+---------+------+------+-------+
| 1 | SIMPLE | student |
index | NULL | teacher_id | 4 | NULL | 9 | |
+------+-------------+---------+-------+---------------+------------+---------+------+------+-------+
example13:
MariaDB [jason]> alter table student add index(name);
MariaDB [jason]> explain select * from student where name like '麗%';
+------+-------------+---------+-------+---------------+------+---------+------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+-------+---------------+------+---------+------+------+-----------------------+
| 1 | SIMPLE | student |
range | name | name | 41 | NULL | 2 | Using index condition |
+------+-------------+---------+-------+---------------+------+---------+------+------+-----------------------+
example14:
MariaDB [jason]> explain select * from student where teacher_id +5 < 7;
+------+-------------+---------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | student | ALL | NULL | NULL | NULL | NULL | 9 | Using where |
+------+-------------+---------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.01 sec)
MariaDB [jason]> explain select * from student where teacher_id < 2;
+------+-------------+---------+-------+---------------+------------+---------+------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+-------+---------------+------------+---------+------+------+-----------------------+
| 1 | SIMPLE | student |
range | teacher_id | teacher_id | 4 | NULL | 3 | Using index condition |
+------+-------------+---------+-------+---------------+------------+---------+------+------+-----------------------+
1 row in set (0.00 sec)
example 15:
MariaDB [jason]> explain select s.stu_id,s.name,s.majar,s.teacher_id,t.name
-> from student s left join teacher t
-> on s.teacher_id = t.teacher_id
-> where t.teacher_id is null;
+------+-------------+-------+--------+---------------+---------+---------+--------------------+------+-------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+--------+---------------+---------+---------+--------------------+------+-------------------------+
| 1 | SIMPLE | s | ALL | NULL | NULL | NULL | NULL | 9 | |
| 1 | SIMPLE | t | eq_ref | PRIMARY | PRIMARY | 4 | jason.s.teacher_id | 1 | Using where; Not exists |
+------+-------------+-------+--------+---------------+---------+---------+--------------------+------+-------------------------+
2 rows in set (0.00 sec)
example 16:
MariaDB [jason]> explain select *
-> from t2 left join t1 on t2.f2=t1.f1
-> left join t3 on t3.f3=t2.f2
-> left join t4 on t4.f4=t3.f3
-> where t1.f1=1;
+------+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
| 1 | SIMPLE | t2 | const | PRIMARY | PRIMARY | 4 | const | 1 | Using index |
| 1 | SIMPLE | t1 | const | PRIMARY | PRIMARY | 4 | const | 1 | Using index |
| 1 | SIMPLE | t3 | const | PRIMARY | PRIMARY | 4 | const | 1 | Using index |
| 1 | SIMPLE | t4 | const | PRIMARY | PRIMARY | 4 | const | 1 | Using index |
+------+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
這裏沒有列出最左原則的例子,你們能夠本身個兒試一下,
analyze table
mysql 在執行時select 或join 時會使用索引的分佈信息來決定表的關聯順序、或使用那個索引,
analyze table tablename 就能夠分析並存儲索引的分佈信息,
MariaDB [jason]> analyze table student;
+---------------+---------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------------+---------+----------+----------+
| jason.student | analyze | status | OK |
+---------------+---------+----------+----------+
能夠經過 show index from tb_name 來查看索引的狀況
MariaDB [jason]> show index from student;
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| student | 0 | PRIMARY | 1 | stu_id | A | 10 | NULL | NULL | | BTREE | | |
| student | 1 | teacher_id | 1 | teacher_id | A | 10 | NULL | NULL | | BTREE | | |
| student | 1 | name | 1 | name | A | 10 | NULL | NULL | YES | BTREE | | |
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
重點解釋一下Cardinality
1. 列值表明的是此列中存儲的惟一值的個數(若是此列爲primary key 則值爲記錄的行數)
2. 列值只是個估計值,並不許確。
3. 列值不會自動更新,須要經過Analyze table來更新一張表或者mysqlcheck -Aa來進行更新整個數據庫。
4. 列值的大小影響Join時是否選用這個Index的判斷。
5. 建立Index時,MyISAM的表Cardinality的值爲null,InnoDB的表Cardinality的值大概爲行數。
6. MyISAM與InnoDB對於Cardinality的計算方式不一樣。
optimize
若是對錶進行了大量的刪除和更新操做,那麼表中就會留下縫隙,optimize table tb_name 能夠將縫隙刪除
將分割的記錄鏈接在一塊兒
MariaDB [jason]> optimize table student;
+---------------+----------+----------+-------------------------------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+---------------+----------+----------+-------------------------------------------------------------------+
| jason.student | optimize | note | Table does not support optimize, doing recreate + analyze instead |
| jason.student | optimize | status | OK |
+---------------+----------+----------+-------------------------------------------------------------------+
什麼鬼?原來是innodb 不支持optimize, 百度找到了方法
ALTER TABLE table.name ENGINE='InnoDB';
This will create a copy of the original table, and drop the original table, and replace to the original place.
Although this is safe, but I suggest you do backup and test first before doing this.