MySQL常見注意事項及優化

MySQL常見注意事項

  1. 模糊查詢 like 默認是對name字段創建了索引

    注意:在使用模糊查詢的時候,當% 在第一個字母的位置的時候,這個時候索引是沒法被使用的。可是% 在其餘的位置的時候,索引是能夠被使用的。 php

     

    # select * from tableName where name like "%zhangsan"; ?可使用到索引啊? 不能夠。 mysql

    分析:由於是不肯定查詢,在表中任何一行記錄都有可能知足查詢條件。 sql

     

    #select * from tableName where name like "zh%"; 可使用嗎? 能夠 數組

    #select * from tableName where name like "zh%三"; 可使用嗎? 能夠 緩存

    # select * from tableName where name like "z%san"; ? 可使用嗎?能夠,首先能夠快速定位z字母開頭的部分。讀z字母這段範圍以內只能逐行比較。 服務器

     

  2. 查詢的列不要使用 函數或者 運算。不然索引沒法使用。

    # select * from tableName where id+1 = 1000; 架構

    # select * from tableName where id = 999; 等價。 函數

     

     

    有的時候,會在查詢字段上面使用函數。使用函數的時候也是沒法使用全部的,通常的解決方案是將查詢後的結果交給php程序(字符串 和 數組)來實現處理。不要把函數的處理放在MySQL裏面完成。 工具

     

  3. 在你開發之中,什麼樣的字段適合創建索引?簡述爲何?

    答: 測試

  4. 在where後面做爲查詢條件的字段是適合創建索引的。
    1. 注意:對於惟一不好的字段不適合創建索引,例如 只有 這兩種狀況的字段。
  5. 在須要排序的字段上面,也能夠創建索引。

     

    執行order by 不加限定,全表掃描,filesort含義 注意:問題?

     

  6. MySQL優化的一個通用方案?

    答:

  7. 開啓MySQL的慢查詢記錄功能,讓系統運行一段時間(測試時間 都是在半個月到一個月時間)
  8. 檢查慢查詢的日誌信息,分析出可能有問題的sql語句
  9. 使用profile工具詳細去分析sql語句執行的時候,每一個步驟所花費的時間,sending data(可能出現的問題 是MySQL沒有使用索引的狀況下,會去磁盤上獲取數據:經驗)
  10. 對sql語句優化(自己寫出來的sql語句就存在問題,例如對查詢的字段使用了函數)或者對錶的結構(表中有些查詢字段沒有創建索引)適當的作一些調整(索引重建或者創建的更合適)
  11. 使用explain工具分析一下這些sql語句在執行的時候,是如何執行(可能使用索引或者是使用那些索引)
    1. type: const \ index \ 出現這些 表明索引正常使用
  12. 反覆上面的過程具體分析。

     

  13. MySQL的 自身緩存

    解釋:MySQL的客戶端在發送sql語句到MySQL服務器端以後,會先去檢查一下權限,以後去查詢該條sql語句的緩存信息是否存在,若是存在,則直接返回;若是不存在,MySQL服務器須要去分析該sql語句,作詞法語法分析,而後編譯,生產執行樹,去磁盤上獲取數據,獲取數據後,緩存到自身的一個緩存容器裏面,而後在返回數據。

     

    使用:

    # show variables like "%cache%";

    更改MySQL緩存的大小(32M),注意 單位是 B(字節)

    # set global query_cache_size = 1024*1024*32;

    注意:第一個是要加關鍵字 global 第二個是大小的單位爲 B(字節) 第三具體給多少合適,取決於自身操做系統的內存大小。

    測試對比:

     

    注意:MySQL自身的緩存須要注意兩點:

  14. MySQL的sql語句裏面不能出現 不肯定信息(例如在條件裏面使用 now()函數),MySQL的自身緩存將沒法被使用。查詢的結構不會被緩存起來。

    分析:

     

  15. MySQL的自身的緩存是嚴格基於 sql 語句的(MySQL自身緩存是嚴格區分sql語句的大小寫的) select === SELECT 關鍵字 實際上是同樣的

     

     

  16. MySQL的架構分析( 讀寫分離

    因爲一個網站業務中 70%的業務基本都是讀操做,剩下的都是寫操做。因此這個時候對讀的壓力過大,須要使用必定的方式來減小壓力,這個時候可使用讀寫分離這種架構來實現壓力的分擔。

    怎麼查詢是讀爲主?

    # show status like "%Com_%";

    經過上面的分析一段時間,就能夠大體計算出網站的讀寫狀況

     

    # show status ; 能夠查看MySQL的一個狀態信息。

     

     

     

    讀寫分離概圖:

    mysql-proxy這個工具能夠實現對sql語句的分析,判斷sql語句是讀操做(select關鍵字) 仍是 寫操做(insert、update、delete)。最後去鏈接不一樣的服務器實現業務的完成。

    當完成讀的時候,MySQL-proxy會從對臺讀服務器按照必定策略去選擇一臺(輪詢、加權、ip_hash)完成讀操做

    當完成寫的時候,直接去鏈接寫的服務器

     

    問題:

    因爲數據只在主服務器上實現寫操做,可是從服務器上是沒有完成寫操做的,這個時候數據就會不一致。

    須要解決一致性的問題?

    答:可使用MySQL的一個bin日誌來完成數據的一致性問題。

     

    使用步驟:

    主服務器配置:

  17. 先在主服務器上開啓bin日誌(bin日誌是MySQL的一個二進制日誌功能,能夠記錄對 MySQL數據形成 更改的sql語句,造成一個日誌文件)
  18. 在主服務器上的配置文件裏面定義一個 server_id = Number 至關於標示一下這個服務器
  19. 在主服務器上添加一個 受權帳號用來到時候獲取bin日誌。

     

    從服務器配置:

  20. 開啓從服務器的一個 中繼日誌,這個日誌主要是把主服務器bin日誌讀取以後(沒法直接使用,須要先轉換爲中繼日誌),造成轉換。
  21. 在從服務器上的配置文件定義一個 server_id =Number 不要和主服務器重複
  22. 使用主服務器的 受權帳號去連接主服務器獲取bin日誌,而後讀取到本地,造成中級日誌,而後在本地的MySQL執行一遍,達到和主服務器上數據文件一致。
  23. 啓動從服務器的主從複製功能。

     

    總結:主從複製是完成讀寫分離的一個基礎。(稍微有點延時)

     

    優化技術

    索引覆蓋

    對於MyISAM的存儲引擎來講,若是查詢的字段信息正好在索引文件裏面出現,這個時候不須要作回行的操做,直接能夠從索引文件裏面返回的現象就叫作索引覆蓋。(索引正好覆蓋了查詢的字段)

     

    應用:在大數據(百萬數據)下的一個翻頁效果

    技術點:翻頁是如何作的?

    答:select * from tableName limit offset,page;

    比如如今是N頁,每頁顯示page條

    offset = (N-1) * page

     

    實際使用:

    分頁操做

    當很大頁碼的時候

     

    經過上面的對比發現,MySQL在使用limit分頁的時候,在頁碼足夠大的狀況下,效率是很低的,爲何?

    答:主要緣由是,MySQL在使用limit作查詢的時候,以下sql:

    select * from tableName limit offset,page;

    執行過程:

    先取出 offset+page 條記錄, 而後在丟棄 offset 條記錄 ,返回 page 條記錄。

    因此有必要對這種狀況作優化操做:

     

  24. 從業務上完成(限制用戶的行爲,不容許翻頁超過規定的頁碼)

    百度限制用戶行爲:

     

  25. 不從限制用戶的行爲上去考慮, 可使用索引來實現
    1. select * from tableName where id > Number limit page;

    當分頁頁碼變大的狀況下:

    經過使用 where id > Number limit 10; 這樣因爲可使用上id的主鍵索引,因此能夠快速的定位,達到一個大數據的分頁的效果。

     

     

    問題:

    a. select * from tableName where id > Number limit page;

    b. select * from tableName limit Number, page;

     

    當上面的這兩條sql語句執行後,結果在何時徹底一致,何時不一致?

    答:當數據沒有被物理行刪除的時候。這個時候數據是一致的,可是有物理行刪除的時候,數據是不一致的。

    如何解決上面的問題?

    答:既然是物理行刪除形成的,那就不作物理行的刪除,只作邏輯刪除(設置一個is_delete 字段 0 表明沒有刪除 1 表明已經刪除)。

    使用邏輯刪除以後,數據會一致,只要在數據顯示的,在顯示層面(HTML)讓is_delete=1 不顯示出來便可。if( is_delete == 1) echo '該條信息已被刪除!' 例如:常見的百度貼吧,網易新聞端。

     

    3. 實現物理行刪除,不限制用戶行爲

    答:這個時候可使用 索引覆蓋 + 延時關聯技巧 來實現。

    分析:

    程序代碼實現:

    在php層面實現        

  26. 因爲主鍵id是能夠快速查找,先查出知足條件id

     

  27. 而後根據id快速的去查找對應的記錄

    foreach($data as $k=>$v){

    $sql = select * from tableName where id = $v;

    $res = mysql_query($sql);

    $row = mysql_fetch_assoc($res);

    $result[]= $row;

    }

    $result //分頁數據

     

    在MySQL層面聯表處理:

    使用聯表來完成大數據的分頁操做

     

    解釋

相關文章
相關標籤/搜索