sql執行時間長,性能下降的原因推測:
    1.查詢語句寫的不好
    2.索引失效
        索引分為:
            1.單值索引
                create index idx_user_name on user(name)
            2.多值索引
                create index idx_user_nameEmail on user(name,email)
    3.關聯查詢太多的join(設計缺陷或者不得已的請求)
   4.服務器調優及各個參數設置(緩存、線程數等)

sql的執行順序

網卡索引號什麼時候用_表名

執行順序魚骨圖如下:

網卡索引號什麼時候用_字段_02

7種join

網卡索引號什麼時候用_表名_03


索引

Mysql官方對索引的定義是:索引(Index)是幫助mysql搞笑獲取數據的數據結構
索引本質:是一種數據結構
可以簡單的理解為:索引是排好序的快速查找數據結構

一般來説,索引本身也很大,不可能全部存儲在內存中,因此索引往往以索引文件的形式存儲在硬盤上
我們平時説的索引,如果沒有特別指明,都是指B樹(多路搜索樹,並不一定是二叉樹)結構組織的索引,其中包含了聚集索引,次要索引,複合索引,前綴索引,唯一索引
默認都是使用B+數索引,統稱為索引

索引的優劣勢:
    1.優勢
        提高數據檢索效率,降低數據庫的io成本
        通過索引對數據進行排序,降低數據排序的成本,降低了CPU的消耗
    2.劣勢
        1.實際上索引也是一張表,該表保存了主鍵和索引字段,並執行實體表的記錄,所以索引列也是要佔用空間的
        2.雖然索引大大的提高了查詢效率,同時也會降低更新表的速度,如對錶進行INSERT\UPDATE\DELETE
        3.因為更新表結構是,mysql不僅要保存數據還要保存一下索引文件每次更新添加了索引的字段,都會調整因為更新所帶來的鍵值變化後的索引信息 
        
        
索引分類:
    1.單值索引:
        一個索引值包含單個列,一個表可以有多個單列索引
    2.唯一索引
        索引列的值必須唯一,但允許有空值
    3.複合索引
        即一個索引包含多個列
        
常用命令:
    1.創建索引
        CREATE INDEX 索引名稱 ON 表名 (字段,字段):一個字段就是單值索引,多個字段就是多值索引
        ALTER 表名 ADD INDEX 索引名稱 ON (字段,字段)
        1.1給表添加一個主鍵,這就意味着索引值必須唯一,且不能為null
            ALTER TABLE 表名 ADD PRIMARY KEY(id字段);
        1.2該條語句創建的索引值必須唯一(除了NULL外,null可能會出現多次)
            ALTER TABLE 表名 ADD UNIQUE 索引名(字段)
        1.3添加普通索引,索引值可以出現多次
            ALTER TABLE 表名 ADD INDEX 索引名(字段)添加普通索引
        1.4指定索引為FULLTEXT,用於全文索引
            ALTER TABLE 表名 ADD FULLTEXT 索引名稱(字段名)
    2.刪除索引:
        DROP INDEX 索引名稱 ON 表名
    3.查看索引:
        SHOW INDEX FROM 表名
        
        
mysql索引結構:
    1.BTree索引
    2.Hash索引
    3.full-text全文索引
    4.R-Tree索引

B-TREE的邏輯圖如下:

網卡索引號什麼時候用_數據_04

上述圖便是b+數的邏輯示意圖:
    一個b+樹,粉紅色地區為一個磁盤塊,每個磁盤塊都包含了數據項和指針(p1,p2,p3)
    非葉子節點是不存儲真實的數據,只存儲指引搜索方向的數據項,如17,35並不真實存在於數據表中
查找過程:
    如果查找的數據是29,
    1.首先會將磁盤塊1加載到內存,此時發生一次IO,在內存中利用二分法查找確定29在17和35之間,鎖定磁盤1的p2指針
    2.通過磁盤1的p2指針將磁盤3加載到內存中,發生第二次IO,29在26和30之間,鎖定磁盤3的p2指針
    3.通過指針加載到次磁盤8到內存,發生第三次IO,同時通過二分法查找到29,查詢結束,總計三次IO
真實情況:
    3層的B+樹可以表示上百萬的數據,如果上百萬的數據查找只需要三次IO,性能提升將是巨大的,如果沒有索引,每個數據項都要進行一次IO,那麼總共需要上百次的IO,顯然成本是非常的高

哪些情況下創建索引:

1.創建索引的情況:
    1.主鍵自動創建唯一索引
    2.頻繁作為查找條件的字段應該創建索引
    3.查詢中於其他表關聯的字段,外鍵關係創建索引
    4.頻繁更新的字段不適合創建索引:因為每次更新不僅是更新了記錄還會更新索引信息
    5.where條件中用不到的字段不要創建索引
    6.單鍵/組合索引的選擇問題:在高併發下傾向於創建組合索引
    7.查詢中排序字段,排序字段若通過索引去訪問會大大的提高排序速度
    8.查詢中統計或者分組字段

2.不創建索引的情況:
    1.表記錄太少
    2.經常增刪改查的表:因為更新表結構是,mysql不僅要保存數據還要保存一下索引文件每次更新添加了索引的字段,都會調整因為更新所帶來的鍵值變化後的索引信息  
    3.數據重複且分佈平均的表字段,因此應該只為最經常查詢和最經常排序的表創建索引
      注意:如果某個數據列包含了很多重複的內容,為他創建索引就沒有太大的實際效果

性能分析:Explain

mysql常見的瓶頸:
    1.CPU:CPU在飽和的時候一般發生在數據裝入內存或者從磁盤讀取數據的時候
    2.IO:磁盤I/O瓶頸發生在狀圖數據遠遠大於內存容量的時候
    3.服務器硬件的性能瓶頸:使用top,free,iostat和vmstat來查看系統的性能狀態
    
Explain:
    使用EXPLAIN關鍵字可以模擬mysql優化器執行sql查詢語句,從而知道Mysql是如何處理你的sql語句的,
    分析你的查詢語句或者表結構的性能瓶頸
    1.使用
     explain +sql語句;
     如原來:select * from user;
     現:explain select * from user;
   2.功能:
       1.表的讀取順序
       2.數據讀取操作的操作類型
       3.哪些索引可以使用
       4.哪些所以被實際使用
       5.表之間的引用
       6.每張表有多少行可以被優化器查詢

網卡索引號什麼時候用_表名_05

explain查詢出的字段解釋:
    1.id
        select查詢的序列號,包含一組數字,表示查詢中執行select子句或者操作表的順序
        三種情況:
            1.id相同:執行順序由上而下
            2.id不同,如果是子查詢,id的序號會遞增,id值越大優先級越高,越先被執行
            3.id如果相同,可以認為是一組,從上而下順序執行
              在所有組中,id值越大,優先級越高,越先執行

網卡索引號什麼時候用_表名_06

網卡索引號什麼時候用_表名_07

網卡索引號什麼時候用_字段_08

2.第二個字段:select_type
    有以下幾種可能:
    1.SIMPLE:簡單的select查詢,查詢中不包含子查詢或者UNION
    2.PRIMARY:查詢中若包含任何複雜的子部分,最外層查詢會被標記為PRIMARY
    3.SUBQUERY:在select或者WHERE列表中包含了子查詢
    4.DERIVED:在FROM列表中包含了子查詢會別標記為DERIVED(衍生),MYSQL會遞歸執行這些子查詢,把結果放在臨時表中
    5.UNION:若第二個select初始在UNION之後,則會被標記為UNION,若UNION包含在FROM子句的子查詢中,外層select會被標記為:DERIVED
    6.UNION RESULT:從UNION表獲取結果的select
    
3.type字段:
    有以下幾種可能:
    1.ALL
    2.index
    3.range
    4.ref
    5.eq_ref
    6.const,system
    7.NULL
    從最好到最差的依次是:
        system>const>eq_ref>ref>range>index>ALL
    一般來説,得保障查詢至少達到range級別,最好可以達到ref級別
    1.system:表中只有一行記錄(等於系統表),這是const(常量)類型的特列,平時不會出現,這個也可以忽略
    
    2.const:表示通過索引依次就可以找到,const用於比較primary kye或者unique索引,因為值匹配一行數據,所以很快
             如將主見置於where列表中,mysql就能將該查詢轉換為一個常量
             
    3.eq_ref:唯一性索引掃描,對於每個索引鍵,表中只有一條記錄與之匹配,常見於主見或者唯一索引掃描.
    
    4.ref:非唯一性索引掃描,返回匹配某個單獨值的所有行,本質上也是一種索引訪問,它返回所有匹配某個單獨值的行,然而
           它可能會找到多個符合條件的行,所以它應該屬於查找和掃描的混合體
           
    5.range:只檢索給定範圍的行,使用一個索引來選擇行,key列顯示使用了哪個索引
             一般就是在你的where語句中出現了between,<,>,in等的查詢
             這種範圍掃描索引比全表掃描要好,因為它只需要開始於索引的某一點,結束於另外一個點,不用掃描全部索引 
             
    6.index:Full Index Scan,index和all區別為index類型只遍歷索引樹,這通常比all快,因為索引文件通常比數據文件小
             也就是説孫然all和index都是讀全表,但是index是從索引中讀取的,而all是從硬盤中讀取的 
             
     7.all:full table sacn,將遍歷全表以找到匹配的行
     備註:一般來説要保障查詢至少達到range級別,最好能達到ref
     

4.possible_keys:顯示可能應用在這張表中的索引,一個或者多個
                查詢涉及到的字段上若存在索引,則該索引將被列出,但不一定被查詢實際使用

5.key:實際使用的索引,如果為null,則沒有使用索引
       查詢中若使用了覆蓋索引,則該索引僅出現在key列表中 
       
6.key_len:表示索引中使用的字節數,可以通過該列計算查詢中使用的索引長度,在不損失精確性的情況下,長度越短越好
           key_len顯示的值為索引字段的最大可能長度,並非實際使用長度,即key_len是根據表定義獲得的,不是通過表內檢索出的 
           
7.ref:顯示索引的哪一列被使用了,如果可能的話,是一個常數,哪些列或者常量被用於查找索引列上的值


8.rows:根據表統計信息及索引選用情況,大致估算出找到所需記錄索要讀取的行數(理論上越小越好)


9.extra:包含不適合在其他列展示但是十分重要的額外信息
    分類可以分為:
        (重要)1.Using filesort:説明mysql會對數據使用一個外部的索引排序,而不是按照表內的索引順序進行讀取
                          Mysql中無法利用索引完成的排序操作稱之為"文件排序"  
        (重要)2.Using temporary:使用臨時表保存中間結果,MySQL在對查詢結果排序時使用臨時表。常見於order by和分組查詢group by
        (重要)3.Using index:表示相應的select操作中使用了覆蓋索引(Covering index),避免訪問了表的數據行,效率不錯!
                      如果同時出現了using where,表名索引別用來執行索引鍵值的查找
                      如果沒有同時出現using where,表名索引用來讀取數據而非執行查找動作
                  覆蓋索引:
                      就是select的數據列只用從索引中就能獲取到,不必讀取數據行,mysql可以利用索引返回select列表中的字段
                      而不必根據索引再次讀取數據文件,換句話説查詢類要被所建的索引覆蓋
                      如創建一個複合索引:
                           CREATE INDEX 索引名稱 ON 表名 (字段1,字段1)
                           select 字段1,字段2 from 表名;
                       此時按照複合索引的字段和順序進行查找,就不會再次讀取數據文件,而是利用索引獲取返回select列表中的字段
                   注意:
                       1.如果要使用覆蓋索引,一定要注意select列表中只能取出需要的列(並且列要在複合索引內)   ,不能select *
                       2.因為如果將所有字段一起做索引會導致索引文件過大,查詢性能下降!
       4.Using where:表明使用了where條件
       5.using join buffer:使用了連接緩存
       6.impossible where:where字句的值總是fasle,不能來獲取任何元組
       7.select tables optimized away:在沒有group by子句的情況下,基於索引優化MIN/MX操作或者對於MyISAM
                                       存儲引擎優化count(*)操作,不必等到執行階段再去計算
                                       查詢執行計劃生成的階段即完成優化
       8.distinct:優化distinct操作,找到第一個匹配元組後即停止趙同樣值的操作

網卡索引號什麼時候用_字段_09

索引優化

創建一張person表,只給主鍵創建了索引


網卡索引號什麼時候用_字段_10

查詢序號>2養狗的最小人的性命和年齡
explain select name,age from person t where t.pet='dog' and t.order > 2 order by t.birth desc limit 1;

網卡索引號什麼時候用_表名_11

聯合索引(複合索引)創建面試:
1.https://www.cnblogs.com/rjzheng/p/12557314.html
2.https://www.cnblogs.com/rjzheng/category/1281020.html

雙表索引

1.左連接
    select * from 左表  left join 右表 on 左表.關聯字段=右表.關聯字段;
    實質上是查詢出右表符合條件的記錄(一條具體記錄),循環左表進行遍歷,索引對遍歷操作沒有什麼實質性幫助,主要幫助是排序,
    結論:所以給右表加索引

2.右關聯
    select * from 左表  right join 右表 on 左表.關聯字段=右表.關聯字段;
    左表驅動右表,即查詢出左表的記錄去遍歷右表
    結論:給左表字段加索引
    
join語句的優化:
    1.儘可能減少jon語句中的循環總次數,"永遠使用小結果集驅動大的結果集"
    2.優先優化嵌套的內層循環
    3.保證join語句彙總被驅動表上join條件字段已經被索引
    4.當無法保證被驅動表的join條件字段被索引且內存資源充足的前提下,不要吝嗇JoinBuffer的設置