MySQL數據庫優化漫談

1.表設計
    遵循三範式,但必要的時候做數據冗餘,舉例說明:在權限模型中可能會用到5張表 用戶表、角色表、權限表,還有用戶角色關聯表和角色權限關聯表。如果此時要通過用戶查詢權限則必須關聯查詢或者使用多條sql查詢,此時可以在用戶表增加一個字段來存儲用戶的權限(例如將權限值使用逗號隔開),這樣可以如果查詢某用戶的權限可以直接在用戶表中查詢,查詢後再用程序來處理。

    設計表時要選用合適的存儲引擎,對於經常查詢的表,並且不需要事務等應用,優先選用MyISAM(例如新聞表),如果需要事務處理對穩定性要求高的表優先選用InnoDB存儲引擎(例如訂單表,訂單商品表),目前InnoDB已經成爲新版MySQL的默認存儲引擎,在高併發寫入時的穩定性相比MyISAM更高,在讀取速度上速度也比較快,所以推薦使用此引擎。 不需要永久保存的數據可以選用Memory存儲引擎(例如session,購物車)

    對於不同的字段選用合適的字段類型,例如IP地址應該存儲爲整型,見將IP以整型的方式存儲到數據庫中。固定長度的字符串要使用char,例如md5加密的密碼。

2.分表技術
    橫向分表(各個表的字段類型與數量是完全一致的),例如用戶表,可以按用戶首字母橫向切分;交易記錄可以按照年份或者月份切分,每張表的字段一致,至於按什麼規則來來區分可以看具體的業務。
    縱向分表(各個表的字段不一致,但條數是一致的),例如某商城網站用戶表使用MyISAM引擎,可以應對用戶登錄時的查詢操作,但是用戶之間轉賬需要事務來保證安全,這樣就可以將用戶餘額字段分離出來組成一張InnoDB引擎的新表,和用戶表關聯,既滿足高效查詢,又滿足穩定性。
    另外還可以進行分區,或者分庫,都是類似的思路。
3.索引優化
    常見的索引有 主鍵索引、唯一索引、普通索引、全文索引(僅MyISAM存儲引擎支持,並且不支持中文,如果需要支持中文需要安裝插件)。通常需要在條件字段、排序字段、分組字段以及關聯字段上建立對應索引。但重複率很高的字段不宜建立索引,比如狀態字段(是否被刪除,是否上架等),emum類型(性別等),另外建立索引會對增刪改操作的速度有影響,因此頻繁更新的字段不適合建立索引,例如文章的點擊量。
4.SQL優化
在開發時可以使用explain 測試sql語句
在測試結果會有如下參數,簡要解釋一下
select_type   
查詢的方式 SIMPLE表示select類型,沒有連接或者子查詢,PRIMARY表示主查詢(注意:不是主鍵,例如子查詢時的外層查詢,UNION查詢時的第一個select),DEPENDENT SUBQUERY表示子查詢語句,UNION表示UNION查詢時除了PRIMARY(第一條語句)之外的語句
table        表名
type        掃描類型(重要)如果是All表示全表掃描,效率低;如果是const表示最多有一行與結果匹配,效率高;system表示表中僅有一條數據,肯定高效;eq_ref表示所以用到主鍵或者唯一索引;ref表示用到普通索引;range表示查詢一個區間(範圍的數據);index表示都是通過索引查詢性能一般
possible_keys    可能使用到的索引(重要)
key        實際用到的索引(重要)
key_len        索引長度
ref
rows        MySQL認爲它執行查詢時必須檢查的行數(重要)越小越好       
Extra        額外信息 Using filesort表示查詢中使用了order by 並且無法利用索引排序,如果確實不需要排序可以在SQL語句末尾增加order by null.Using temporary某些操作使用了臨時表,不要.Using where 使用索引.

    編寫代碼以及SQL語句需要注意的如下幾項:

    1)如果查詢條件中有or,則所有使用到的字段必須都有索引纔有效;

    2)like查詢條件中如果以%開頭則索引失效;

    3)聯合(多列)索引 只有使用左邊的列索引才能生效;

    4)where後有多個查詢條件應優先使用能夠過濾數據量大的條件(先後順序很重要);

    5)不要使用子查詢(效率很低,除非數據量非常少),儘可能少用關聯查詢,寧可份多次查詢,有條件可以封裝成存儲過程。

    6)不要在循環中使用SQL語句,如果是查詢儘可能一次查詢然後通過程序來計算。如果是insert可使用擴展插入,即類似insert into tablename values (11,22),(33,33),(45,42)。
    檢測MySQL的索引使用情況可以使用以下命令
show global status where Variable_name like 'Handler_read%';
解釋一下主要參數
Handler_read_first 全索引掃描的次數,使用到了索引,但是全部索引;
Handler_read_key 越大越好,使用索引的情況;
Handler_read_rnd_next 表示沒有命中,值越大索引利用率越低;

對於已經上線的項目可以開啓MySQL的慢查詢來定位低效率的SQL,見使用MySQL的慢查詢日誌找到低效的SQL語句並通過explain分析進行優化
使用如下命令
show global status like 'Com%';
show global status like 'InnoDB_rows%';
show variables like  'long_query_time';
show variables like  '%slow%';

查看MySQL各種SQL的執行頻度 以及慢查詢狀態

使用optimize table 表名;命令來優化表,執行時會佔用大量資源,所以建議在用戶訪問量少的時刻執行。
5.配置優化

修改mysql的配置文件,通常在windows下爲my.ini,在Linux下爲my.cnf

query_cache_size = 64M

該值可以通過使用SHOW STATUS LIKE 'Qcache%';命令來查看MySQL狀態來進行相應的更改,如果Qcache_lowmem_prunes的值非常大,則表明經常出現緩衝不夠的情況需要增加cache值;如果Qcache_hits的值非常大,則表明查詢緩衝使用非常頻繁,是理想狀態,如果該值較小反而會影響效率,那麼可以考慮不用查詢緩衝。
對於MyISAM設置
key_buffer_size = 32M
MyISAM表會使用操作系統的緩存來緩存數據,設置的值取決於系統內存、索引大小、數據量以及負載。
對於InnoDB設置
innodb_buffer_pool_size = 2.4G
可以設置內存的70%左右,當然要考慮內存的整體佔用情況。

6.硬件架構設計優化

更換硬件 硬盤更換爲SSD 可提高几倍的效率,
延時寫入(更新),對於實時性較小的數據可以先將數據寫入到文件,每隔一段時間批量寫入(更新)到數據庫中
搭建MySQL主從同步架構,使用讀寫分離技術
使用sphinx 全文檢索服務器, 減輕MySQL服務器的壓力

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