在互聯網大廠必須遵守的MySql開發軍規
作者:esrever
在互聯網大廠必須遵守的MySql開發軍規:不在數據庫做運算;單表數據量:一年內單表純INT不超過1000W,含CHAR不超500W,單庫不超過300~400表;表字段盡量少,上限控制在20~50個;適當可以冗余(平衡范式和冗余);拒絕大sql,大事務,大批量。
核心
- 不在數據庫做運算
- 單表數據量:一年內單表純INT不超過1000W,含CHAR不超500W。單庫不超過300~400表
- 表字段盡量少,上限控制在20~50個
- 適當可以冗余(平衡范式和冗余)
- 拒絕大sql,大事務,大批量
字段
- 數值類型的字節和運用范圍
- 如果可以,將字符串轉化為數字存儲。可以加快查詢速度和節省空間,舉例用INT代替CHAR(15)來存儲IP
- 優先使用SET和ENUM...(可能有問題!)
- 避免使用NULL
- 少用TEXT/BLOB,如果必須使用(超過varchar最大限制64k)則必須拆分到單獨的表
- 不在數據庫存圖片
索引
- 能不加的索引盡量不加,最好不超過字段數的20%(如:性別不加),結合核心SQL優先考慮覆蓋索引
- 字符字段必須建前綴索引。由于字符串很長,通常可以索引開始的幾個字符,而不是全部值,以節約空間并得到好的性能。
- 不在索引列進行數學運算和函數運算(會導致無法使用索引 => 全表掃描),如where id+1 = 100 和 id = 100 - 1,效率差很遠
- 自增列或全局ID做INNODB的主鍵
- 盡量不用外鍵(由程序保證約束),高并發的時候容易死鎖
SQL
- SQL語句盡可能簡單,因為一條SQL只能在一個CPU運算,在高并發的情況下,可能一條大SQL就把整個數據庫堵死。而簡單的SQL緩存命中率更高,減少鎖表的時間(特別是MyISAM),用上多CPU
- 保持事務、DB連接足夠短,即開即用、用完就關。與事務無關操作放到事務外面,減少鎖資源的占用;在不破壞一致性前提下,使用多個短事務代替長事務(如:發帖時的圖片上傳等待)
- 盡可能少用存儲過程,少用觸發器,減用MySQL函數對結果進行處理(交由客戶端程序負責)
- 盡量少用select *,只取需要數據列,為使用覆蓋索引提供可能性,減少臨時表生成,更安全
- 用in()代替or,因為or的效率是O(n),而in()的效率是O(Log n)。如:where a = 1 OR a = 100 與 where a IN (1, 100)
- merge index往往很弱智,所以用union代替對多字段的or查詢。如:select * from t where a = 1 OR b = 2 與 select * from t where a = 1 UNION select * from t where b = 2
- 盡量避免負向查找,如NOT、!=等
- 盡量避免%前綴模糊查詢,由于使用的是B+ Tree,前綴模糊使用不了索引,導致全表掃描(后綴模糊速度相對快很多)
- 減少COUNT(*),使用COUNT(col),前者資源開銷大,盡量少用。MyISAM不帶WHERE COUNT()而INNODB帶WHERE COUNT()。 計數的統計可以采用的方法:實時統計可以使用memcache,雙向更新,凌晨跑基準;非實時統計盡量用單獨統計表,定期重算
- LIMIT高效分頁:傳統的方法是select * from t limit 10000, 10,推薦的方法是select * from t where id > 23423 limit 10。LIMIT的偏移量越大則越慢。還有一些高效的方法有:先取id來LIMIT偏移,減少整體的數據偏移;取到需要的id,與原表JOIN;程序取ID,然后用IN來填寫。select * from t where id >= (select id from t limit 10000, 1) limit 10 , select * from t INNER JOIN (select id from t limit 10000, 10) USING (id) , select id from t limit 10000, 10; select * from t where id in (123, 456...)
- 若無需對結果進行去重,則用UNION ALL而非UNION(UNION有去重開銷)
- 分解JOIN聯接來保證高并發。高并發DB不建議進行兩個表以上的JOIN
- group by會默認自動升序排序,如果需要去掉排序,需要指定order by NULL
- 比較原則:數字對數字、字符對字符。如果數值列與字符類型作比較,同時轉換成雙精度;如果字符列與數值類型作比較,字符列整列轉數值,且不會使用索引查詢
- load data導入數據比insert快約20倍(不需要刷新緩存)
- 盡量不使用insert...select(延遲、同步出錯)
- 大批量更新凌晨操作,避開高峰
- SQL的一些命令:explain, show profile, mysqlsla, mysqldumpslow, show slow log, show processlist, show QUERY_RESPONSE_TIME(Percona)
約定
- 數據庫在不同時期使用不同的:實時數據用real庫,模擬環境用sim庫,測試用qa庫,開發用dev庫
- 禁止未經DBA確認的子查詢(大部分情況優化較差,特別是WHERE中使用IN id的子查詢,一般可以用JOIN改寫)
- 不要在程序上加鎖數據庫,因為外部鎖對數據庫不可控,高并發時是災難,并且極難調試排查(可以采用事務來解決)
- 統一字符集:UTF-8,校對規則:utf8_general_ci
- 庫和表的名稱統一用小寫(大小寫敏感、且不同操作系統都有不同的限制);字段名大小寫不敏感;索引名默認為idx_字段名;庫名用縮寫,盡量在2~7個字母;避免用保留字命名
責任編輯:未麗燕
來源:
簡書




























