高性能Mysql筆記 — 優化

性能優化

瞭解查詢的整個生命週期,清楚每一個階段的時間消耗狀況html

性能分析

慢查詢日誌——服務器性能分析

參考
慢查詢日誌是優化很重要的手段,可是開啓慢查詢日誌對性能的影響並不大,因此能夠考慮在線上打開慢查詢日誌mysql

  • 查看慢查詢是否打開、以及日誌存儲位置:show variables like '%slow%'
    統計當前數據庫鏈接狀態
    mysql -e 'show processlist \G' -uroot -proot | grep State | sort | uniq -c | sort -rn

剖析單條查詢

select @@profiling:查看profiling是否打開
set profiling=1:打開profiling
show profiles:查看每條查詢的性能
show profile for query id:查看query id的詳細時間花費
information_schema.profiling:該表存儲了每一個query的詳細時間花費
show status:查看會話級別的計數器
show global status:查看全局的計數器
show status where variable_name like '%handler%':查看某些變量的計數sql

查詢性能優化

查詢由多個子任務組成,優化查詢也就是優化子任務數據庫

  1. 消除一些子任務
  2. 減小子任務執行次數
  3. 讓子任務執行更快

優化數據訪問

不要請求不須要的數據緩存

  1. 只返回必要的行(limit)、列(儘可能不要使用星號返回全部列)
  2. 儘可能不要查詢重複的數據,使用緩存

是否在掃描額外的記錄

mysql衡量查詢開銷的指標:性能優化

  1. 響應時間
  2. 掃描行數
  3. 返回的行數

訪問類型
explain語句中的type指明瞭訪問類型,包括:全表掃描,索引掃描,範圍掃描,惟一索引查詢,常數引用,從左到右掃描的行數從多到少,速度從慢到快
查詢語句中where條件的使用,性能從好到壞是:服務器

  1. 在索引中使用where條件過濾不匹配的記錄,這是在存儲引擎層完成的
  2. 使用覆蓋引擎(extra中出現using index)來返回記錄,直接從索引過濾不須要的記錄並返回結果,在在服務器層完成,不須要回表
  3. 在表中返回數據,使用where過濾不匹配的記錄(extra中出現using where),在服務層完成。mysql須要先讀數據而後過濾

分解複雜查詢

  1. 切分查詢:將數據量大的查詢切分爲幾回(有些狀況分析查詢的性能更好,好比刪除數據,每次刪除10條比一次刪除100條來得好,當在數據庫業務繁忙的時候)
  2. 分解關聯查詢:
    • 緩存效率高:mysql中若是關聯表發生了變化,緩存就失效了;並且應用程序能夠緩存切分查詢以後的結果
    • 執行單個查詢減小鎖競爭
    • 數據庫表不作強關聯,在應用層作,擴展性更好

mysql執行、優化查詢的方式

mysql查詢優化器的侷限性

優化器只關心隨機頁面的讀取函數

  1. 關聯子查詢:有時候能夠使用join的方式重寫關聯子查詢,效率更好
  2. union的限制:mysql不能將條件放入union各個查詢中,重寫的時候能夠把共同的條件寫入各個查詢中
  3. 索引合併優化:mysql能夠利用同一張表上的多個索引,explain的時候type爲index_merge,key爲使用到的索引。若是存在合併(and的狀況)那麼能夠考慮將多個單列索引合爲一個多列索引
  4. 等值傳遞
  5. 並行執行:
  6. 鬆散索引
  7. 哈希關聯
  8. 最大值和最小值:mysql的min和max函數
  9. 在同一個表上查詢和更新:mysql不容許同時對一張表查詢和更新,能夠使用join的方式來select須要在該表上查詢的字段

干涉查詢優化器

mysql提供了一些選項來干涉優化器的行爲,可是建議通常狀況下不要使用,由於通常干涉優化器帶來的收效較小,反而給版本升級的時候帶來一些問題性能

優化特定類型的查詢

count

count(col):查詢該列值得個數(不包含null)
count(星號):查詢行數優化

  1. myisam全表count(星號)很快
  2. 對於不精確的統計使用緩存

優化關聯查詢

  1. 確保on和using列上有索引,A join B on col,那麼通常只須要在B的col建立索引就夠了
  2. 確保group by 和order by的表達式只涉及一個表中的列,mysql才能夠使用索引來優化

優化子查詢

使用關聯查詢代替子查詢,在mysql5.6和mariadb不須要考慮

優化group by和order by

group by的結果默認會按照分組字段進行排序,若是不須要排序能夠去掉排序,指定order by NULL

優化分頁查詢

當頁碼比較多的時候須要掃描的數據較大,這個時候能夠使用覆蓋索引進行優化,先使用索引覆蓋查詢出limit的分頁數據,而後join該表,查詢其餘字段,這樣就減小了掃描的行數

select * from user_order inner join (select order_id from user_order order by buy_date limit 50, 5) as lim on lim.order_id=user_order.order_id;

或者能夠記下該分界行的標識列(該列最好有索引),好比主鍵id,而後查詢基於該分界的記錄

select * from user_order where order_id > 500 order by order_id limit 5;

對於總記錄數,若是不那麼精確的話能夠使用explain的rows

優化union查詢

除非有消除重複行的必要,不然使用union all,由於使用union會在臨時表上加distinct,致使對整個臨時表作惟一性校驗

使用自定義變量

相關文章
相關標籤/搜索