MySQL索引

索引管理

索引是什麼?

索引就比如一本書的目錄,它會讓你更快的找到內容;mysql

讓獲取的數據更有目的性,從而提升數據庫檢索數據的性能;sql

索引創建在表的列上(字段)。數據庫

索引的設計理念

數據庫索引的設計原則:緩存

爲了使索引的使用效率更高,在建立索引時,必須考慮在哪些字段上建立索引和建立什麼類型的索引。服務器

那麼索引設計原則又是怎樣的?運維

1.選擇惟一性索引函數

     惟一性索引的值是惟一的,能夠更快速的經過該索引來肯定某條記錄。性能

    例如,學生表中學號是具備惟一性的字段。爲該字段創建惟一性索引能夠很快的肯定某個學生的信息。優化

  若是使用姓名的話,可能存在同名現象,從而下降查詢速度。ui

2.爲常常須要排序、分組和聯合操做的字段創建索引

  常常須要ORDER BY、GROUP BY、DISTINCT和UNION等操做的字段,排序操做會浪費不少時間。

  若是爲其創建索引,能夠有效地避免排序操做。

3.爲常做爲查詢條件的字段創建索引

  若是某個字段常常用來作查詢條件,那麼該字段的查詢速度會影響整個表的查詢速度。所以,

  爲這樣的字段創建索引,能夠提升整個表的查詢速度。

4.限制索引的數目

  索引的數目不是越多越好。每一個索引都須要佔用磁盤空間,索引越多,須要的磁盤空間就越大。

  修改表時,對索引的重構和更新很麻煩。越多的索引,會使更新表變得很浪費時間。

5.儘可能使用數據量少的索引

  若是索引的值很長,那麼查詢的速度會受到影響。例如,對一個CHAR(100)類型的字段進行全文

  檢索須要的時間確定要比對CHAR(10)類型的字段須要的時間要多。

6.儘可能使用前綴來索引

  若是索引字段的值很長,最好使用值的前綴來索引。例如,TEXT和BLOG類型的字段,進行全文檢索

  會很浪費時間。若是隻檢索字段的前面的若干個字符,這樣能夠提升檢索速度。

7.刪除再也不使用或者不多使用的索引

  表中的數據被大量更新,或者數據的使用方式被改變後,原有的一些索引可能再也不須要。數據庫管理

  員應當按期找出這些索引,將它們刪除,從而減小索引對更新操做的影響。

8.小表不該創建索引;

  包含大量的列而且不須要搜索非空值的時候能夠考慮不建索引

索引的分類

主鍵索引

主鍵索引:只能有一個主鍵。

列的內容是惟一值

表建立的時候至少要有一個主鍵索引,最好和業務無關。

主鍵索引的創建,是在規範化建立表的時候就自動添加了

實例(建表時添加)
mysql> create table test(id int(4) not null auto_increment,name char(20) not null,primary key (id));
Query OK, 0 rows affected (0.02 sec)

mysql> desc test;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| id    | int(4)   | NO   | PRI | NULL    | auto_increment |
| name  | char(20) | NO   |     | NULL    |                |
+-------+----------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

PRI就表明主鍵索引

實例2(建表後增長)
alter table test change id id int(4) primary key not null auto_increment;

普通索引

加快查詢速度,工做中優化數據庫的關鍵。

在合適的列上創建索引,讓數據查詢更高效。

建立格式:

alter table 表名 add index 索引名(列名);
create index 索引名 on 表名(列名);

實例(MUL就表明是普通索引):

mysql> alter table test1 add key name_idx(name);
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc test1;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(10)     | YES  |     | NULL    |       |
| name  | varchar(20) | YES  | MUL | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

普通索引建立的條件

一、查詢需求多的 (業務邏輯中,where條件後常常查詢的條件)

二、惟一值多的列

      (1)統計下總行數

      (2)計算不重複的行數量

查看錶的惟一值數量:

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

distinct通常是用來去除查詢結果中的重複記錄的

前綴索引

根據字段的前N個字符創建索引

就是若是想作索引的一些字符過多,而後就可使用前綴索引,之前幾個字符作索引

create index name_idx on test(name(8));
show index from test\G

實例

mysql> create index name_idx on test(name(2));
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc test;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| id    | int(4)   | NO   | PRI | NULL    | auto_increment |
| name  | char(20) | NO   | MUL | NULL    |                |
+-------+----------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

複合索引

就是以表中的多個列作索引,把最經常使用來做爲條件查詢的列放在前面。

alter table ppp add key name_sex_idx(name,age);

惟一索引

內容是惟一的,但不是主鍵,是在主鍵上作的索引,除了惟一索引,其他的能夠說全是普通索引。

create unique index index_name on tese(name);
alter table ppp add unique key age_uidx(age);

刪除索引

刪除索引實例

mysql> alter table test1 drop index name_idx;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc test1;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(10)     | YES  | MUL | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

查詢索引

desc 表名
show index from 表名\G

查詢是否走沒走索引

使用的sql語句:explain  查詢執行計劃

explain顯示的內容詳解

id | select_type | table |type| possible_keys | key| key_len |ref|rows | Extra
explain查看sql執行計劃

explain顯示了mysql如何使用索引來處理select語句以及鏈接表。能夠幫助選擇更好的索引和寫出更優化的查詢語句。

使用方法,在select語句前加上explain就能夠了:

mysql> explain select id,name from test where name='baba'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: test
type: ref
possible_keys: ind_name
key: ind_name
key_len: 60
ref: const
rows: 1
Extra: Using where; Using index
1 row in set (0.00 sec)
++++++++++++++++++++++++++++

explain select SQL_NO_CACHE * from test where name='baba'\G

SQL_NO_CACHE的做用是禁止緩存查詢結果。

一、id

SELECT識別符。這是SELECT查詢序列號。這個不重要,查詢序號即爲sql語句執行的順序

  • id相同,執行順序由上至下
  • 若是是子查詢,id的序號會遞增,id值越大優先級越高,越先被執行
  • id若是相同,能夠認爲是一組,從上往下順序執行;在全部組中,id值越大,優先級越高,越先執行
二、select_type

示查詢中每一個select子句的類型

select類型,它有如下幾種值:

  • simple 它表示簡單的select,沒有union和子查詢
  • primary 最外面的select,在有子查詢的語句中,最外面的select查詢就是primary
  • union union語句的第二個或者說是後面那一個
  • dependent union  UNION中的第二個或後面的SELECT語句,取決於外面的查詢
  • union result  UNION的結果,如上面所示
  • 在SELECT或WHERE列表中包含了子查詢,該子查詢被標記爲:SUBQUERY
  • 還有幾個參數,這裏就不說了,不重要
三、table

輸出的行所用的表

四、type

鏈接類型。有多個參數,先從最佳類型到最差類型介紹,很重要

表示MySQL在表中找到所需行的方式,又稱「訪問類型」,常見類型以下:

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

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

system 表僅有一行,這是const類型的特列,平時不會出現,這個也能夠忽略不計

const 表最多有一個匹配行,const用於比較primary key 或者unique索引。由於只匹配一行數據,因此很快。記住必定是用到primary key 或者unique,而且只檢索出兩條數據的 狀況下才會是const,能夠理解爲const是最優化的

  • a. ALL:Full Table Scan, MySQL將遍歷全表以找到匹配的行
  • b. index:Full Index Scan,index與ALL區別爲index類型只遍歷索引樹
  • c. range:索引範圍掃描,對索引的掃描開始於某一點,返回匹配值域的行。顯而易見的索引範圍掃描是帶有between或者where子句裏帶有<, >查詢。當mysql使用索引去查找一系列值時,例如IN()和OR列表,也會顯示range(範圍掃描),固然性能上面是有差別的。
  • d. ref:使用非惟一索引掃描或者惟一索引的前綴掃描,返回匹配某個單獨值的記錄行
  • e. eq_ref:相似ref,區別就在使用的索引是惟一索引,對於每一個索引鍵值,表中只有一條記錄匹配,簡單來講,就是多表鏈接中使用primary key或者 unique key做爲關聯條件
  • f. const、system:當MySQL對查詢某部分進行優化,並轉換爲一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換爲一個常量
  • g. NULL:MySQL在優化過程當中分解語句,執行時甚至不用訪問表或索引, 例如從一個索引列裏選取最小值能夠經過單獨索引查找完成。
五、possible_keys

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

六、key

顯示MySQL在查詢中實際使用的索引,

若沒有使用索引,顯示爲NULL

七、key_len

表示索引中使用的字節數,可經過該列計算查詢中使用的索引的長度(key_len顯示的值爲索引字段的最大可能長度,並不是實際使用長度,即key_len是根據表定義計算而得,不是經過表內檢索出的)

八、ref

表示上述表的鏈接匹配條件,即哪些列或常量被用於查找索引列上的值

九、rows

表示MySQL根據表統計信息及索引選用狀況,估算的找到所需的記錄所須要讀取的行數

十、Extra

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

a. Using index

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

b. Using where

  表示mysql服務器將在存儲引擎檢索行後再進行過濾。許多where條件裏涉及索引中的列,當(而且若是)它讀取索引時,就能被存儲引擎檢驗,所以不是全部帶where字句的查詢都會顯示"Using where"。有時"Using where"的出現就是一個暗示:查詢可受益與不一樣的索引。

c. Using temporary

  表示MySQL須要使用臨時表來存儲結果集,常見於排序和分組查詢

d. Using filesort

  MySQL中沒法利用索引完成的排序操做稱爲「文件排序」

  Using join buffer

  該值強調了在獲取鏈接條件時沒有使用索引,

  而且須要鏈接緩衝區來存儲中間結果。

  若是出現了這個值,那應該注意,根據查詢的具體狀況可能須要添加索引來改進能。

f. Impossible where

  這個值強調了where語句會致使沒有符合條件的行。

I. Index merges

  當MySQL 決定要在一個給定的表上使用超過一個索引的時候,就會出現如下格式中的一個,詳細說明使用的索引以及合併的類型。

(優化)不走索引的緣由總結

企業級SQL優化思路

一、把一個大的不使用索引的SQL語句按照功能進行拆分

二、長的SQL語句沒法使用索引,能不能變成2條短的SQL語句讓它分別使用上索引

三、對SQL語句功能的拆分和修改

四、減小「爛」SQL

      由運維(DBA)和開發交流(確認),共同肯定如何改,最終由DBA執行

五、制定開發流程

不走索引的緣由

走不走索引的決定權在優化器上:

一、集羣因子過大,可能不走索引

二、未來結果集的條目佔總數據量的30%的時候,優化器就以爲走全表掃描計劃更好(where)

三、默認的order by單獨使用的時候,優化器也以爲全變掃面更好(where和limit)

四、子查詢儘可能避免 union或者union all

五、select 使用了不合理的條件或功能(沒有where 邏輯計算符號 運算符號+-*/  函數)

六、帶有 select * 可能不走索引

七、where條件中有like 而且'%a%',能夠支持'a%',可是不必定

八、沒有查詢條件,或者查詢條件沒有創建索引

九、索引自己失效

十、對小表查詢

十一、統計數據不真實

十二、CBO計算走索引花費過大的狀況。其實也包含了上面的狀況,這裏指的是表佔有的block要比索引小。

1三、隱式轉換致使索引失效.這一點應當引發重視.也是開發中常常會犯的錯誤. 因爲表的字段tel_num定義爲varchar2(20),但在查詢時把該字段做爲number類型以where條件傳給數據庫,這樣會致使索引失效.

錯誤的例子:select * from test where tel_nume=13333333333;

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

1四、not in ,not exist.

1五、in  儘可能改爲 union

1六、當變量採用的是times變量,而表的字段採用的是date變量時.或相反狀況。

1七、B-tree索引is null不會走,is not null會走,位圖索引 is null,is not null 都會走

1八、聯合索引 is not null 只要在創建的索引列(不分前後)都會走, in null時 必需要和創建索引第一列一塊兒使用,當創建索引第一位置條件是is null 時,其餘創建索引的列能夠是is null(但必須在全部列 都知足is null的時候),或者=一個值; 當創建索引的第一位置是=一個值時,其餘索引列能夠是任何狀況(包括is null =一個值),以上兩種狀況索引都會走。其餘狀況不會走。

相關文章
相關標籤/搜索