1. 程式人生 > >Mysql(二)--索引使用及優化

Mysql(二)--索引使用及優化

索引簡介

索引是什麼?索引是類似於書的目錄這樣的結構嗎?可以這麼講,但是到底索引是什麼,索引是排好序的快速查詢資料結構。索引最常用的型別是BTree型別,這種型別同樣可以體現出索引是排好序的快速查詢資料結構,沒有索引之前要想查詢符合某個條件的資料就需要全表掃描,這樣效能是非常低的,當有了BTree型別,可以按照一定的規則進行查詢,如下是BTree結構:
這裡寫圖片描述

索引分類

1. 單值索引
一個索引只包含單個列,一個表可以包含多個單值索引。例如我們想查name欄位等於特定值,
表結構:

select * from user where name='張三01';
+----+----------+
| id | name | +----+----------+ | 1 | 張三01 | +----+----------+

在沒有加索引的情況下:

explain select * from user where name='張三01';
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | user | ALL | NULL | NULL | NULL | NULL | 1 | Using where | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+

加索引:

create index idx_user_name on user(name);

加完索引之後:

 explain select * from user where name='張三01';
+----+-------------+-------+------+---------------+---------------+---------+-------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+---------------+---------+-------+------+-----------------------+ | 1 | SIMPLE | user | ref | idx_user_name | idx_user_name | 63 | const | 1 | Using index condition | +----+-------------+-------+------+---------------+---------------+---------+-------+------+-----------------------+

單值索引的建立方式有三種:

create index index_name on table_name(column)
alter table table_name add index index_name(column)
create table table_name(column1,column2...PRIMARY KEY (`id`),INDEX index_name (column)

2. 複合索引
一個索引包含多個列
如下表結構:

select * from article;
+----+-----------+-------------+-------+----------+-------+---------+
| id | author_id | category_id | views | comments | title | content |
+----+-----------+-------------+-------+----------+-------+---------+
|  1 |         1 |           1 |     1 |        1 | 1     | 1       |
|  2 |         2 |           2 |     2 |        2 | 2     | 2       |
|  3 |         1 |           1 |     3 |        3 | 3     | 3       |
+----+-----------+-------------+-------+----------+-------+---------+

建立複合索引:

create index idx_article_cv on article(category_id,views);

3. 唯一索引
索引值必須唯一,允許有空值

create unique index idx_test on article(content);

4. 全文索引
FULLTEXT索引僅可用於 MyISAM 表;他們可以從CHAR、VARCHAR或TEXT列中作為CREATE TABLE語句的一部分被建立,或是隨後使用ALTER TABLE 或CREATE INDEX被新增,索引也是佔用記憶體空間的,所以在資料量特別大的表上不要使用全文索引,因為在更新資料庫資料的時候,會同時更新索引表,因此,效能會特別慢。

索引法則及優化
  • 最左字首原則,不跳過索引中的列
    在name,age,pos三個欄位上建立索引:
create index idx_staffs_nameAgePos on staffs;

舉一個不遵從最左字首的例子,where之後的條件是age和pos,沒有索引的最左列name,因此是不遵從最左字首的,導致索引失效,可以看到下圖中的key為NULL,沒有用到索引:
這裡寫圖片描述
不能跳過索引中的列,如果跳過了,如果最左字首列還在,則會使用部分索引,如果最左字首列沒有,則直接導致索引失效,例如,我們只使用最左字首查,發現索引是使用了,key_len是74:
這裡寫圖片描述
跳過一個索引列,跳過中間的age列,如下,發現key_len依舊是74,說明是用到了部分索引:
這裡寫圖片描述
2. 不在索引列上做任何操作,否則會導致索引失效而轉向全表掃描
這裡寫圖片描述
3. 儲存引擎不能使用索引中範圍條件右邊的列,範圍之後全失效,將導致name和age被用到了,pos失效

select * from staffs where name='July' and age >25 and pos='manager';

4.儘量用覆蓋索引(覆蓋索引:查詢的列和所建立的索引的列個數相同,欄位相同),減少select * 的使用
5. 儘量不使用!=或<>,如果使用,則無法使用索引,會導致全表掃描

explain select * from article where category_id != '1';
+----+-------------+---------+------+----------------+------+---------+------+------+-------------+
| id | select_type | table   | type | possible_keys  | key  | key_len | ref  | rows | Extra       |
+----+-------------+---------+------+----------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | article | ALL  | idx_article_cv | NULL | NULL    | NULL |    3 | Using where |
+----+-------------+---------+------+----------------+------+---------+------+------+-------------+

6.is null, is not null無法使用索引

explain select * from article where category_id is null;
+----+-------------+-------+------+---------------+------+---------+------+------+------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra            |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | Impossible WHERE |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------+

7.like查詢,%要在最右側(‘字串%’),否則會進行全表掃描,那麼如何解決like查詢時’%字串%’時索引不被使用的方法(可以使用覆蓋索引)
8. 字串型別不加單引號會導致索引失效,因為mysql會自己做型別轉換,相當於在索引列上進行了操作
如下例子中category_id是一個字串,但是由於沒有加單引號,就會降低效能

select * from article where category_id =1;

9.少用or,用它會索引失效

小試牛刀

這裡寫圖片描述