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,用它會索引失效
小試牛刀 |