MySQL高級部分筆記

 

有關於MySQL的高級部分筆記


這是一篇關於MySQL高級部分的筆記主要是,sql優化以及mysql鎖的相關內容,以及主從配置等內容等比較基礎的優化mysql

1、邏輯架構部分

  1. 邏輯架構ios

    邏輯架構介紹圖以下sql

      

  • 鏈接層:最上層是一些客戶端和鏈接服務,包含本地的sock通信大多時基於客戶端/服務端工具實現的相似於tcp/ip的通信數據庫

  • 服務層:完成大多數的核心服務的功能,如,SQL接口,並完成緩存的查詢SQL的分析和優化以及部份內置函數的執行,全部款存儲引擎的功能api

  • 引擎層:存儲引擎真正的負責了MySQL中的數據的存儲和提取,服務器經過api與存儲引擎進行通信,經常使用的有MyISAM和InnoDB緩存

  • 存儲層:數據存儲在裸設備上,並完成與存儲引擎的交互服務器

     

    優化主要是隻使SQL的解析格式符合優化器的優化格式數據結構

  1. 存儲引擎架構

    查看mysql的存儲引擎命令併發

    # 看你的mysql提供了生麼存儲引擎
    show engines;
    # 看當前默認的存儲引擎
    show variables like '%storage_engine%';

    MyISAM與InnoDB的對好比下表

    對比項 MyISAM InnoDB
    主外鍵 不支持 支持
    事務 不支持 支持
    行表鎖 表鎖,即便操做一條記錄也會鎖住整個表,不適合高併發的操做 行鎖,操做時只鎖某一行,不對其餘的行有影響,適合高併發的操做
    緩存 只緩存索引不緩存真實數據 不只緩存索引還要緩存真實數據,對內存的要求比較高,並且內存的大小對性能有決定性的影響
    表空間
    關注點 性能 事務
    默認安裝 Y Y
  2. 性能降低SQL慢的緣由

    • 查詢語句寫的爛

    • 索引失效

      • 單值索引

      • 符合索引

    • 關聯查詢太多join(設計缺陷)

    • 服務器調優及各個參數的設置(緩衝、線程數等)

  3. SQL執行加載的順序

    • 手寫順序

      select distinct
      <select_list>
      from
      <left_table> <join_type>
      join <right_tablr> on <join_condition>
      where
      <where_condition>
      group by
      <group_by_list>
      having
      <having_condition>
      order by
      <order_by_condition>
      limit <limit_number>

       

    • MySQL的執行

      from <left_table>
      on <join_condition> <join_type>
      join <right_table>
      where <where_condition>
      group by <group_by_list>
      having <having_condition>
      select
      distinct <select_list>
      order by <order_by_condition>
      limit <limit_number>

      總結

2、索引及優化部分

  1. 索引簡介

    • 是什麼

      索引是幫助MySQL高效獲取數據的數據結構,本質上是數據結構(查找+排序)

    • 種類

      B+樹索引

      hash索引

      全文索引

      RTree索引

    • 優點

      提升數據的檢索效率下降的磁盤的io

      下降數據的排序成本下降了cpu的消耗

    • 劣勢

      實際上索引也是一張表,保存主鍵與索引字段,指向實體表的記錄,也是要佔用空間的

      會下降對於insert,update,delete的速度

      索引只是提升效率的一個因素

    • 分類

      • 單值索引:一個索引只包含一個列

      • 惟一索引:索引的列必須惟一,能夠有空值

      • 複合索引:一個索引包含多個列

      • 基本語法

        # 建立 
        create [unique] index indexName on table(columnname(length));
        alter tablename add [unique] index indexname on (columnname(length));
        # 刪除
        drop index [indexname] on tablename;
        # 查看
        show index from tablename\G
    • 哪些狀況適合建索引

      1. 主鍵自動創建惟一索引

      2. 頻繁做爲查詢條件的字段

      3. 查詢中與其餘表關聯的字段,外鍵關係創建索引

      4. 頻繁更新的字段不適合創建索引

      5. where用不到的字段不建立索引

      6. 單鍵/組合索引的選擇問題(高併發下傾向於建立複合索引)

      7. 查詢中排序的字段排序字段經過索引訪問將大大提升訪問的速度

      8. 查詢中統計和分組的字段

    • 哪些狀況不適合建索引

      1. 表記錄太少

      2. 頻繁修改的字段

      3. 數據重複且分佈平均的字段

    • 性能分析

      MySQL Query Optimizer 查詢優化器

      負責對select語句進行優化

      性能瓶頸

      cpu:cpu飽和的時候通常發生在數據裝入內存或者從磁盤上讀取數據的時候

      io:裝入數據元大於內存容量的時候

      服務器硬件:top,free,iostat,vmstat命令查看系統的性能狀態

3、Explain 執行計劃

  • 是什麼

    使用explain關鍵字能夠模擬優化器執行sql查詢語句,從而知道,MySQL是如何處理你的sql語句的分析你的查詢語句或是表結構的性能瓶頸

  • 怎麼用

    explain + sql

    執行計劃包含的信息

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
                       
  • 字段解釋

id

id:select查詢的序列號,包含一組數字表示查詢中執行select子句或操做表的順序

三種狀況:id相同執行順序由上至下

id不一樣若是是子查詢,id的序號會遞增,id越大優先級越高,越先被執行

id相同又不一樣會遵循上兩條規律

select_type

select_type: 查詢的類型主要是用於區別,普通查詢,聯合查詢,子查詢等複雜查詢

simple:簡單查詢不包含子查詢,或者union

primary:主查詢子查詢最外層的查詢

subquery:子查詢

derived:在from列表中包含的子查詢被標記爲dervied衍生,MySQL會遞歸執行這些子查詢,把最終結果放在臨時表裏

union:第二個select出如今union以後則被標記爲union,若union包含在from子句中,外層的select將被標記爲derived

union result:從union表中獲取結果的select

table 顯示這一行數據是關於那一張表的

type

常見的訪問類型八種

all index range ref eq_ref const,system null
全表掃描 全索引掃描比all好 檢索指定範圍的行 非惟一性索引掃描,多條記錄匹配 惟一性索引掃描,表中只有一條記錄匹配常見於主鍵索引惟一索引 system表只有一行記錄 const表示經過索引一次就找到了覺得只匹配一行數據 如將主鍵置於where列表中,MySQL就能將查詢轉化爲const  

最好到最差

system > const > eq_ref > ref > range > index > all

通常來講得保證查詢至少優化到range最好到ref

prossiable_keys和key

prossiable_keys:顯示出在本次查詢中可能用到的索引,可是不必定用

keys:實際查詢的過程當中實際使用的索引爲null沒有使用索引,若查詢中使用覆蓋索引則在該索引僅出如今key列表中

key_len

索引字段的最大可能長度,並不是實際長度,再不損失精確性的狀況下越小越好

ref

顯示索引的那一列被使用了,若是可能的話儘可能是個常數

rows

找到所需的記錄讀取的行數

extra

很重要的額外信息

using filesort:使用文件內排序(壞)

using temporary:使用臨時文件(壞)

using index:使用索引(好)

using where:使用where

4、優化的幾點建議

  1. 全值匹配

  2. 最佳左前綴法則

  3. 不在索引列上作任何的操做(計算,函數,(自動or手動的類型轉換)),會致使索引失效而全表掃描

  4. 存儲引擎不能使用索引中範圍條件右邊的列

  5. 儘可能使用覆蓋索引只訪問索引的查詢(索引列與查詢列一致),減小select *

  6. mysql在使用不等於(!= 或 <>)的時候沒法使用索引回單之全表掃描

  7. is null ,is not null 也沒法使用索引

  8. like以通配符開頭會致使索引失效全表掃描

  9. 字符串不單引號索引失效

  10. 少用or用來鏈接時會使索引失效

  11. 永遠小表驅動大表

  12. group by/order by排序字段也會用到索引(左前綴,儘可能使用where)

 

5、查詢截取分析

  1. 慢查詢日誌截取慢sql

    # 查看
    show variables like '%slow_query_log%';
    # 開啓
    set global slow_query_log=1
    # 查看記錄sql的閾值時間
    show variables like 'long_query_time%';
    # 設置閾值時間
    set global long_query_time=3;

     

  2. show profile

    # 查看是否支持
    show variables like 'profiling'
    # 開啓
    set profiling=on

    # 查看結果
    show profiles;
    show profile cpu,block io from query [問題sql的query_id];

6、MySQL鎖機制

  • 概念

    鎖是計算機協調鎖個進程或者線程併發訪問某一資源的機制

  • 分類

    讀鎖/寫鎖

    • 讀鎖:共享鎖

    • 寫鎖:排它鎖

    表鎖/行鎖

    • 表鎖:鎖整張表(偏讀,偏向MyISAM存儲引擎,開銷小,加鎖快,無死鎖,鎖定的粒度大,大,發生鎖衝突的機率高,併發度低)

    • 行鎖:鎖一行(偏寫,偏向InnoDB存儲引擎,開銷大,加鎖慢會出現死鎖,鎖定的粒度小,發生鎖衝突的機率最低,併發度也高)

    • 事務及ACID屬性

      事務是由一組SQL語句組成的邏輯處理單元,事物具備如下四個屬性

      • 原子性(Atomicity):事務是一個原子性的操做單元,其對數據的修改,要麼全都執行,要麼全都不執行

      • 一致性(Consistent):在事務開始和完成時,數據都必須保持一致的狀態,這意味着,全部相關的數據規則都必須應用於事務的修改,以保持數據的完整性,十五屆數值,全部的內部數據(如b樹索引或雙向鏈表)也都必須是正確的

      • 隔離性(Isolation):數據庫系統提供必定的隔離機制,保證十五在不收外部併發操做的影響的「獨立」環境執行,這意味着事務處理過程當中的中間狀態對外部是不可見的,反之亦然

      • 持久性(Durable):事務完成以後,它對數據的修改是永久性的,即便出現系統故障也可以保持

      併發處理帶來的問題

      • 更新丟失:相似於版本覆蓋

      • 髒讀:讀到已修改還沒有提交的數據

      • 不可重複讀:兩次讀的不同

      • 幻讀:事務a讀到了事務b提交新增的數據不符合隔離性

      數據庫的事務隔離級別

      數據庫的隔離級別 數據一致性 髒讀 不可重複讀 幻讀
      讀未提交 最低級別,只能保證不讀物理損壞的數據 Y Y Y
      讀已提交 語句級 N Y Y
      可重複讀 事務級 N N Y
      可序列化 最高級別,事務級 N N N
      # 查看數據庫的隔離級別 MySQL默認爲可重複讀
      show variables like 'tx_isolation';
      # 鎖定一行
      begin;

      sql+for update;

      commit;

       

    # 建表
    create table mylock(
    id int not null primary key auto_increment,
    name varchar(20)
    ) engine myisam;
    # 插入數據
    insert into mylock(name) values('a'),('b'),('c'),('d'),('e');

    select * from mylock;

    # 手動增長表鎖
    lock table 表名1 read,表名2 write;

    # 查看錶的加鎖狀態
    show open tables;

    # 解鎖
    unlock tables;
相關文章
相關標籤/搜索