一個來自開發的數據庫優化

數據庫優化

第一級

簡單DDL、DML調優。SQL寫的好很差?group by、order by對不對?select別用*,記得要用hit index啊。數據庫表設計好點啊,主鍵外鍵索引啊,執行計劃看一看啊。html

SQL語句和索引的優化是最重要的。咱們追求的就是寫出結構良好的SQL,而後根據SQL在表中創建有效的索引。若是索引過多,不但會影響寫入的效率,對查詢也有必定的影響。mysql

要根據一些範式來進行表結構的設計。設計表結構時,就須要考慮如何設計纔可以更有效的查詢。sql

第二級

第二級是DBA層級調優。MSSQL,ORACLE,MYSQL都各自有幾十項配置。在不一樣的應用場景下須要針對性調整系統配置的優化。MySQL數據庫是基於文件的,若是打開的文件數達到必定的數量,沒法打開以後就會進行頻繁的IO操做。數據庫

參考這裏工具

第三級

是數據庫中間件和infra層級調優。優化

參考《MySQL數據庫優化兩三事》(大佬,打擾了!小弟告辭).net

優化成本和效果

1、SQL語句優化

  1. 查詢慢日誌設計

    能夠經過開啓查詢慢日誌的方式進行定位效率有問題的SQLunix

    • 查看MySQL是否開啓慢查詢日誌日誌

      show variables like 'slow_query_log';

    • 設置沒有索引的記錄到慢查詢日誌

      set global log_queries_not_using_indexes=on;
    • 查看超過多長時間的sql進行記錄到慢查詢日誌

      show variables like 'long_query_time';
    • 開啓慢查詢日誌

      set global slow_query_log=on
    • 設置超時時間

      Set global long_query_time=5;  --超過5s的語句才記錄日誌
    • 查看慢查詢日誌的位置

      show variables like 'slow%'
  2. 慢查詢日誌內容分析

    慢查詢日誌主要分爲5部分,第一部分是慢查詢時間,第二部分是慢查詢的來源主機和用戶,第三部分是查詢的執行時間、鎖定時間、發送的行數、掃描的行數。最後是時間戳形式記錄的命令以及該命令的執行的時間戳。

    系統運行一段時間後,慢查詢日誌可能比較多,須要經過mysqldumpslow、pt-query-digest等工具分析慢查詢日誌。參考這裏

  3. 經過explain查看SQL的執行計劃

    具體的分析過程能夠參考這裏,裏面的例子描述的很清晰。

2、索引優化

​ 索引通常狀況下都是高效的。不過凡是都有兩面性,索引是以空間換時間的一種策略,索引自己在提升查詢效率的同時會影響插入、更新、刪除的效率。不當的使用索引不只增長了寫操做的負擔,也會影響讀取的效率。索引越多,數據庫分析的越慢。注意點:

  1. InnoDB 每一個索引都會加上主鍵,聯合索引不要加上主鍵,innodb會自動加,不然會冗餘。
  2. 索引存在的目的是爲了加快查詢的效率,不過不是索引越多越好,創建索引要適當纔好。過多的索引會增長數據庫判斷使用什麼索引來查詢的開銷,因此,有時候也會出現以去掉重複或者無效的索引爲優化手段的優化方式。
  3. 主鍵已是索引了,因此primay key 的主鍵不用再設置unique惟一索引了。

索引的原理能夠參考這裏或者這裏。理解索引原理對於索引優化有很大幫助。

3、數據表結構優化

  1. 選擇合適的數據類型

    • 使用可存下數據的最小的數據類型;
    • 使用簡單地數據類型,int要比varchar類型在mysql處理上更簡單;
    • 儘量使用not null定義字段,這是由innodb的特性決定的,由於非not null的數據可能須要一些額外的字段進行存儲,這樣就會增長一些IO。能夠對非null的字段設置一個默認值;
    • 儘可能少用text,非用不可最好分表,將text字段存放到另外一張表中,在須要的時候再使用聯合查詢,這樣可提升查詢主表的效率;
    -- 例子一、用int存儲日期時間from_unixtime()可將Int類型的時間戳轉換爲時間格式
    
    select from_unixtime(1392178320); 
    -- 輸出爲 2014-02-12 12:12:00
    
    -- unix_timestamp()可將時間格式轉換爲Int類型
    select unix_timestamp('2014-02-12 12:12:00'); 
    -- 輸出爲1392178320
    
    
    -- 例子二、存儲IP地址——bigInt
    
    -- 利用inet_aton(),inet_ntoa()轉換
    select inet_aton('192.169.1.1'); 
    -- 輸出爲3232301313select 
    inet_ntoa(3232301313); 
    -- 輸出爲192.169.1.1
相關文章
相關標籤/搜索