Mysql與InnoDB優化

Mysql能夠從如下幾個方面進行數據庫優化:

SQL及索引優化:

  sql優化:

  • 優化count
    select count(*) ,count(id) from t; #count(*) 會包含null,count(id)不包含Null
    select count(release_year='2006' OR NULL) AS '2006year',count(release_year='2007' OR NULL) AS '2007year' from film; #查找2006年和2007年分別發行的電影數
  • 優化max 經過索引優化
    explain select max(payment_date) from payment; #當沒有爲payment_date創建索引時,使用的是全表掃描
    create index idx_paydate on payment(payment_date); #創建索引後再分析則爲覆蓋索引
  • 優化子查詢
    一般狀況下須要把子查詢優化爲join 查詢,但在優化時要注意關聯鍵是否有一對多的關係,要注意重複數據
    select dictinct t.id from t join t1 on t.id=t1.id;
  • 優化group by

     避免查詢使用臨時表和文件排序,儘可能使用索引mysql

    eg:查詢每一個演員所參演的影片的數量 影片表和演員表
    優化前 Explain select actor.frist_name,actor.last_name,,count(*) from file_actor inner join actor using(actor_id) group by film_actor.actor_id
    優化後 Explain select actor.frist_name,actor.last_name,c.cnt from actor inner join(select actor_id,count(*) as cnt from film_actor Group By actor_id) As c using(actor_id)
  • 優化limit查詢
    使用索引的列或主鍵進行Order by操做
      select film_id,description from film order by film_id limit 50,5;
    記錄上次返回的主鍵,在下次查詢時使用主鍵過濾
      select film_id,description from film where film_id>50 and film_id<=60 order by film_id limit 1,5; #這種狀況掃描表的行數爲5,固然這種狀況也要求film_id是連續的
  • 藉助Mysql慢日誌查詢
    show variables like 'slow_query_log';
    set global slow_query_log=on; #開啓慢日誌查詢
    藉助工具分析慢日誌
      1.mysqldumpslow
        mysqldumpslow -t 3 /home/mysql/msyql-slow.log |more
      2.pt-query-digest
 

  索引優化:

  • 如何選擇適合的列創建索引
    1. 在where從句,group by從句,order by從句,on從句中出現的列
    2. 索引字段越小越好
    3. 離散度大的列放在聯合索引的前面
    eg:select count(distinct customer_id),count(distinct staff_id) from payment;
    查詢結果:customer_id 599 staff_id 2
    因爲customer_id的離散度更大,因此應該使用 index(customer_id,staff_id)
  • 索引的維護及優化: 查找重複及冗餘索引
select  
a.TABLE_SCHEMA AS '數據名',
a.TABLE_NAME AS '表名',
a.INDEX_NAME AS '索引1',
b.INDEX_NAME AS '索引2',
a.COLUMN_NAME as '重複列名'
from STATISTICS a JOIN STATISTICS b ON
a.TABLE_SCHEMA = b.TABLE_SCHEMA 
AND a.TABLE_NAME = b.TABLE_NAME
AND a.SEQ_IN_INDEX = b.SEQ_IN_INDEX
AND a.COLUMN_NAME = b.COLUMN_NAME;

 

數據庫表結構

  • 選擇合適的數據類型
  • 表的範式化和反範式化設計
    目前說到的範式化通常指第三設計範式,也就是要求數據表中不存在非關鍵字段對任意候選關鍵字段的傳遞函數依賴
    反範式指爲了提升查詢效率適當增長一些冗餘,是一種空間換時間的操做
  • 表的垂直拆分:
    就是把原來一個有不少列的表拆分紅多個表,拆分原則:
    1. 把不經常使用的字段單獨存放到一個表中
    2. 把大字段獨立存放到一個表中
    3. 把常常用到的字段放到一塊兒
  • 表的水平拆分:
    表的水平拆分是爲了解決單表的數據量過大的問題,水平拆分的表每個表的結構都是徹底一致的
    拆分方式:
    1. 對 id 進行hash運算,若是要拆分紅5個表,則使用摸底(id,5)取出0~4個值
    2. 針對不一樣的hashID把數據存到不一樣的表中

系統配置

  網絡方面的配置,要修改 /etc/sysctl.conf

    #增長tcp支持的隊列數
      net.ipv4.tcp_max_syn_backlog=65535
    #減小斷開鏈接時,資源回收
      net.ipv4.tcp_max_tw_buckets=8000
      bet.ipv4.tcp_tw_reuse=1
      net.ipv4.tcp_tw_recycle=1
      net.ipv4.tcp_fin_timeout=10
    #打開文件數的限制 /etc/security/limits.conf
      * soft nofile 65535
      * hard nofile 65535
    關閉 iptables 等防火牆
 

  Mysql 的配置

SELECT engine,ROUND(SUM(data_length+index_length)/1024/2014,1) AS "Total MB" FROM INFORMATION_SCHEMA.TABLES WHERE table_schema not in ("information_schema","performance_schema") GROUP BY ENGINE; #系統中每一種引擎表的大小 
  innodb_buffer_pool_size   #重要,緩衝池的大小 推薦總內存量的75%,越大越好。
  innodb_buffer_pool_instances   #該參數能夠控制緩衝池的個數,默認只有一個緩衝池,若是一個緩衝池中併發量過大,容易阻塞,此時能夠分爲多個緩衝池;
  innodb_log_buffer_size #innodb log 緩衝大小,由緩衝區刷新到磁盤,因爲日誌最長每秒鐘就會刷新因此通常不用太大
  innodb_flush_log_at_trx_commit #關鍵,數據庫多長時間把數據刷新到磁盤,默認值爲1,可取0,1,2三個值,0表示每一秒鐘把變動刷新到磁盤,1表示每一次提交會把變動刷新到磁盤,2表示每一次提交刷新到緩衝區而後每一秒從緩衝區刷新到磁盤,建議設置爲2,若是數據安全性要求較高則使用默認值1
  innodb_read_io_threads #Innodb讀IO進程數,默認爲4
  innodb_write_io_threads #Innodb 寫IO 進程數,默認爲4
  innodb_file_per_table #on表示每一個表使用獨立的表空間,默認爲 off,也就是全部的表都會創建在共享表空間上,設爲on可提升併發效率
  innodb_stats_on_metadata # 決定Mysql在什麼狀況下會刷新innodb表的統計信息,通常關掉
 

硬件

  如何選擇CPU
    通常選擇單核更快的CPU,而且並不要求核數太多,32核,內存64G 足矣
  磁盤IO 優化
    經常使用RAID 級別簡介
    RAID0:也稱條帶,就是把多個磁盤連接成一個硬盤使用,這個級別IO最好
    RAID1:也稱鏡像,要求至少有兩個磁盤,每組磁盤存儲的數據相同
    RAID5:也是把多個(最少3個)硬盤合併成1個邏輯磁盤使用,數據讀寫時會創建奇偶校驗信息,並把奇偶校驗信息和相對應的數據分別存儲於不一樣的磁盤上。當RAID5的一個磁盤數據發生損壞後,利用剩下的數據和相應的奇偶校驗信息去恢復損壞的數據
      RAID1+0:也就是RAID1和RAID0的結合。同時具備兩個級別的優勢。通常建議數據庫使用這個級別
相關文章
相關標籤/搜索