《一塊兒學mysql》4

索引的使用
 
索引太少返回結果很慢,可是索引太多,又會佔用空間。每次插入新記錄時,索引都會針對變化從新排序
 
何時使用索引
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 |
+------+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
 
 
這裏沒有列出最左原則的例子,你們能夠本身個兒試一下,
 
關於expalin 各列的解釋能夠看 這裏
 
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.
相關文章
相關標籤/搜索