95%的人都不知道 MySQL還有索引管理與執(zhí)行計(jì)劃

1.1 索引的介紹

索引是對(duì)數(shù)據(jù)庫表中一列或多列的值進(jìn)行排序的一種結(jié)構(gòu)僚匆,使用索引可快速訪問數(shù)據(jù)庫表中的特定信息。如果想按特定職員的姓來查找他或她,則與在表中搜索所有的行相比盯孙,索引有助于更快地獲取信息。

索引的一個(gè)主要目的就是加快檢索表中數(shù)據(jù)的方法祟滴,亦即能協(xié)助信息搜索者盡快的找到符合限制條件的記錄ID的輔助數(shù)據(jù)結(jié)構(gòu)振惰。

file

1.1.1 唯一索引

唯一索引是不允許其中任何兩行具有相同索引值的索引。當(dāng)現(xiàn)有數(shù)據(jù)中存在重復(fù)的鍵值時(shí)垄懂,大多數(shù)數(shù)據(jù)庫不允許將新創(chuàng)建的唯一索引與表一起保存骑晶。數(shù)據(jù)庫還可能防止添加將在表中創(chuàng)建重復(fù)鍵值的新數(shù)據(jù)。

例如草慧,如果在employee表中職員的姓(lname)上創(chuàng)建了唯一索引桶蛔,則任何兩個(gè)員工都不能同姓。

1.1.2 主鍵索引

數(shù)據(jù)庫表經(jīng)常有一列或多列組合漫谷,其值唯一標(biāo)識(shí)表中的每一行仔雷。該列稱為表的主鍵。在數(shù)據(jù)庫關(guān)系圖中為表定義主鍵將自動(dòng)創(chuàng)建主鍵索引,主鍵索引是唯一索引的特定類型碟婆。

該索引要求主鍵中的每個(gè)值都唯一电抚。當(dāng)在查詢中使用主鍵索引時(shí),它還允許對(duì)數(shù)據(jù)的快速訪問脑融。

1.1.3 聚集索引

在聚集索引中喻频,表中行的物理順序與鍵值的邏輯(索引)順序相同。一個(gè)表只能包含一個(gè)聚集索引肘迎。如果某索引不是聚集索引甥温,則表中行的物理順序與鍵值的邏輯順序不匹配。與非聚集索引相比妓布,聚集索引通常提供更快的數(shù)據(jù)訪問速度姻蚓。

聚集索引和非聚集索引的區(qū)別,如字典默認(rèn)按字母順序排序匣沼,讀者如知道某個(gè)字的讀音可根據(jù)字母順序快速定位狰挡。因此聚集索引和表的內(nèi)容是在一起的。如讀者需查詢某個(gè)生僻字释涛,則需按字典前面的索引加叁,舉例按偏旁進(jìn)行定位,找到該字對(duì)應(yīng)的頁數(shù)唇撬,再打開對(duì)應(yīng)頁數(shù)找到該字它匕。

這種通過兩個(gè)地方而查詢到某個(gè)字的方式就如非聚集索引。

1.1.4 索引列

可以基于數(shù)據(jù)庫表中的單列或多列創(chuàng)建索引窖认。多列索引可以區(qū)分其中一列可能有相同值的行豫柬。如果經(jīng)常同時(shí)搜索兩列或多列或按兩列或多列排序時(shí),索引也很有幫助扑浸。

例如烧给,如果經(jīng)常在同一查詢中為姓和名兩列設(shè)置判據(jù),那么在這兩列上創(chuàng)建多列索引將很有意義喝噪。

檢查查詢的WHERE和JOIN子句础嫡。在任一子句中包括的每一列都是索引可以選擇的對(duì)象。對(duì)新索引進(jìn)行試驗(yàn)以檢查它對(duì)運(yùn)行查詢性能的影響酝惧〕巯牛考慮已在表上創(chuàng)建的索引數(shù)量。最好避免在單個(gè)表上有很多索引系奉。

檢查已在表上創(chuàng)建的索引的定義。最好避免包含共享列的重疊索引姑廉。

檢查某列中唯一數(shù)據(jù)值的數(shù)量缺亮,并將該數(shù)量與表中的行數(shù)進(jìn)行比較。比較的結(jié)果就是該列的可選擇性,這有助于確定該列是否適合建立索引萌踱,如果適合葵礼,確定索引的類型。

1.1.5 B樹算法

file

  B樹的搜索并鸵,從根結(jié)點(diǎn)開始鸳粉,如果查詢的關(guān)鍵字與結(jié)點(diǎn)的關(guān)鍵字相等,那么就命中园担;否則届谈,如果查詢關(guān)鍵字比結(jié)點(diǎn)關(guān)鍵字小,就進(jìn)入左邊弯汰;如果比結(jié)點(diǎn)關(guān)鍵字大艰山,就進(jìn)入右邊;如果左邊或右邊的指針為空咏闪,則報(bào)告找不到相應(yīng)的關(guān)鍵曙搬。

如果B樹的所有非葉子結(jié)點(diǎn)的左右子樹的結(jié)點(diǎn)數(shù)目均保持差不多(平衡),那么B樹的搜索性能逼近二分查找鸽嫂;但它比連續(xù)內(nèi)存空間的二分查找的優(yōu)點(diǎn)是纵装,改變B樹結(jié)構(gòu)(插入與刪除結(jié)點(diǎn))不需要移動(dòng)大段的內(nèi)存數(shù)據(jù),甚至通常是常數(shù)開銷据某。

1.1.6 B+樹算法

B+樹是B-樹的變體橡娄,也是一種多路搜索樹:

       1.其定義基本與B-樹同,除了:
       2.非葉子結(jié)點(diǎn)的子樹指針與關(guān)鍵字個(gè)數(shù)相同哗脖;
       3.非葉子結(jié)點(diǎn)的子樹指針P[i]瀑踢,指向關(guān)鍵字值屬于[K[i], K[i+1])的子樹(B-樹是開區(qū)間);
       5.為所有葉子結(jié)點(diǎn)增加一個(gè)鏈指針才避;
       6.所有關(guān)鍵字都在葉子結(jié)點(diǎn)出現(xiàn)橱夭;
       如:(M=3)
file

   B+的搜索與B-樹也基本相同,區(qū)別是B+樹只有達(dá)到葉子結(jié)點(diǎn)才命中(B-樹可以在非葉子結(jié)點(diǎn)命中)桑逝,其性能也等價(jià)于在關(guān)鍵字全集做一次二分查找棘劣;

? B+的特性:

       1.所有關(guān)鍵字都出現(xiàn)在葉子結(jié)點(diǎn)的鏈表中(稠密索引),且鏈表中的關(guān)鍵字恰好是有序的楞遏;
       2.不可能在非葉子結(jié)點(diǎn)命中茬暇;
       3.非葉子結(jié)點(diǎn)相當(dāng)于是葉子結(jié)點(diǎn)的索引(稀疏索引),葉子結(jié)點(diǎn)相當(dāng)于是存儲(chǔ)(關(guān)鍵字)數(shù)據(jù)的數(shù)據(jù)層寡喝;
       4.更適合文件索引系統(tǒng)糙俗;

1.1.7 HASH:HASH算法

哈希索引只有Memory, NDB兩種引擎支持,Memory引擎默認(rèn)支持哈希索引预鬓,如果多個(gè)hash值相同巧骚,出現(xiàn)哈希碰撞,那么索引以鏈表方式存儲(chǔ)。

但是劈彪,Memory引擎表只對(duì)能夠適合機(jī)器的內(nèi)存切實(shí)有限的數(shù)據(jù)集竣蹦。

要使InnoDB或MyISAM支持哈希索引,可以通過偽哈希索引來實(shí)現(xiàn)沧奴,叫自適應(yīng)哈希索引痘括。

主要通過增加一個(gè)字段,存儲(chǔ)hash值滔吠,將hash值建立索引纲菌,在插入和更新的時(shí)候,建立觸發(fā)器屠凶,自動(dòng)添加計(jì)算后的hash到表里驰后。

1.1.8 其他的索引

FULLTEXT:全文索引
RTREE:R樹索引

1.2 MySQL索引管理

索引建立在表的列上(字段)的。

在where后面的列建立索引才會(huì)加快查詢速度矗愧。

pages<---索引(屬性)<----查數(shù)據(jù)灶芝。

添加索引的方法:

alter table test add index index_name(name);
create index index_name on test(name);

語法格式:

alter table 表 add index 索引名稱(name);

1.2.1 創(chuàng)建普通索引

創(chuàng)建普通索引方法一:

mysql> ALTER TABLE PLAYERS ADD INDEX   name_idx(NAME);
mysql> desc PLAYERS;
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| NAME       | char(15)    | NO   | MUL | NULL    |       |

創(chuàng)建普通索引方法二:

mysql> ALTER TABLE PLAYERS ADD INDEX   name_idx(NAME);
mysql> desc PLAYERS;
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| NAME       | char(15)    | NO   | MUL | NULL    |       |

1.2.2 刪除索引

alter table PLAYERS delete INDEX  name_idx;
mysql> show index from  PLAYERS\G
*************************** 1. row ***************************
        Table: PLAYERS
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: PLAYERNO
    Collation: A
  Cardinality: 14
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment:

1.3 MySQL中的約束索引

主鍵索引

只能有一個(gè)主鍵。

主鍵索引:列的內(nèi)容是唯一值,例如學(xué)號(hào).

表創(chuàng)建的時(shí)候至少要有一個(gè)主鍵索引唉韭,最好和業(yè)務(wù)無關(guān)夜涕。

普通索引

加快查詢速度,工作中優(yōu)化數(shù)據(jù)庫的關(guān)鍵属愤。

在合適的列上建立索引女器,讓數(shù)據(jù)查詢更高效。

create index index_name on test(name);
alter table test add index index_name(name);

用了索引住诸,查一堆內(nèi)容驾胆。

在where條件關(guān)鍵字后面的列建立索引才會(huì)加快查詢速度.

select id,name from test where state=1 order by id group by name;

唯一索引

內(nèi)容唯一,但不是主鍵贱呐。

create unique index index_name on test(name);

1.3.1 創(chuàng)建主鍵索引

建立表時(shí)

CREATE TABLE `test` (
`id` int(4) NOT NULL AUTO_INCREMENT,
`name` char(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=UTF8;

建立表后增加

CREATE TABLE `test` (
`id` int(4) NOT NULL,
`name` char(20) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=UTF8;

增加自增主鍵

alter table test change id id int(4) primary key 
not null auto_increment;

1.3.2 使用字段前綴創(chuàng)建索引及聯(lián)合索引

前綴索引:根據(jù)字段的前N個(gè)字符建立索引

create index index_name on test(name(8));

聯(lián)合索引:多個(gè)字段建立一個(gè)索引丧诺。

where a女生 and b身高165 and c身材好
index(a,b,c)

特點(diǎn):前綴生效特性。

a,ab,abc 可以走索引奄薇。
b ac bc c 不走索引(5.6之后 ac 可以走主鍵索引)驳阎。

原則:把最常用來作為條件查詢的列放在前面。

*示例:*

創(chuàng)建表

 create table people (id int not null auto_increment ,name char(20),sr(20),sex int ,age int, primary key (id));

創(chuàng)建聯(lián)合索引

mysql> alter table people  add key name_sex_idx(name,sex)
    -> ;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

查看索引的類型

mysql> desc people;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| id    | int(11)  | NO   | PRI | NULL    | auto_increment |
| name  | char(20) | YES  | MUL | NULL    |                |
| sex   | int(11)  | YES  |     | NULL    |                |
| age   | int(11)  | YES  |     | NULL    |                |
+-------+----------+------+-----+---------+----------------+

建立唯一鍵索引

mysql> alter table people add unique key age_uidx(age);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

查看數(shù)據(jù)表

mysql> desc people;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| id    | int(11)  | NO   | PRI | NULL    | auto_increment |
| name  | char(20) | YES  | MUL | NULL    |                |
| sex   | int(11)  | YES  |     | NULL    |                |
| age   | int(11)  | YES  | UNI | NULL    |                |
+-------+----------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

聯(lián)合主鍵是聯(lián)合索引的特殊形式

PRIMARY KEY (`Host`,`User`)
alter table test add sex char(4) not null;
create index ind_name_sex on test(name,sex);

前綴加聯(lián)合索引

create index index_name on test(name(8),sex(2));

1.4 SQL語句優(yōu)化

1.4.1 企業(yè)SQL優(yōu)化思路

1馁蒂、把一個(gè)大的不使用索引的SQL語句按照功能進(jìn)行拆分

2呵晚、長的SQL語句無法使用索引,能不能變成2條短的SQL語句讓它分別使用上索引沫屡。

3饵隙、對(duì)SQL語句功能的拆分和修改

4、減少“爛”SQL由運(yùn)維(DBA)和開發(fā)交流(確認(rèn))沮脖,共同確定如何改癞季,最終由DBA執(zhí)行

5劫瞳、制定開發(fā)流程

1.4.2 不適合走索引的場景

1、唯一值少的列上不適合建立索引或者建立索引效率低绷柒。例如:性別列

2、小表可以不建立索引涮因,100條記錄废睦。

3、對(duì)于數(shù)據(jù)倉庫违诗,大量全表掃描的情況驱负,建索引反而會(huì)慢

1.4.3 查看表的唯一值數(shù)量

select count(distinct user) from mysql.user;
select count(distinct user,host) from mysql.user;

1.4.4 建立索引流程

1省有、找到慢SQL。

show processlist;

記錄慢查詢?nèi)罩尽?/p>

2购披、explain select句,條件列多。

3肩榕、查看表的唯一值數(shù)量:

select count(distinct user) from mysql.user;
select count(distinct user,host) from mysql.user;

條件列多刚陡。可以考慮建立聯(lián)合索引株汉。

4筐乳、建立索引(流量低谷)

force index

5、拆開語句(和開發(fā))乔妈。

6蝙云、like '%%'不用mysql

7、進(jìn)行判斷重復(fù)的行數(shù)

查看行數(shù):

mysql> select count(*) from city;
+----------+
| count(*) |
+----------+
|     4079 |
+----------+
1 row in set (0.00 sec)

查看去重后的行數(shù):

mysql> select count(distinct countrycode) from city;
+-----------------------------+
| count(distinct countrycode) |
+-----------------------------+
|                         232 |
+-----------------------------+
1 row in set (0.00 sec)

1.5 用explain查看SQL的執(zhí)行計(jì)劃

在工作中路召,我們用于捕捉性能問題最常用的就是打開慢查詢勃刨,定位執(zhí)行效率差的SQL,那么當(dāng)我們定位到一個(gè)SQL以后還不算完事股淡,我們還需要知道該SQL的執(zhí)行計(jì)劃身隐,比如是全表掃描,還是索引掃描揣非,這些都需要通過EXPLAIN去完成抡医。

EXPLAIN命令是查看優(yōu)化器如何決定執(zhí)行查詢的主要方法≡缇矗可以幫助我們深入了解MySQL的基于開銷的優(yōu)化器忌傻,還可以獲得很多可能被優(yōu)化器考慮到的訪問策略的細(xì)節(jié),以及當(dāng)運(yùn)行SQL語句時(shí)哪種策略預(yù)計(jì)會(huì)被優(yōu)化器采用搞监。

需要注意的是水孩,生成的QEP并不確定,它可能會(huì)根據(jù)很多因素發(fā)生改變琐驴。MySQL不會(huì)將一個(gè)QEP和某個(gè)給定查詢綁定俘种,QEP將由SQL語句每次執(zhí)行時(shí)的實(shí)際情況確定秤标,即便使用存儲(chǔ)過程也是如此。盡管在存儲(chǔ)過程中SQL語句都是預(yù)先解析過的宙刘,但QEP仍然會(huì)在每次調(diào)用存儲(chǔ)過程的時(shí)候才被確定苍姜。

1.5.1 查看 select 語句的執(zhí)行過程

mysql> explain select id,name from test where name='clsn';
+----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key      | key_len | ref   | rows | Extra       |
+----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+
|  1 | SIMPLE      | test  | ref  | name_idx      | name_idx | 24      | const |    1 | Using where |
+----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+
1 row in set (0.00 sec)

SQL_NO_CACHE的作用是禁止緩存查詢結(jié)果。

使用where****條件查找

mysql> explain select user,host from mysql.user where user='root' and host='127.0.0.1';
+----+-------------+-------+-------+---------------+---------+---------+-------------+------+-------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref         | rows | Extra       |
+----+-------------+-------+-------+---------------+---------+---------+-------------+------+-------------+
|  1 | SIMPLE      | user  | const | PRIMARY       | PRIMARY | 228     | const,const |    1 | Using index |
+----+-------------+-------+-------+---------------+---------+---------+-------------+------+-------------+
1 row in set (0.00 sec)

1.5.2 通過執(zhí)行計(jì)劃可以知道什么悬包?

mysql> explain select d1.age, t2.id from (select age,name from t1 where id in (1,2))d1, t2 where d1.age=t2.age group by d1.age, t2.id order by t2.id;
+----+-------------+------------+-------+---------------+---------+---------+--------+------+---------------------------------+
| id | select_type | table      | type  | possible_keys | key     | key_len | ref    | rows | Extra                           |
+----+-------------+------------+-------+---------------+---------+---------+--------+------+---------------------------------+
|  1 | PRIMARY     | <derived2> | ALL   | NULL          | NULL    | NULL    | NULL   |    2 | Using temporary; Using filesort |
|  1 | PRIMARY     | t2         | ref   | age           | age     | 5       | d1.age |    1 | Using where; Using index        |
|  2 | DERIVED     | t1         | range | PRIMARY       | PRIMARY | 4       | NULL   |    2 | Using where                     |
+----+-------------+------------+-------+---------------+---------+---------+--------+------+---------------------------------+
3 rows in set (0.00 sec)

1.5.3 MySQL執(zhí)行計(jì)劃調(diào)用方式

1.EXPLAIN SELECT ……
2.EXPLAIN EXTENDED SELECT ……
  將執(zhí)行計(jì)劃"反編譯"成SELECT語句衙猪,運(yùn)行SHOW WARNINGS 可得到被MySQL優(yōu)化器優(yōu)化后的查詢語句
3.EXPLAIN PARTITIONS SELECT ……
  用于分區(qū)表的EXPLAIN生成QEP的信息

1.5.4 執(zhí)行計(jì)劃包含的信息

+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+

1.5.5 id

包含一組數(shù)字,表示查詢中執(zhí)行select子句或操作表的順序

【示例一】id相同布近,執(zhí)行順序由上至下

mysql> explain select t2.* from t1, t2, t3 where t1.id=t2.id and t1.id=t3.id and t1.name='';
+----+-------------+-------+--------+---------------+---------+---------+------------+------+--------------------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref        | rows | Extra                    |
+----+-------------+-------+--------+---------------+---------+---------+------------+------+--------------------------+
|  1 | SIMPLE      | t1    | ref    | PRIMARY,name  | name    | 63      | const      |    1 | Using where; Using index |
|  1 | SIMPLE      | t2    | eq_ref | PRIMARY       | PRIMARY | 4       | test.t1.id |    1 |                          |
|  1 | SIMPLE      | t3    | eq_ref | PRIMARY       | PRIMARY | 4       | test.t1.id |    1 | Using index              |
+----+-------------+-------+--------+---------------+---------+---------+------------+------+--------------------------+
3 rows in set (0.00 sec)

【示例二】如果是子查詢垫释,id的序號(hào)會(huì)遞增,id值越大優(yōu)先級(jí)越高撑瞧,越先被執(zhí)行

mysql> explain select t2.* from t2 where id = (select id from t1 where id = (select t3.id from t3 where t3.name=''));
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                                               |
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
|  1 | PRIMARY     | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | Impossible WHERE noticed after reading const tables |
|  2 | SUBQUERY    | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | no matching row in const table                      |
|  3 | SUBQUERY    | t3    | ref  | name          | name | 63      |      |    1 | Using where; Using index                            |
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
3 rows in set (0.00 sec)

【示例三】id如果相同棵譬,可以認(rèn)為是一組,從上往下順序執(zhí)行预伺;在所有組中订咸,id值越大,優(yōu)先級(jí)越高扭屁,越先執(zhí)行

mysql> explain select t2.* from (select t3.id from t3 where t3.name='')s1, t2 where s1.id=t2.id;
+----+-------------+------------+--------+---------------+---------+---------+-------+------+--------------------------+
| id | select_type | table      | type   | possible_keys | key     | key_len | ref   | rows | Extra                    |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+--------------------------+
|  1 | PRIMARY     | <derived2> | system | NULL          | NULL    | NULL    | NULL  |    1 |                          |
|  1 | PRIMARY     | t2         | const  | PRIMARY       | PRIMARY | 4       | const |    1 |                          |
|  2 | DERIVED     | t3         | ref    | name          | name    | 63      |       |    1 | Using where; Using index |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+--------------------------+
3 rows in set (0.00 sec)

1.5.6 select_type

示查詢中每個(gè)select子句的類型(簡單OR復(fù)雜)
    a. SIMPLE:查詢中不包含子查詢或者UNION
    b. 查詢中若包含任何復(fù)雜的子部分算谈,最外層查詢則被標(biāo)記為:PRIMARY
    c. 在SELECT或WHERE列表中包含了子查詢,該子查詢被標(biāo)記為:SUBQUERY
    d. 在FROM列表中包含的子查詢被標(biāo)記為:DERIVED(衍生)用來表示包含在from子句中的子查詢的select料滥,mysql會(huì)遞歸執(zhí)行并將結(jié)果放到一個(gè)臨時(shí)表中然眼。服務(wù)器內(nèi)部稱為"派生表",因?yàn)樵撆R時(shí)表是從子查詢中派生出來的
    e. 若第二個(gè)SELECT出現(xiàn)在UNION之后葵腹,則被標(biāo)記為UNION高每;若UNION包含在FROM子句的子查詢中,外層SELECT將被標(biāo)記為:DERIVED
    f. 從UNION表獲取結(jié)果的SELECT被標(biāo)記為:UNION RESULT

說明:

SUBQUERY和UNION還可以被標(biāo)記為DEPENDENT和UNCACHEABLE践宴。
DEPENDENT意味著select依賴于外層查詢中發(fā)現(xiàn)的數(shù)據(jù)鲸匿。
UNCACHEABLE意味著select中的某些 特性阻止結(jié)果被緩存于一個(gè)item_cache中。

【示例】

mysql> explain select d1.name, ( select id from t3) d2 from (select id,name from t1 where name='')d1 union (select name,id from t2);
+----+--------------+------------+--------+---------------+------+---------+------+------+--------------------------+
| id | select_type  | table      | type   | possible_keys | key  | key_len | ref  | rows | Extra                    |
+----+--------------+------------+--------+---------------+------+---------+------+------+--------------------------+
|  1 | PRIMARY      | <derived3> | system | NULL          | NULL | NULL    | NULL |    0 | const row not found      |
|  3 | DERIVED      | t1         | ref    | name          | name | 63      |      |    1 | Using where; Using index |
|  2 | SUBQUERY     | t3         | index  | NULL          | age  | 5       | NULL |    6 | Using index              |
|  4 | UNION        | t2         | index  | NULL          | name | 63      | NULL |    4 | Using index              |
| NULL | UNION RESULT | <union1,4> | ALL    | NULL          | NULL | NULL    | NULL | NULL |                          |
+----+--------------+------------+--------+---------------+------+---------+------+------+--------------------------+
5 rows in set (0.00 sec)

內(nèi)容說明:

第一行:id列為1阻肩,表示第一個(gè)select带欢,select_type列的primary表 示該查詢?yōu)橥鈱硬樵儯瑃able列被標(biāo)記為<derived3>烤惊,表示查詢結(jié)果來自一個(gè)衍生表乔煞,其中3代表該查詢衍生自第三個(gè)select查詢,即id為3的select柒室。
第二行:id為3渡贾,表示該查詢的執(zhí)行次序?yàn)?( 4 => 3),是整個(gè)查詢中第三個(gè)select的一部分雄右。因查詢包含在from中空骚,所以為derived纺讲。
第三行:select列表中的子查詢,select_type為subquery囤屹,為整個(gè)查詢中的第二個(gè)select熬甚。
第四行:select_type為union,說明第四個(gè)select是union里的第二個(gè)select牺丙,最先執(zhí)行则涯。
第五行:代表從union的臨時(shí)表中讀取行的階段,table列的<union1,4>表示用第一個(gè)和第四個(gè)select的結(jié)果進(jìn)行union操作冲簿。

1.5.7 type

表示MySQL在表中找到所需行的方式,又稱“訪問類型”亿昏,常見類型如下:

ALL, index,  range, ref, eq_ref, const, system, NULL

從左到右峦剔,性能從最差到最好

【示例一】ALL:Full Table Scan, MySQL將遍歷全表以找到匹配的行

mysql> explain select * from t1 where email='';
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t1    | ALL  | NULL          | NULL | NULL    | NULL |    4 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

【示例二】index:Full Index Scan角钩,index與ALL區(qū)別為index類型只遍歷索引樹

mysql> explain select id from t1;
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t1    | index | NULL          | age  | 5       | NULL |    4 | Using index |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

【示例三】range:索引范圍掃描吝沫,對(duì)索引的掃描開始于某一點(diǎn),返回匹配值域的行递礼。

顯而易見的索引范圍掃描是帶有between或者where子句里帶有<, >查詢惨险。當(dāng)mysql使用索引去查找一系列值時(shí),例如IN()和OR列表脊髓,也會(huì)顯示range(范圍掃描),當(dāng)然性能上面是有差異的辫愉。

mysql> explain select * from t1 where id in (1,4);
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | t1    | range | PRIMARY       | PRIMARY | 4       | NULL |    2 | Using where |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.00 sec)
mysql> explain select * from t1 where id between 1 and 4;
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | t1    | range | PRIMARY       | PRIMARY | 4       | NULL |    3 | Using where |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.00 sec)
mysql> explain select * from t1 where id=1 or id=4;       
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | t1    | range | PRIMARY       | PRIMARY | 4       | NULL |    2 | Using where |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.01 sec)
mysql> explain select * from t1 where id > 1;      
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | t1    | range | PRIMARY       | PRIMARY | 4       | NULL |    3 | Using where |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.00 sec)

【示例四】ref:使用非唯一索引掃描或者唯一索引的前綴掃描,返回匹配某個(gè)單獨(dú)值的記錄行

mysql> explain select * from t1 where name='guo';
+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref   | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+
|  1 | SIMPLE      | t1    | ref  | name          | name | 63      | const |    1 | Using where |
+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+
1 row in set (0.00 sec)

【示例五】eq_ref:類似ref将硝,區(qū)別就在使用的索引是唯一索引恭朗,對(duì)于每個(gè)索引鍵值,表中只有一條記錄匹配依疼,簡單來說痰腮,就是多表連接中使用primary key或者 unique key作為關(guān)聯(lián)條件。

mysql> explain select t1.name from t1, t2 where t1.id=t2.id;
+----+-------------+-------+--------+---------------+---------+---------+------------+------+-------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref        | rows | Extra       |
+----+-------------+-------+--------+---------------+---------+---------+------------+------+-------------+
|  1 | SIMPLE      | t1    | index  | PRIMARY       | name    | 63      | NULL       |    4 | Using index |
|  1 | SIMPLE      | t2    | eq_ref | PRIMARY       | PRIMARY | 4       | test.t1.id |    1 | Using index |
+----+-------------+-------+--------+---------------+---------+---------+------------+------+-------------+
2 rows in set (0.00 sec)

【示例六】const律罢、system:當(dāng)MySQL對(duì)查詢某部分進(jìn)行優(yōu)化膀值,并轉(zhuǎn)換為一個(gè)常量時(shí),使用這些類型訪問误辑。

如將主鍵置于where列表中沧踏,MySQL就能將該查詢轉(zhuǎn)換為一個(gè)常量

mysql> explain select * from ( select * from t1 where id=1)b1;
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------+
| id | select_type | table      | type   | possible_keys | key     | key_len | ref  | rows | Extra |
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------+
|  1 | PRIMARY     | <derived2> | system | NULL          | NULL    | NULL    | NULL |    1 |       |
|  2 | DERIVED     | t1         | const  | PRIMARY       | PRIMARY | 4       |      |    1 |       |
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------+
2 rows in set (0.00 sec)

*注:*system是const類型的特例,當(dāng)查詢的表只有一行的情況下稀余,使用system

【示例七】NULL:MySQL在優(yōu)化過程中分解語句悦冀,執(zhí)行時(shí)甚至不用訪問表或索引, 例如從一個(gè)索引列里選取最小值可以通過單獨(dú)索引查找完成睛琳。

mysql> explain select * from t1 where id = (select min(id) from t2);
+----+-------------+-------+-------+---------------+---------+---------+-------+------+------------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref   | rows | Extra                        |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+------------------------------+
|  1 | PRIMARY     | t1    | const | PRIMARY       | PRIMARY | 4       | const |    1 |                              |
|  2 | SUBQUERY    | NULL  | NULL  | NULL          | NULL    | NULL    | NULL  | NULL | Select tables optimized away |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+------------------------------+
2 rows in set (0.00 sec)

1.5.8 possible_keys

指出MySQL能使用哪個(gè)索引在表中找到記錄盒蟆,查詢涉及到的字段上若存在索引踏烙,則該索引將被列出,但不一定被查詢使用

1.5.9 key

顯示MySQL在查詢中實(shí)際使用的索引历等,若沒有使用索引讨惩,顯示為NULL

【示例】

mysql> explain select id,age from t1;
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t1    | index | NULL          | age  | 5       | NULL |    4 | Using index |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

1.5.10 key_len

表示索引中使用的字節(jié)數(shù),可通過該列計(jì)算查詢中使用的索引的長度(key_len顯示的值為索引字段的最大可能長度寒屯,并非實(shí)際使用長度荐捻,即key_len是根據(jù)表定義計(jì)算而得,不是通過表內(nèi)檢索出的)寡夹。

1.5.11 ref

表示上述表的連接匹配條件处面,即哪些列或常量被用于查找索引列上的值。

1.5.12 rows

表示MySQL根據(jù)表統(tǒng)計(jì)信息及索引選用情況菩掏,估算的找到所需的記錄所需要讀取的行數(shù)魂角。

【示例】

mysql> explain select * from t1 , t2 where t1.id=t2.id and t2.name='atlas';
+----+-------------+-------+--------+---------------+---------+---------+------------+------+-------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref        | rows | Extra       |
+----+-------------+-------+--------+---------------+---------+---------+------------+------+-------------+
|  1 | SIMPLE      | t2    | ref    | PRIMARY,name  | name    | 63      | const      |    1 | Using where |
|  1 | SIMPLE      | t1    | eq_ref | PRIMARY       | PRIMARY | 4       | test.t2.id |    1 |             |
+----+-------------+-------+--------+---------------+---------+---------+------------+------+-------------+
2 rows in set (0.00 sec)

1.5.13 Extra

包含不適合在其他列中顯示但十分重要的額外信息

【示例一】Using index

該值表示相應(yīng)的select操作中使用了覆蓋索引(Covering Index)

mysql> explain select id from t1;
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t1    | index | NULL          | age  | 5       | NULL |    4 | Using index |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

覆蓋索引(Covering Index)

MySQL可以利用索引返回select列表中的字段,而不必根據(jù)索引再次讀取數(shù)據(jù)文件

包含所有滿足查詢需要的數(shù)據(jù)的索引稱為覆蓋索引(Covering Index)

注意:如果要使用覆蓋索引智绸,一定要注意select列表中只取出需要的列野揪,不可select *,因?yàn)槿绻麑⑺凶侄我黄鹱鏊饕龝?huì)導(dǎo)致索引文件過大瞧栗,查詢性能下降

【示例二】Using where

表示mysql服務(wù)器將在存儲(chǔ)引擎檢索行后再進(jìn)行過濾斯稳。許多where條件里涉及索引中的列,當(dāng)(并且如果)它讀取索引時(shí)迹恐,就能被存儲(chǔ)引擎檢驗(yàn)挣惰,因此不是所有帶where字句的查詢都會(huì)顯示"Using where"。

有時(shí)"Using where"的出現(xiàn)就是一個(gè)暗示:查詢可受益與不同的索引系草。

mysql> explain select id,name from t1 where id<4;
+----+-------------+-------+-------+---------------+------+---------+------+------+--------------------------+
| id | select_type | table | type  | possible_keys | key  | key_len | ref  | rows | Extra                    |
+----+-------------+-------+-------+---------------+------+---------+------+------+--------------------------+
|  1 | SIMPLE      | t1    | index | PRIMARY       | name | 63      | NULL |    4 | Using where; Using index |
+----+-------------+-------+-------+---------------+------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

【示例三】Using temporary

表示MySQL需要使用臨時(shí)表來存儲(chǔ)結(jié)果集通熄,常見于排序和分組查詢

這個(gè)值表示使用了內(nèi)部臨時(shí)(基于內(nèi)存的)表。一個(gè)查詢可能用到多個(gè)臨時(shí)表找都。有很多原因都會(huì)導(dǎo)致MySQL在執(zhí)行查詢期間創(chuàng)建臨時(shí)表唇辨。兩個(gè)常見的原因是在來自不同表的上使用了DISTINCT,或者使用了不同的ORDER BY和GROUP BY列∧艹埽可以強(qiáng)制指定一個(gè)臨時(shí)表使用基于磁盤的MyISAM存儲(chǔ)引擎赏枚。這樣做的原因主要有兩個(gè):

1)內(nèi)部臨時(shí)表占用的空間超過min(tmp_table_size,max_heap_table_size)系統(tǒng)變量的限制

2)使用了TEXT/BLOB 列

mysql> explain select id from t1 where id in (1,2) group by age,name;
+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                                        |
+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------+
|  1 | SIMPLE      | t1    | range | PRIMARY       | PRIMARY | 4       | NULL |    2 | Using where; Using temporary; Using filesort |
+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------+
1 row in set (0.00 sec)

【示例四】Using filesort

MySQL中無法利用索引完成的排序操作稱為“文件排序”

mysql> explain select id,age from t1 order by name; 
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
|  1 | SIMPLE      | t1    | ALL  | NULL          | NULL | NULL    | NULL |    4 | Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)
mysql> explain select id,age from t1 order by age; 
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t1    | index | NULL          | age  | 5       | NULL |    4 | Using index |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

【示例五】Using join buffer

該值強(qiáng)調(diào)了在獲取連接條件時(shí)沒有使用索引晓猛,并且需要連接緩沖區(qū)來存儲(chǔ)中間結(jié)果饿幅。

如果出現(xiàn)了這個(gè)值,那應(yīng)該注意戒职,根據(jù)查詢的具體情況可能需要添加索引來改進(jìn)能栗恩。

mysql> explain select t1.name from t1 inner join t2 on t1.name=t2.name;
+----+-------------+-------+-------+---------------+------+---------+--------------+------+--------------------------+
| id | select_type | table | type  | possible_keys | key  | key_len | ref          | rows | Extra                    |
+----+-------------+-------+-------+---------------+------+---------+--------------+------+--------------------------+
|  1 | SIMPLE      | t1    | index | name          | name | 63      | NULL         |    4 | Using index              |
|  1 | SIMPLE      | t2    | ref   | name          | name | 63      | test.t1.name |    2 | Using where; Using index |
+----+-------------+-------+-------+---------------+------+---------+--------------+------+--------------------------+
2 rows in set (0.00 sec)

刪除t1索引

mysql> alter table t1 drop key name;                                   
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

刪除t2索引

mysql> alter table t2 drop key name; 
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

經(jīng)常查找

mysql> explain select t1.name from t1 inner join t2 on t1.name=t2.name;
+----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                          |
+----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+
|  1 | SIMPLE      | t1    | ALL  | NULL          | NULL | NULL    | NULL |    4 |                                |
|  1 | SIMPLE      | t2    | ALL  | NULL          | NULL | NULL    | NULL |    4 | Using where; Using join buffer |
+----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+
2 rows in set (0.00 sec)

【示例六】Impossible where

這個(gè)值強(qiáng)調(diào)了where語句會(huì)導(dǎo)致沒有符合條件的行。

mysql> EXPLAIN SELECT * FROM t1 WHERE 1=2;
+----+-------------+-------+------+---------------+------+---------+------+------+------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra            |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | Impossible WHERE |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------+
1 row in set (0.00 sec)

【示例七】Select tables optimized away

這個(gè)值意味著僅通過使用索引洪燥,優(yōu)化器可能僅從聚合函數(shù)結(jié)果中返回一行.

mysql> explain select max(id) from t1;
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
| 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 |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
1 row in set (0.00 sec)

【示例八】Index merges

當(dāng)MySQL 決定要在一個(gè)給定的表上使用超過一個(gè)索引的時(shí)候磕秤,就會(huì)出現(xiàn)以下格式中的一個(gè)乳乌,詳細(xì)說明使用的索引以及合并的類型。

Using sort_union(...)
Using union(...)
Using intersect(...)

1.5.14 小結(jié)

EXPLAIN不會(huì)告訴你關(guān)于觸發(fā)器市咆、存儲(chǔ)過程的信息或用戶自定義函數(shù)對(duì)查詢的影響情況汉操。

EXPLAIN不考慮各種Cache。

EXPLAIN不能顯示MySQL在執(zhí)行查詢時(shí)所作的優(yōu)化工作蒙兰。

部分統(tǒng)計(jì)信息是估算的磷瘤,并非精確值。

EXPALIN只能解釋SELECT操作搜变,其他操作要重寫為SELECT后查看執(zhí)行計(jì)劃采缚。

1.6 mysql不走索引的原因

1.6.1 一些常見的原因

1) 沒有查詢條件,或者查詢條件沒有建立索引

2) 在查詢條件上沒有使用引導(dǎo)列

3) 查詢的數(shù)量是大表的大部分挠他,應(yīng)該是30%以上仰担。

4) 索引本身失效

5) 查詢條件使用函數(shù)在索引列上,或者對(duì)索引列進(jìn)行運(yùn)算绩社,運(yùn)算包括(+,-赂苗,*愉耙,/,! 等)

錯(cuò)誤的例子:select * from test where id-1=9; 正確的例子:select * from test where id=10;

6) 對(duì)小表查詢

7) 提示不使用索引

8) 統(tǒng)計(jì)數(shù)據(jù)不真實(shí)

9) CBO計(jì)算走索引花費(fèi)過大的情況拌滋。其實(shí)也包含了上面的情況朴沿,這里指的是表占有的block要比索引小。

10)隱式轉(zhuǎn)換導(dǎo)致索引失效.這一點(diǎn)應(yīng)當(dāng)引起重視.也是開發(fā)中經(jīng)常會(huì)犯的錯(cuò)誤.

由于表的字段tel_num定義為varchar2(20),但在查詢時(shí)把該字段作為number類型以where條件傳給數(shù)據(jù)庫,這樣會(huì)導(dǎo)致索引失效.

錯(cuò)誤的例子:select * from test where tel_nume=13333333333;

正確的例子:select * from test where tel_nume='13333333333';

11) 注意使用的特殊符號(hào)

1,<> ,!=

2,單獨(dú)的>,<,(有時(shí)會(huì)用到败砂,有時(shí)不會(huì))

12)like "%_" 百分號(hào)在前.

select * from t1 where name like 'linux培訓(xùn)%';

13) not in ,not exist.

14) in 盡量改成 union 赌渣。

15)當(dāng)變量采用的是times變量,而表的字段采用的是date變量時(shí).或相反情況昌犹。

16)B-tree索引is null不會(huì)走,is not null會(huì)走,位圖索引 is null,is not null 都會(huì)走 坚芜。

17)聯(lián)合索引 is not null 只要在建立的索引列(不分先后)都會(huì)走,

in null時(shí) 必須要和建立索引第一列一起使用,當(dāng)建立索引第一位置條件是is null 時(shí),其他建立索引的列可以是is null(但必須在所有列 都滿足is null的時(shí)候),或者=一個(gè)值;

當(dāng)建立索引的第一位置是=一個(gè)值時(shí),其他索引列可以是任何情況(包括is null =一個(gè)值),以上兩種情況索引都會(huì)走斜姥。其他情況不會(huì)走鸿竖。

1.6.2 需要注意的一些

1)    MyISAM 存儲(chǔ)引擎索引鍵長度總和不能超過1000 字節(jié);
2)    BLOB 和TEXT 類型的列只能創(chuàng)建前綴索引铸敏;
3)    MySQL 目前不支持函數(shù)索引缚忧;
4)    使用不等于(!= 或者<>)的時(shí)候MySQL 無法使用索引;
5)    過濾字段使用了函數(shù)運(yùn)算后(如abs(column))杈笔,MySQL 無法使用索引闪水;
6)    Join 語句中Join 條件字段類型不一致的時(shí)候MySQL 無法使用索引;
7)    使用LIKE 操作的時(shí)候如果條件以通配符開始( '%abc...')MySQL 無法使用索引蒙具;
8)    使用非等值查詢的時(shí)候MySQL 無法使用Hash 索引球榆;
9)    在我們使用索引的時(shí)候朽肥,需要注意上面的這些限制,尤其是要注意無法使用索引的情況芜果,因?yàn)檫@很容易讓我們因?yàn)槭韬龆斐蓸O大的性能隱患鞠呈。

1.7 數(shù)據(jù)庫索引的設(shè)計(jì)原則

為了使索引的使用效率更高,在創(chuàng)建索引時(shí)右钾,必須考慮在哪些字段上創(chuàng)建索引和創(chuàng)建什么類型的索引蚁吝。

1.7.1 那么索引設(shè)計(jì)原則又是怎樣的

1.選擇唯一性索引

唯一性索引的值是唯一的,可以更快速的通過該索引來確定某條記錄舀射。

例如窘茁,學(xué)生表中學(xué)號(hào)是具有唯一性的字段。為該字段建立唯一性索引可以很快的確定某個(gè)學(xué)生的信息脆烟。如果使用姓名的話山林,可能存在同名現(xiàn)象,從而降低查詢速度邢羔。

2.為經(jīng)常需要排序驼抹、分組和聯(lián)合操作的字段建立索引

經(jīng)常需要ORDER BY、GROUP BY拜鹤、DISTINCT和UNION等操作的字段框冀,排序操作會(huì)浪費(fèi)很多時(shí)間。

如果為其建立索引敏簿,可以有效地避免排序操作明也。

3.為常作為查詢條件的字段建立索引

如果某個(gè)字段經(jīng)常用來做查詢條件,那么該字段的查詢速度會(huì)影響整個(gè)表的查詢速度惯裕。因此温数,

為這樣的字段建立索引,可以提高整個(gè)表的查詢速度蜻势。

4.限制索引的數(shù)目

索引的數(shù)目不是越多越好撑刺。每個(gè)索引都需要占用磁盤空間,索引越多咙边,需要的磁盤空間就越大猜煮。修改表時(shí),對(duì)索引的重構(gòu)和更新很麻煩败许。越多的索引王带,會(huì)使更新表變得很浪費(fèi)時(shí)間。

5.盡量使用數(shù)據(jù)量少的索引

如果索引的值很長市殷,那么查詢的速度會(huì)受到影響愕撰。例如,對(duì)一個(gè)CHAR(100)類型的字段進(jìn)行全文檢索需要的時(shí)間肯定要比對(duì)CHAR(10)類型的字段需要的時(shí)間要多。

6.盡量使用前綴來索引

如果索引字段的值很長搞挣,最好使用值的前綴來索引带迟。例如,TEXT和BLOG類型的字段囱桨,進(jìn)行全文檢索會(huì)很浪費(fèi)時(shí)間仓犬。如果只檢索字段的前面的若干個(gè)字符,這樣可以提高檢索速度舍肠。

7.刪除不再使用或者很少使用的索引

表中的數(shù)據(jù)被大量更新搀继,或者數(shù)據(jù)的使用方式被改變后,原有的一些索引可能不再需要翠语。數(shù)據(jù)庫管理員應(yīng)當(dāng)定期找出這些索引叽躯,將它們刪除,從而減少索引對(duì)更新操作的影響肌括。

8.小表不應(yīng)建立索引

包含大量的列并且不需要搜索非空值的時(shí)候可以考慮不建索引

1.8 參考文獻(xiàn)

https://baike.baidu.com/item/數(shù)據(jù)庫索引/8751686?fr=aladdin
https://www.cnblogs.com/oldhorse/archive/2009/11/16/1604009.html
http://blog.csdn.net/manesking/archive/2007/02/09/1505979.aspx
http://blog.csdn.net/woshiqjs/article/details/24135495

簡書號(hào) 同 公號(hào)
回復(fù):【計(jì)算機(jī)】【設(shè)計(jì)模式】【面試】有驚喜哦

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末点骑,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子谍夭,更是在濱河造成了極大的恐慌黑滴,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件紧索,死亡現(xiàn)場離奇詭異跷跪,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)齐板,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來葛菇,“玉大人甘磨,你說我怎么就攤上這事∶型#” “怎么了济舆?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長莺债。 經(jīng)常有香客問我滋觉,道長,這世上最難降的妖魔是什么齐邦? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任椎侠,我火速辦了婚禮,結(jié)果婚禮上措拇,老公的妹妹穿的比我還像新娘我纪。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布浅悉。 她就那樣靜靜地躺著趟据,像睡著了一般。 火紅的嫁衣襯著肌膚如雪术健。 梳的紋絲不亂的頭發(fā)上汹碱,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音荞估,去河邊找鬼咳促。 笑死,一個(gè)胖子當(dāng)著我的面吹牛泼舱,可吹牛的內(nèi)容都是我干的等缀。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼娇昙,長吁一口氣:“原來是場噩夢啊……” “哼尺迂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起冒掌,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤噪裕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后股毫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體膳音,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年铃诬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了祭陷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡趣席,死狀恐怖兵志,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情宣肚,我是刑警寧澤想罕,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站霉涨,受9級(jí)特大地震影響按价,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜笙瑟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一楼镐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧往枷,春花似錦鸠蚪、人聲如沸今阳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽盾舌。三九已至,卻和暖如春蘸鲸,著一層夾襖步出監(jiān)牢的瞬間妖谴,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來泰國打工酌摇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留膝舅,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓窑多,卻偏偏與公主長得像仍稀,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子埂息,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 一.索引作用 提供了類似于書中目錄的作用技潘,目的是為了優(yōu)化查詢 二.索引的種類 B樹索引Hash索引 R樹索引 Fu...
    極光01閱讀 588評(píng)論 0 0
  • 一: 索引作用: 提供類似書中目錄的作用,目的是為了優(yōu)化查詢 二:索引 的種類: B樹索引Hash索引R樹full...
    醉舞經(jīng)閣半卷書A閱讀 329評(píng)論 0 0
  • B/B+樹 我們?cè)贛ySQL中的數(shù)據(jù)一般是放在磁盤中的千康,讀取數(shù)據(jù)的時(shí)候肯定會(huì)有訪問磁盤的操作享幽,磁盤中有兩個(gè)機(jī)械運(yùn)動(dòng)...
    __destory__閱讀 392評(píng)論 0 0
  • 我們知道一般圖書館都會(huì)建書目索引,可以提高數(shù)據(jù)檢索的效率拾弃,降低數(shù)據(jù)庫的IO成本值桩。MySQL在300萬條記錄左右性能...
    weknow閱讀 814評(píng)論 1 6
  • 久違的晴天,家長會(huì)豪椿。 家長大會(huì)開好到教室時(shí)奔坟,離放學(xué)已經(jīng)沒多少時(shí)間了。班主任說已經(jīng)安排了三個(gè)家長分享經(jīng)驗(yàn)搭盾。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,520評(píng)論 16 22