高性能MySql讀書筆記

以下是Xmind筆記,看着有些費勁。。。記錄下

高性能Mysql
    mysql架構和基礎
        mysql邏輯架構圖
            客戶端
            服務器層
                連接/線程處理、查詢緩存、解析器、優化器
            存儲引擎
        鎖粒度
            表鎖:服務器會爲諸如 alter Table之類語句使用表鎖,而忽略存儲引擎的鎖機制
            行級鎖:只在存儲引擎層,不在服務器層
        事務
            ACID
                atomicity 原子性
                consistency 一致性
                isolation 隔離性
                durability 持久性
            隔離級別
                Read uncommitted
                Read  committed
                Repeatable read  (mysql默認)
                Serializable 可串行化
            死鎖
                InnoDB 處理方法:將持有最少行級排它鎖的事務進行回滾
            服務器層不管理事務,是由下層的存儲引擎實現的。  最好不要在事務中混合使用存儲引擎(InnoDB-事務型、MyIsAM-非事務型)
        MVCC 多版本併發控制
            在每條記錄後保留2條隱藏的列:行版本號、行刪除版本號。每開始一個事務,系統版本號自動遞增。Select:只查 【 行版本號<=當前系統版本號 && 行刪除版本要麼未定義,要麼大於當前系統版本號--確保未被刪除】。
        存儲引擎
            InnoDB (mysql默認)
                事務型、高併發  間隙鎖、聚簇索引、熱備份
            MyIsAM
                不支持事務(沒有回滾)、不支持行級鎖、不支持崩潰後的安全恢復
                對整張表加鎖
                對於只讀數據可以考慮
        導入導出
            Create table a Like b; Insert into a  Select * from b;
    Schema與數據類型優化
        數據類型
            整數類型: -2^(N-1)到2^(N-1)-1.  Unsigned。INT(11) 指定寬度,只是規定了交互工具(mysql命令行客戶端)來顯示字符的個數,值的合法範圍,比如INT(1)和INT(20)是相同
            實數類型:DECIMAL ,數據量大時也可以用BIGINT代替
            字符串類型
                VARCHAR 可變長字符串、CHAR 定長,括號裏的是字符數
                ENUM 枚舉代替字符串類型
            日期和時間類型:TIMESTAMP(1970年-2038年) 效率更高、DATATIME(1001年-9999年)
            IPv4地址:32位無符號整數,不是字符串
        範式和反範式
            第一範式:無重複的列
            第二範式:屬性完全依賴於主鍵
            第三範式:屬性不依賴於其他表的非主鍵
            反範式可以避免表關聯,所以一般是 混用範式和反範式
        緩存表與彙總表
            緩存表:存儲從其他表獲取速度慢的信息,例如 邏輯上冗餘的數據
            彙總表:保存 Group By語句聚合數據,例如 邏輯上不冗餘的數據
        總結
            一切爲了  更快地讀,更慢地寫
            儘量使用可以正確存儲數據的最小數據類型
            儘量 NOT NULL
    索引
        索引類型
            BTREE,InnoDB使用B+Tree,通過比較節點頁的值和要查找的值找到合適的指針進入下層子節點(二分查找),有序的
            哈希索引:對索引列計算一個哈希碼
                InnoDB有 自定義哈希索引:當注意到某些索引列被使用得非常頻繁時,它會在內存中基於BTree索引之上再創建一個哈希索引,自動的內部行爲
                創建自定義哈希索引
                    新增一個被索引的url_crc 列
                    Select id From url Where url_crc=CRC32("http://myslq.com")  And url="http://myslq.com";
                無法排序、不支持部分索引列匹配查找、不支持範圍查詢
        索引策略
            獨立的列:索引列不能是表達式的一部分,也不能是函數的參數
            前綴索引
                索引開始的部分字符,提高索引效率。對於BLOB、Text、很長的VARCHAR,必須使用前綴索引
                索引的選擇性:不重複的索引值(基數)/數據表的記錄總數(#T),1/#T到1之間,例如 唯一索引的選擇性=1     --P154
                無法Order By 和Group By,無法覆蓋掃描
            多列索引
                在多個列上建立獨立的單列索引大部分情況下不能提高mysql的查詢性能
                Or  -> UNION ALL
                選擇合適的索引列順序:當不需要考慮排序和分組時,將選擇性最高的列放在前面通常是最好的
            聚簇索引 (InnoDB)
                數據存儲方式,表示數據行和相鄰的鍵值緊湊地存儲在一起。一般 一個表只能有一個聚簇索引
                葉子頁包含了行的全部數據,但是節點頁只包含了索引列
                缺點: 二級索引訪問需要倆次索引查找。 存儲引擎需要找到二級索引的葉子節點獲得對應的主鍵列,然後根據這個值取聚簇索引中查找到對應的行
                聚簇索引:主鍵索引,非聚簇索引:二級索引    --P167
            主鍵索引:Auto_Increment
                併發插入 可能導致間隙鎖競爭  ,innodb_autonic_lock_mode配置=0:鎖,保證ID連續; >=1: 性能提升,ID可能不連續
            覆蓋索引
                定義:一個索引包含所有需要查詢的字段的值
                由於InnoDB的聚簇索引,覆蓋索引對InnoDB表非常有用:若二級主鍵能覆蓋查詢,則可以避免對主鍵索引的二次查詢。
                延遲關聯:  P174、P187
                    Select name,sex From profiles Where sex='M' Order By rating Limit 100000,10
                    轉化爲 Select name,sex From profiles Inner Join( Select id From profiles where x.sex='M' Order By rating Limit 100000,10) As x  Using(id);
            索引掃描來做排序
                EXPLAIN出來的type列:"index"
                若索引不能覆蓋查詢所需的列,按索引順序讀取的速度通常要慢於順序全表掃描,因爲 每掃描一條索引都得回表查詢
                OrderBy 索引最左前綴
                查詢需要關聯多表,則只當OrderBy子句所引用的字段全部爲第一個表時,才能使索引用作排序
        總結
            BTree索引的限制
                最左前綴
                不能跳過索引的列
                若查詢中有某個列的範圍查詢,則其右邊所有列都無法使用索引優化查找
            mysql 不能在索引中執行LIKE操作
            只在索引中做最左前綴匹配的LIKE比較,若是通配符開頭的LIKE查詢,將無法匹配
            儘量擴展已有索引而不是創建新索引,但有時出於性能考慮需要冗餘索引
            id > 45  轉化爲  id IN (1,4,99) :範圍條件查詢,就無法使用範圍列後面的其他索引列,但是對於多個等值查詢就可以
    查詢性能優化
        慢查詢
            是否向數據庫請求了不需要的數據? LIMIT、只取需要的列
            是否在掃描額外的記錄? 
“Extra: Using Where”: Mysql將通過Where條件來篩選存儲引擎返回的記錄
                索引中使用where 是在存儲引擎層完成
                索引覆蓋掃描(Extra:Using index)直接從索引中過濾不需要的記錄並返回命中結果,無須再回表查詢,Mysql服務器層完成
                Using Where 需要先從數據表讀出記錄然後過濾,Mysql服務器層完成
        重構查詢方式
            大查詢分解成多個小查詢
            分解關聯查詢
                讓緩存的效率更高:關聯中的某個表變化,就無法使用查詢緩存,
拆分後,某個表很少變化可重複利用查詢緩存結果
        查詢的過程 -圖P204
            mysql客戶端/服務端通信協議
                半雙工,要麼服務器向客戶端發數據,要麼客戶端到服務器, 倆個動作不能同時發生
                庫函數實際是從緩存獲取數據
                查詢狀態   -P207
            查詢緩存
                查詢優化器
                    靜態優化:直接對解析樹分析優化,第一次完成後一直有效,編譯時優化
                        Or -> IN()先對列表內數據排序,再二分查找,O(log N)優於O(N)
                    動態優化
                關聯查詢 :嵌套循環關聯
                    先在一個表循環取出單條數據,再嵌套循環到下一個表尋找匹配的行,直到找到所有表的匹配的行爲止,然後回溯到上一個表
                    關聯查詢優化器 評估不同順序的成本來選一個代價最小的關聯順序
                排序優化 不能用索引生成排序結果時,需自己排序(filesort)
                    倆次傳輸排序 , I/O成本高
                    單次傳輸排序,當查詢需要所有列的總長度不超過參數
max_length_for_sort_data ,Mysql使用此排序算法。
            查詢執行引擎
                逐步執行計劃
            返回結果給客戶端
                增量、逐步返回的過程
        查詢優化器的侷限性
            糟糕:Where條件中包含IN()的子查詢語句
                Select * From film Where film_id IN(
Select film_id From film_actor Where actor_id = 1)
                轉化爲 
 Select film.* From film inner Join film_actor Using(film_id) Where actor_id = 1
            UNION
                Union的各個子句中分別使用這些 Order By、Limit
        優化特定類型查詢
            Count
                count(列值):不統計列值NULL
                最好用Count(*)
            優化關聯查詢
                確保Group By和Order By只涉及到一個表中的列,這樣索引纔可以優化
            優化子查詢
                儘量用關聯查詢代替
            優化Limit 分頁
                延遲關聯 -見上一章
            優化UNION查詢
                創建並填充臨時表來執行Union查詢; 儘量用Union All,否則會對整個臨時表做唯一性檢查,代價高
            使用用戶自定義變量
                Set @rownum := 0; 
Select id,@rownum := @rownum + 1 AS rownum From actor
        總結
            分組查詢:若可以,在應用程序中做超級聚合更好
            快速地完成事情:儘量使用Update 代替先Select For Update再Update的寫法,因爲事務提交的越快,持有鎖的時間越短
            儘量少做事:看是否真的需要這麼精確的計算,可以運用簡單的方案過濾大多數數據
    高級特性
        分區表  (粗粒度)
            定義:是一個獨立的邏輯表,但是底層由多個物理子表組成。底層表必須相同存儲引擎
            CREATE TABLE sales(
    order_date DATETIME NOT NULL,
    -- other columns omitted
)ENGIN=InnoDB PARTITION BY RANG(Year(order_date))(
    PARTITION p_2010 values less than (2010),
    PARTITION p_2010 values less than (2010),
    PARTITION p_2010 values less than (2010),
    PARTITION p_catchall values less than MAXVALUE );,
                表達式返回的值是一個確定的整數,且不能是常數
            策略
                全量掃描數據,不要任何索引(根據分區的規則大致定位需要的數據位置)
                索引數據,並分離熱點  (數據有明顯的熱點,可以單獨放一個分區)
            可能的問題
                Null值會使分區過濾無效
                    PARTITION BY RANGE COLUMNS(order_date)  
--直接使用列本身而不是基於列的函數,mysql5.5版本
                儘量分區列和索引列匹配
                限制分區的數量,一般最多100個左右分區
            總結
                要做Where條件帶入分區列!!!
                根據粗粒度索引優勢,通過分區過濾通常可以讓查詢掃描更少的數據。
        視圖
            本身是一個虛擬表,不存放任何數據,返回的數據是從其他表中生成的
            CREATE VIEW Oceania AS 
    Select * from country where continent = 'Oceania'
    With CHECK OPTION;
            合併算法、臨時表算法(包含Group By、Distinct、聚合函數、Union、子查詢)
            不支持在視圖上建觸發器
            只有合併算法的視圖 纔可更新。
(update Oceania Set population = popluation * 1.1 Where Name='Australia')
        存儲過程
            適用於:   相比查詢執行的成本,解析和網絡開銷很明顯
        觸發器
            每個表的每個事件,最多隻能定義一個觸發器
            基於行的觸發
            作用: 實現更新反範式化數據、記錄數據變更日誌、系統維護任務、約束
        事件
            指定mysql 在某個時候執行一段代碼,或者每隔一段時間間隔執行一段代碼
        綁定變量
            SET @sql := 'Select id,first_name  FROM actor where first_name=?';
            客戶端向服務器發送一個 sql 語句原型,服務器解析並存儲這個 sql 部分執行計劃,返回客戶端處理句柄。以後每次執行這類查詢,客戶端都指定使用這個句柄。
        字符集和校對規則
            一種從二進制編碼到字符的映射;  校對: 用於字符集的排序規則
            服務器 -> 數據庫 -> 表,這是一個逐級繼承的默認設置,最靠底層的默認設置影響
            大小寫敏感:_cs  、_ci (case sensitive;  case insensitive);
 字符串編碼的二進制:_bin
                col2 CHAR(1) CHARSET utf8,
col3 CHAR(1) COLLATE latin1_bin
            只有排序查詢要求的字符集與服務器數據的字符集相同的時候,才能使用索引進行排序
        全文索引 (B-Tree)
            通過關鍵字匹配來進行查詢過濾,基於相似度的查詢
            只有MyISAM 支持全文索引,msql5.6版本後,InnoDB 也支持了
            自然語言的全文索引
                在整個索引中出現次數越少的詞語,匹配時的相關度就越高
                SELECT film_id,title, RIGHT(description,25)
From film_text
Where MATCH(title,description)   AGAINST('factory casu');
                自動按照相似度進行排序
            布爾全文索引
                SELECT film_id,title, RIGHT(description,25)
From film_text
Where MATCH(title,description)   AGAINST('+factory  +casu'  IN  BOOLEAN MODE);
                只有MyISAM 引擎才能使用
        查詢緩存
            定義:緩存完整的select 查詢結果
            默認應該關閉查詢緩存;
若實在查詢緩存作用很大,也要配置很小的查詢緩存空間(幾十兆)
            若查詢語句包含任何不確定的函數,那麼查詢緩存不能找到緩存結果。如:current_date
            命中和寫入的比率,Qcache_hits/Qcache_inserts >3:1  通常查詢緩存是有效的;即緩存帶來的資源節約大於其本身的資源消耗;
            Flush query cache: 碎片管理。小心用,因爲無法訪問查詢緩存,服務器會僵死一段時間。
            query_cache_size  設置成0, 來關閉查詢緩存。
            總結:
                對於寫密集型應用,直接禁用  可以提高系統性能

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章