MySQL 進階之索引

一,索引前傳

  在瞭解數據庫索引以前,首先有必要了解一下數據庫索引的數據結構基礎,那麼什麼樣的數據結構能夠做爲索引呢?php

  B-tree是最經常使用的用於索引的數據結構。由於它們是時間複雜度低, 查找、刪除、插入操做均可以能夠在對數時間內完成。另一個重要緣由存儲在B-Tree中的數據是有序的。數據庫管理系統(RDBMS)一般決定索引應該用哪些數據結構。可是,在某些狀況下,你在建立索引時能夠指定索引要使用的數據結構。css

       B+是一個樹數據結構,一般用於數據庫和操做系統的文件系統中,B+樹的特色是可以保持數據穩定有序,其插入與修改擁有比較穩定的對數時間複雜度,B+樹元素自底向上插入,這個和二叉樹恰好相反。html

  B+tree 是一個n叉樹,每一個節點有多個葉子節點,一顆B+樹包含根節點,內部節點,葉子節點。根節點多是一個葉子節點,也多是一個包含兩個或兩個以上葉子節點的節點。python

  B+tree的性質:mysql

    1.n棵子tree的節點包含n個關鍵字,不用來保存數據而是保存數據的索引。git

    2.全部的葉子結點中包含了所有關鍵字的信息,及指向含這些關鍵字記錄的指針,且葉子結點自己依關鍵字的大小自小而大順序連接。面試

    3.全部的非終端結點能夠當作是索引部分,結點中僅含其子樹中的最大(或最小)關鍵字。算法

        因爲B+tree的性質, 它一般被用於數據庫和操做系統的文件系統中。NTFS, ReiserFS, NSS, XFS, JFS, ReFS 和BFS等文件系統都在使用B+樹做爲元數據索引,由於B+ 樹的特色是可以保持數據穩定有序,其插入與修改擁有較穩定的對數時間複雜度(B+ 樹元素自底向上插入)。sql

B+tree結構原型圖大概以下(引用):數據庫

 

 

哈希表索引是怎麼工做的?

  哈希表是另一種你可能看到用做索引的數據結構-這些索引一般被稱爲哈希索引。使用哈希索引的緣由是,在尋找值時哈希表效率極高。因此,若是使用哈希索引,對於比較字符串是否相等的查詢可以極快的檢索出的值。

哈希索引的缺點是什麼呢?

  哈希表是無順的數據結構,對於不少類型的查詢語句哈希索引都無能爲力。舉例來講,假如你想要找出全部小於40歲的員工。你怎麼使用使用哈希索引進行查詢?這不可行,由於哈希表只適合查詢鍵值對-也就是說查詢相等的查詢(例:like 「WHERE name = ‘Jesus’)。哈希表的鍵值映射也暗示其鍵的存儲是無序的。這就是爲何哈希索引一般不是數據庫索引的默認數據結構-由於在做爲索引的數據結構時,其不像B-Tree那麼靈活

還有什麼其餘類型的索引?

  使用R-Tree做爲數據結構的索引一般用來爲空間問題提供幫助。例如,一個查詢要求「查詢出全部距離我兩千米以內的星巴克」,若是數據庫表使用R- Tree索引,這類查詢的效率將會提升。
  另外一種索引是位圖索引(bitmap index), 這類索引適合放在包含布爾值(true 和 false)的列上,可是這些值(表示true或false的值)的許多實例-基本上都是選擇性(selectivity)低的列。

 二,索引內容

2.一、索引
  索引是對數據庫表中一列或者多列的值進行排序的一種結構,使用索引能夠快速訪問數據庫表中的特定信息,索引有助於更快的獲取信息。索引是表的目錄,在查找內容以前能夠先在目錄中查找索引位置,以此快速定位查詢數據。對於索引,會保存在額外的文件中。

  索引的一個主要的目的就是加快檢索表中數據的方法,也能夠協助信息搜尋者能儘快的找到符合限制條件的記錄。

 

2.二、索引種類

      • 普通索引:僅加速查詢
      • 惟一索引:加速查詢 + 列值惟一(能夠有null)
        • 惟一索引是不容許其中任何兩行具備相同索引值的索引,當現有數據存在大量的重複的鍵值的時候,大多數數據庫不容許惟一索引與表一塊兒保存,數據庫還可能防止添加將表中建立重複鍵值的新數據。
      • 主鍵索引:加速查詢 + 列值惟一 + 表中只有一個(不能夠有null)
        • 數據庫表常常有一列或者多列組合,其值惟一標識表中的每一行,每一列稱爲表的主鍵,在數據庫關係圖中爲表定義主鍵將自動建立主鍵索引,主鍵索引是惟一索引的特定類型,該索引要求主鍵索引的每一個值都惟一。
      • 組合索引:多列值組成一個索引,
                      專門用於組合搜索,其效率大於索引合併
      • 全文索引:對文本的內容進行分詞,進行搜索 

——普通索引

 -1,建立表 + 索引

create table in1(
    nid int not null auto_increment primary key,
    name varchar(32) not null,
    email varchar(64) not null,
    extra text,
    index ix_name (name)
)

 -2,建立表

create index index_name on table_name(column_name)

-3,刪除表

drop index_name on table_name;

-4,查看索引

show index from table_name;

 注意:對於建立索引時若是是BLOB 和 TEXT 類型,必須指定length。

create index ix_extra on in1(extra(32));

——惟一索引

-1,建立表 + 惟一索引

create table in1(
    nid int not null auto_increment primary key,
    name varchar(32) not null,
    email varchar(64) not null,
    extra text,
    unique ix_name (name)
)

-2,建立惟一索引

create unique index 索引名 on 表名(列名)

-3,刪除惟一索引

drop unique index 索引名 on 表名

——主鍵索引

-1,建立表+建立主鍵

create table in1(
    nid int not null auto_increment primary key,
    name varchar(32) not null,
    email varchar(64) not null,
    extra text,
    index ix_name (name)
)

OR

create table in1(
    nid int not null auto_increment,
    name varchar(32) not null,
    email varchar(64) not null,
    extra text,
    primary key(ni1),
    index ix_name (name)
)

-2,建立主鍵

alter table 表名 add primary key(列名);

-3,刪除主鍵

alter table 表名 drop primary key;
alter table 表名  modify  列名 int, drop primary key;

——組合索引

組合索引是將n個列組合成一個索引

其應用場景爲:頻繁的同時使用n列來進行查詢,如:where n1 = 'alex' and n2 = 666。

-1,建立表

create table in3(
    nid int not null auto_increment primary key,
    name varchar(32) not null,
    email varchar(64) not null,
    extra text
)

-2,建立組合索引

create index ix_name_email on in3(name,email);

如上建立組合索引以後,查詢:

  • name and email  -- 使用索引
  • name                 -- 使用索引
  • email                 -- 不使用索引

注意:對於同時搜索n個條件時,組合索引的性能好於多個單一索引合併。

 ——其餘

-1,條件語句(if條件語句例子)

delimiter \\
CREATE PROCEDURE proc_if ()
BEGIN
    
    declare i int default 0;
    if i = 1 THEN
        SELECT 1;
    ELSEIF i = 2 THEN
        SELECT 2;
    ELSE
        SELECT 7;
    END IF;

END\\
delimiter ;

-2,while循環語句

delimiter \\
CREATE PROCEDURE proc_while ()
BEGIN

    DECLARE num INT ;
    SET num = 0 ;
    WHILE num < 10 DO
        SELECT
            num ;
        SET num = num + 1 ;
    END WHILE ;

END\\
delimiter ;

 

-3,repeat循環語句

delimiter \\
CREATE PROCEDURE proc_repeat ()
BEGIN

    DECLARE i INT ;
    SET i = 0 ;
    repeat
        select i;
        set i = i + 1;
        until i >= 5
    end repeat;

END\\
delimiter ;

  

-4,loop循環語句

BEGIN
    
    declare i int default 0;
    loop_label: loop
        
        set i=i+1;
        if i<8 then
            iterate loop_label;
        end if;
        if i>=10 then
            leave loop_label;
        end if;
        select i;
    end loop loop_label;

END

  

-5,動態執行SQL語句

delimiter \\
DROP PROCEDURE IF EXISTS proc_sql \\
CREATE PROCEDURE proc_sql ()
BEGIN
    declare p1 int;
    set p1 = 11;
    set @p1 = p1;

    PREPARE prod FROM 'select * from tb2 where nid > ?';
    EXECUTE prod USING @p1;
    DEALLOCATE prepare prod; 

END\\
delimiter ;

 

2.三、相關命令

查看錶結構
    desc 表名
 
- 查看生成表的SQL
    show create table 表名
 
- 查看索引
    show index from  表名
 
- 查看執行時間
    set profiling = 1;
    SQL...
    show profiles;

2.四、索引的優缺點(使用索引和不使用索引)

 

經過創建索引能夠極大地提升在數據庫中獲取所需信息的速度,同時還能提升服務器處理相關搜索請求的效率,從這個方面來看它具備如下優勢:

 

  • 在設計數據庫時,經過建立一個唯一的索引,可以在索引和信息之間造成一對一的映射式的對應關係,增長數據的唯一性特色。
  • 能提升數據的搜索及檢索速度,符合數據庫創建的初衷。
  • 可以加快表與表之間的鏈接速度,這對於提升數據的參考完整性方面具備重要做用。
  • 在信息檢索過程當中,若使用分組及排序子句進行時,經過創建索引能有效的減小檢索過程當中所需的分組及排序時間,提升檢索效率。
  • 創建索引以後,在信息查詢過程當中可使用優化隱藏器,這對於提升整個信息檢索系統的性能具備重要意義。
雖然索引的創建在提升檢索效率方面具備諸多積極的做用,但仍是存在下列缺點  :
  • 在數據庫創建過程當中,需花費較多的時間去創建並維護索引,特別是隨着數據總量的增長,所花費的時間將不斷遞增。
  • 在數據庫中建立的索引須要佔用必定的物理存儲空間,這其中就包括數據表所佔的數據空間以及所建立的每個索引所佔用的物理空間,若是有必要創建起聚簇索引,所佔用的空間還將進一步的增長
  • 在對錶中的數據進行修改時,例如對其進行增長、刪除或者是修改操做時,索引還須要進行動態的維護,這給數據庫的維護速度帶來了必定的麻煩。

 

因爲索引是專門用於加速搜索而生,因此加上索引以後,查詢效率會快到飛起來。
 
# 有索引
mysql> select * from tb1 where name = 'wupeiqi-888';
+-----+-------------+---------------------+----------------------------------+---------------------+
| nid | name        | email               | radom                            | ctime               |
+-----+-------------+---------------------+----------------------------------+---------------------+
| 255 | tonm        | 12474565666@qq.com  | cdccccce76a16a90b8a8301d5314204b | 2017-08-03 09:33:35 |
+-----+-------------+---------------------+----------------------------------+---------------------+
1 row in set (0.00 sec)
 
# 無索引
mysql> select * from tb1 where email = 'wupeiqi888@live.com';
+-----+-------------+---------------------+----------------------------------+---------------------+
| nid | name        | email               | radom                            | ctime               |
+-----+-------------+---------------------+----------------------------------+---------------------+
| 256 | tonm        | 12474565666@qq.com  | 5312269e76a1clslclscc01d5314204b | 2017-08-03 09:33:35 |
+-----+-------------+---------------------+----------------------------------+---------------------+
1 row in set (1.23 sec)

  

2五、正確使用索引

數據庫表中添加索引後確實會讓查詢速度起飛,但前提必須是正確的使用索引來查詢,若是以錯誤的方式使用,則即便創建索引也會不奏效。
即便創建索引,索引也不會生效:

- like '%xx'
    select * from tb1 where name like '%cn';
- 使用函數
    select * from tb1 where reverse(name) = 'wupeiqi';
- or
    select * from tb1 where nid = 1 or email = 'seven@live.com';
    特別的:當or條件中有未創建索引的列才失效,如下會走索引
            select * from tb1 where nid = 1 or name = 'seven';
            select * from tb1 where nid = 1 or email = 'seven@live.com' and name = 'alex'
- 類型不一致
    若是列是字符串類型,傳入條件是必須用引號引發來,否則...
    select * from tb1 where name = 999;
- !=
    select * from tb1 where name != 'alex'
    特別的:若是是主鍵,則仍是會走索引
        select * from tb1 where nid != 123
- >
    select * from tb1 where name > 'alex'
    特別的:若是是主鍵或索引是整數類型,則仍是會走索引
        select * from tb1 where nid > 123
        select * from tb1 where num > 123
- order by
    select email from tb1 order by name desc;
    當根據索引排序時候,選擇的映射若是不是索引,則不走索引
    特別的:若是對主鍵排序,則仍是走索引:
        select * from tb1 order by nid desc;
 
- 組合索引最左前綴
    若是組合索引爲:(name,email)
    name and email       -- 使用索引
    name                 -- 使用索引
    email                -- 不使用索引

 

2.6,使用索引注意事項

   索引是創建在數據庫表中的某些列的上面。在建立索引的時候,應該考慮在哪些列上能夠建立索引,在哪些列上不能建立索引。通常來講,應該在這些列上建立索引:
  在常常須要搜索的列上,能夠加快搜索的速度;
  在做爲 主鍵的列上,強制該列的惟一性和組織表中數據的排列結構;
  在常常用在鏈接的列上,這些列主要是一些 外鍵,能夠加快鏈接的速度;在常常須要根據範圍進行搜索的列上建立索引,由於索引已經排序,其指定的範圍是連續的;
  在常常須要排序的列上建立索引,由於索引已經排序,這樣查詢能夠利用索引的排序,加快排序查詢時間;
  在常用在WHERE子句中的列上面建立 索引,加快條件的判斷速度。
  一樣,對於有些列不該該建立索引。通常來講,不該該建立索引的這些列具備下列特色:
  第一,對於那些在查詢中不多使用或者參考的列不該該建立索引。這是由於,既然這些列不多使用到,所以有索引或者無索引,並不能提升查詢速度。相反,因爲增長了索引,反而下降了系統的維護速度和增大了空間需求。
  第二,對於那些只有不多數據值的列也不該該增長索引。這是由於,因爲這些列的取值不多,例如人事表的性別列,在查詢的結果中, 結果集的數據行佔了表中數據行的很大比例,即須要在表中搜索的數據行的比例很大。增長 索引,並不能明顯加快檢索速度。
  第三,對於那些定義爲text, image和 bit數據類型的列不該該增長索引。這是由於,這些列的數據量要麼至關大,要麼取值不多,不利於使用索引。
  第四,當修改性能遠遠大於檢索性能時,不該該建立索引。這是由於,修改性能和檢索性能是互相矛盾的。當增長索引時,會提升檢索性能,可是會下降修改性能。當減小索引時,會提升修改性能,下降檢索性能。所以,當修改操做遠遠多於檢索操做時,不該該建立索引。

 三,索引後記

3.1把數據庫索引類比成什麼比較好呢?

  一個很是好的類比是把數據庫索引看做是書的索引。若是你有一本關於狗的書,你想要找關於‘黃金獵犬’的那部分。當你能夠經過在書背的索引找到哪幾頁有關於‘黃金獵犬’信息的時候,你爲何要翻完正本書 - 這至關於數據庫中的全表掃描。一樣的,就像一本書的索引包含頁碼同樣,數據庫的索引包含了指針,指向你在SQL中想要查詢的值所在的行。

3.2使用數據庫索引會有什麼代價?

  那麼,使用數據庫索引有什麼缺點呢?其一,索引會佔用空間 - 你的表越大,索引佔用的空間越大。其二,性能損失(主要值更新操做),當你在表中添加、刪除或者更新行數據的時候, 在索引中也會有相同的操做。

記住:創建在某列(或多列)索引須要保存該列最新的數據

基本原則是隻若是表中某列在查詢過程當中使用的很是頻繁,那就在該列上建立索引

3.三、limit分頁

不管是否有索引,limit分頁是一個值得關注的問題

每頁顯示10條:
當前 118 120, 125

倒序:
            大      小
   970  7 6  6 5  54  43  32
19 98     
下一頁:

    select 
        * 
    from 
        tb1 
    where 
        nid < (select nid from (select nid from tb1 where nid < 當前頁最小值 order by nid desc limit 每頁數據 *【頁碼-當前頁】) A order by A.nid asc limit 1)  
    order by 
        nid desc 
    limit 10;



    select 
        * 
    from 
        tb1 
    where 
        nid < (select nid from (select nid from tb1 where nid < 970  order by nid desc limit 40) A order by A.nid asc limit 1)  
    order by 
        nid desc 
    limit 10;


上一頁:

    select 
        * 
    from 
        tb1 
    where 
        nid < (select nid from (select nid from tb1 where nid > 當前頁最大值 order by nid asc limit 每頁數據 *【當前頁-頁碼】) A order by A.nid asc limit 1)  
    order by 
        nid desc 
    limit 10;


    select 
        * 
    from 
        tb1 
    where 
        nid < (select nid from (select nid from tb1 where nid > 980 order by nid asc limit 20) A order by A.nid desc limit 1)  
    order by 
        nid desc 
    limit 10;

  

3.四、執行計劃

explain + 查詢SQL - 用於顯示SQL執行信息參數,根據參考信息能夠進行SQL優化

mysql> explain select * from tb2;
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | tb2   | ALL  | NULL          | NULL | NULL    | NULL |    2 | NULL  |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)
id
        查詢順序標識
            如:mysql> explain select * from (select nid,name from tb1 where nid < 10) as B;
            +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
            | id | select_type | table      | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
            +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
            |  1 | PRIMARY     | <derived2> | ALL   | NULL          | NULL    | NULL    | NULL |    9 | NULL        |
            |  2 | DERIVED     | tb1        | range | PRIMARY       | PRIMARY | 8       | NULL |    9 | Using where |
            +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
        特別的:若是使用union鏈接氣值可能爲null


    select_type
        查詢類型
            SIMPLE          簡單查詢
            PRIMARY         最外層查詢
            SUBQUERY        映射爲子查詢
            DERIVED         子查詢
            UNION           聯合
            UNION RESULT    使用聯合的結果
            ...
    table
        正在訪問的表名


    type
        查詢時的訪問方式,性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const
            ALL             全表掃描,對於數據表從頭至尾找一遍
                            select * from tb1;
                            特別的:若是有limit限制,則找到以後就不在繼續向下掃描
                                   select * from tb1 where email = 'seven@live.com'
                                   select * from tb1 where email = 'seven@live.com' limit 1;
                                   雖然上述兩個語句都會進行全表掃描,第二句使用了limit,則找到一個後就再也不繼續掃描。

            INDEX           全索引掃描,對索引從頭至尾找一遍
                            select nid from tb1;

            RANGE          對索引列進行範圍查找
                            select *  from tb1 where name < 'alex';
                            PS:
                                between and
                                in
                                >   >=  <   <=  操做
                                注意:!= 和 > 符號


            INDEX_MERGE     合併索引,使用多個單列索引搜索
                            select *  from tb1 where name = 'alex' or nid in (11,22,33);

            REF             根據索引查找一個或多個值
                            select *  from tb1 where name = 'seven';

            EQ_REF          鏈接時使用primary key 或 unique類型
                            select tb2.nid,tb1.name from tb2 left join tb1 on tb2.nid = tb1.nid;



            CONST           常量
                            表最多有一個匹配行,由於僅有一行,在這行的列值可被優化器剩餘部分認爲是常數,const表很快,由於它們只讀取一次。
                            select nid from tb1 where nid = 2 ;

            SYSTEM          系統
                            表僅有一行(=系統表)。這是const聯接類型的一個特例。
                            select * from (select nid from tb1 where nid = 1) as A;
    possible_keys
        可能使用的索引

    key
        真實使用的

    key_len
        MySQL中使用索引字節長度

    rows
        mysql估計爲了找到所需的行而要讀取的行數 ------ 只是預估值

    extra
        該列包含MySQL解決查詢的詳細信息
        「Using index」
            此值表示mysql將使用覆蓋索引,以免訪問表。不要把覆蓋索引和index訪問類型弄混了。
        「Using where」
            這意味着mysql服務器將在存儲引擎檢索行後再進行過濾,許多where條件裏涉及索引中的列,當(而且若是)它讀取索引時,就能被存儲引擎檢驗,所以不是全部帶where子句的查詢都會顯示「Using where」。有時「Using where」的出現就是一個暗示:查詢可受益於不一樣的索引。
        「Using temporary」
            這意味着mysql在對查詢結果排序時會使用一個臨時表。
        「Using filesort」
            這意味着mysql會對結果使用一個外部索引排序,而不是按索引次序從表裏讀取行。mysql有兩種文件排序算法,這兩種排序方式均可以在內存或者磁盤上完成,explain不會告訴你mysql將使用哪種文件排序,也不會告訴你排序會在內存裏仍是磁盤上完成。
        「Range checked for each record(index map: N)」
            這個意味着沒有好用的索引,新的索引將在聯接的每一行上從新估算,N是顯示在possible_keys列中索引的位圖,而且是冗餘的。

詳細

  

1)、id列數字越大越先執行,若是說數字同樣大,那麼就從上往下依次執行,id列爲null的就表是這是一個結果集,不須要使用它來進行查詢。

 
2)、select_type列常見的有:
A:simple:表示不須要union操做或者不包含子查詢的簡單select查詢。有鏈接查詢時,外層的查詢爲simple,且只有一個
B:primary:一個須要union操做或者含有子查詢的select,位於最外層的單位查詢的select_type即爲primary。且只有一個
C:union:union鏈接的兩個select查詢,第一個查詢是dervied派生表,除了第一個表外,第二個之後的表select_type都是union
D:dependent union:與union同樣,出如今union 或union all語句中,可是這個查詢要受到外部查詢的影響
E:union result:包含union的結果集,在union和union all語句中,由於它不須要參與查詢,因此id字段爲null
F:subquery:除了from字句中包含的子查詢外,其餘地方出現的子查詢均可能是subquery
G:dependent subquery:與dependent union相似,表示這個subquery的查詢要受到外部表查詢的影響
H:derived:from字句中出現的子查詢,也叫作派生表,其餘數據庫中可能叫作內聯視圖或嵌套select
 
3)、table
顯示的查詢表名,若是查詢使用了別名,那麼這裏顯示的是別名,若是不涉及對數據表的操做,那麼這顯示爲null,若是顯示爲尖括號括起來的<derived N>就表示這個是臨時表,後邊的N就是執行計劃中的id,表示結果來自於這個查詢產生。若是是尖括號括起來的<union M,N>,與<derived N>相似,也是一個臨時表,表示這個結果來自於union查詢的id爲M,N的結果集。
 
4)、type
依次從好到差:system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,index_subquery,range,index_merge,index,ALL,除了all以外,其餘的type均可以使用到索引,除了index_merge以外,其餘的type只能夠用到一個索引
A:system:表中只有一行數據或者是空表,且只能用於myisam和memory表。若是是Innodb引擎表,type列在這個狀況一般都是all或者index
B:const:使用惟一索引或者主鍵,返回記錄必定是1行記錄的等值where條件時,一般type是const。其餘數據庫也叫作惟一索引掃描
C:eq_ref:出如今要鏈接過個表的查詢計劃中,驅動表只返回一行數據,且這行數據是第二個表的主鍵或者惟一索引,且必須爲not null,惟一索引和主鍵是多列時,只有全部的列都用做比較時纔會出現eq_ref
D:ref:不像eq_ref那樣要求鏈接順序,也沒有主鍵和惟一索引的要求,只要使用相等條件檢索時就可能出現,常見與輔助索引的等值查找。或者多列主鍵、惟一索引中,使用第一個列以外的列做爲等值查找也會出現,總之,返回數據不惟一的等值查找就可能出現。
E:fulltext:全文索引檢索,要注意,全文索引的優先級很高,若全文索引和普通索引同時存在時,mysql無論代價,優先選擇使用全文索引
F:ref_or_null:與ref方法相似,只是增長了null值的比較。實際用的很少。
G:unique_subquery:用於where中的in形式子查詢,子查詢返回不重複值惟一值
H:index_subquery:用於in形式子查詢使用到了輔助索引或者in常數列表,子查詢可能返回重複值,可使用索引將子查詢去重。
I:range:索引範圍掃描,常見於使用>,<,is null,between ,in ,like等運算符的查詢中。
J:index_merge:表示查詢使用了兩個以上的索引,最後取交集或者並集,常見and ,or的條件使用了不一樣的索引,官方排序這個在ref_or_null以後,可是實際上因爲要讀取所個索引,性能可能大部分時間都不如range
K:index:索引全表掃描,把索引從頭至尾掃一遍,常見於使用索引列就能夠處理不須要讀取數據文件的查詢、可使用索引排序或者分組的查詢。
L:all:這個就是全表掃描數據文件,而後再在server層進行過濾返回符合要求的記錄。
 
5)、possible_keys
查詢可能使用到的索引都會在這裏列出來
 
6)、key
查詢真正使用到的索引,select_type爲index_merge時,這裏可能出現兩個以上的索引,其餘的select_type這裏只會出現一個。
 
7)、key_len
用於處理查詢的索引長度,若是是單列索引,那就整個索引長度算進去,若是是多列索引,那麼查詢不必定都能使用到全部的列,具體使用到了多少個列的索引,這裏就會計算進去,沒有使用到的列,這裏不會計算進去。留意下這個列的值,算一下你的多列索引總長度就知道有沒有使用到全部的列了。要注意,mysql的ICP特性使用到的索引不會計入其中。另外, key_len只計算where條件用到的索引長度,而排序和分組就算用到了索引,也不會計算到key_len中。
 
8)、ref
若是是使用的常數等值查詢,這裏會顯示const,若是是鏈接查詢,被驅動表的執行計劃這裏會顯示驅動表的關聯字段,若是是條件使用了表達式或者函數,或者條件列發生了內部隱式轉換,這裏可能顯示爲func
 
9)、rows
這裏是執行計劃中估算的掃描行數,不是精確值
 
10)、extra
這個列能夠顯示的信息很是多,有幾十種,經常使用的有
A:distinct:在select部分使用了distinc關鍵字
B:no tables used:不帶from字句的查詢或者From dual查詢
C:使用not in()形式子查詢或not exists運算符的鏈接查詢,這種叫作反鏈接。即,通常鏈接查詢是先查詢內表,再查詢外表,反鏈接就是先查詢外表,再查詢內表。
D:using filesort:排序時沒法使用到索引時,就會出現這個。常見於order by和group by語句中
E:using index:查詢時不須要回表查詢,直接經過索引就能夠獲取查詢的數據。
F:using join buffer(block nested loop),using join buffer(batched key accss):5.6.x以後的版本優化關聯查詢的BNL,BKA特性。主要是減小內表的循環數量以及比較順序地掃描查詢。
G:using sort_union,using_union,using intersect,using sort_intersection:
using intersect:表示使用and的各個索引的條件時,該信息表示是從處理結果獲取交集
using union:表示使用or鏈接各個使用索引的條件時,該信息表示從處理結果獲取並集
using sort_union和using sort_intersection:與前面兩個對應的相似,只是他們是出如今用and和or查詢信息量大時,先查詢主鍵,而後進行排序合併後,才能讀取記錄並返回。
H:using temporary:表示使用了臨時表存儲中間結果。臨時表能夠是內存臨時表和磁盤臨時表,執行計劃中看不出來,須要查看status變量,used_tmp_table,used_tmp_disk_table才能看出來。
I:using where:表示存儲引擎返回的記錄並非全部的都知足查詢條件,須要在server層進行過濾。查詢條件中分爲限制條件和檢查條件,5.6以前,存儲引擎只能根據限制條件掃描數據並返回,而後server層根據檢查條件進行過濾再返回真正符合查詢的數據。5.6.x以後支持ICP特性,能夠把檢查條件也下推到存儲引擎層,不符合檢查條件和限制條件的數據,直接不讀取,這樣就大大減小了存儲引擎掃描的記錄數量。extra列顯示using index condition
J:firstmatch(tb_name):5.6.x開始引入的優化子查詢的新特性之一,常見於where字句含有in()類型的子查詢。若是內表的數據量比較大,就可能出現這個
K:loosescan(m..n):5.6.x以後引入的優化子查詢的新特性之一,在in()類型的子查詢中,子查詢返回的可能有重複記錄時,就可能出現這個
 
除了這些以外,還有不少查詢數據字典庫,執行計劃過程當中就發現不可能存在結果的一些提示信息
 
11)、filtered
使用explain extended時會出現這個列,5.7以後的版本默認就有這個字段,不須要使用explain extended了。這個字段表示存儲引擎返回的數據在server層過濾後,剩下多少知足查詢的記錄數量的比例,注意是百分比,不是具體記錄數。

3.五、慢日誌查詢

a、配置MySQL自動記錄慢日誌

slow_query_log = OFF                            是否開啓慢日誌記錄
long_query_time = 2                              時間限制,超過此時間,則記錄
slow_query_log_file = /usr/slow.log        日誌文件
log_queries_not_using_indexes = OFF     爲使用索引的搜索是否記錄

注:查看當前配置信息:
       show variables like '%query%'
     修改當前配置:
    set global 變量名 = 值

b、查看MySQL慢日誌

mysqldumpslow -s at -a  /usr/local/var/mysql/MacBook-Pro-3-slow.log

"""
--verbose    版本
--debug      調試
--help       幫助
 
-v           版本
-d           調試模式
-s ORDER     排序方式
             what to sort by (al, at, ar, c, l, r, t), 'at' is default
              al: average lock time
              ar: average rows sent
              at: average query time
               c: count
               l: lock time
               r: rows sent
               t: query time
-r           反轉順序,默認文件倒序拍。reverse the sort order (largest last instead of first)
-t NUM       顯示前N條just show the top n queries
-a           不要將SQL中數字轉換成N,字符串轉換成S。don't abstract all numbers to N and strings to 'S'
-n NUM       abstract numbers with at least n digits within names
-g PATTERN   正則匹配;grep: only consider stmts that include this string
-h HOSTNAME  mysql機器名或者IP;hostname of db server for *-slow.log filename (can be wildcard),
             default is '*', i.e. match all
-i NAME      name of server instance (if using mysql.server startup script)
-l           總時間中不減去鎖定時間;don't subtract lock time from total time
"""

  

 

數據庫的索引很是重要,基本面試數據庫的問題都在索引上,因此這裏小編整理出來,一方面爲了本身複習,一方面也方便你們。

(關於MySQL的安裝,具體見下面博客:http://www.cnblogs.com/wj-1314/p/7573242.html

(關於MySQL的基礎知識,具體見下面博客:http://www.cnblogs.com/wj-1314/p/8343101.html

(關於MySQL的筆試知識,具體見下面博客:http://www.cnblogs.com/wj-1314/p/7643125.html

 此篇博客主要參考:http://www.cnblogs.com/wupeiqi/articles/5716963.html;http://www.cnblogs.com/xiaoboluo768/p/5400990.html,寫在這裏主要是爲了鞏固學習知識,同時但願更多的同窗學習。

相關文章
相關標籤/搜索