t_crm_relation
,中間的 crm 表明業務模塊名view_
開頭,事件以event_
開頭,觸發器以trig_
開頭,存儲過程以proc_
開頭,函數以func_
開頭idx_col1_col2
命名,惟一索引以uk_col1_col2
命名(可去掉f_公共部分)。如 idx_companyid_corpid_contacttime(f_company_id,f_corp_id,f_contact_time)庫名、表名、字段名支持最多64個字符,但爲了統一規範、易於辨識以及減小傳輸量,禁止超過32個字符mysql
如 t_crm_relation_tmp0425。備份表也相似,形如 _bak20160425
。sql
這也是爲未來有可能分表作準備的,好比t_crm_ec_record_201403
,但像 t_crm_contact_at201506就打破了這種規範。
不具備時間特性的,直接以 t_tbname_001
這樣的方式命名。數據庫
5.5版本開始mysql默認存儲引擎就是InnoDB,5.7版本開始,系統表都放棄MyISAM了。緩存
SET NAMES UTF8;
。(對於已經在項目中長期使用latin1的,救不了了)即便2個表的字段有明確的外鍵參考關係,也不使用 FOREIGN KEY ,由於新紀錄會去主鍵表作校驗,影響性能。網絡
好比不一樣表中都有 f_user_id 字段,那麼它的類型、字段長度要設計成同樣mysql優化
儘可能避免extra列出現:Using File Sort,Using Temporary,rows超過1000的要謹慎上線。
explain解讀併發
type
:ALL, index, range, ref, eq_ref, const, system, NULL(從左到右,性能從差到好)possible_keys
:指出MySQL能使用哪一個索引在表中找到記錄,查詢涉及到的字段上若存在索引,則該索引將被列出,但不必定被查詢使用key
:表示MySQL實際決定使用的鍵(索引)ref
:表示選擇 key
列上的索引,哪些列或常量被用於查找索引列上的值rows
:根據表統計信息及索引選用狀況,估算的找到所需的記錄所須要讀取的行數Extra
Using temporary
:表示MySQL須要使用臨時表來存儲結果集,常見於排序和分組查詢Using filesort
:MySQL中沒法利用索引完成的排序操做稱爲「文件排序」INNODB存儲引擎中,secondary index(非主鍵索引,又稱爲輔助索引、二級索引)沒有直接存儲行地址,而是存儲主鍵值。
若是用戶須要查詢secondary index中所不包含的數據列,則須要先經過secondary index查找到主鍵值,而後再經過主鍵查詢到其餘數據列,所以須要查詢兩次。覆蓋索引則能夠在一個索引中獲取全部須要的數據列,從而避免回表進行二次查找,節省IO所以效率較高。
例如SELECT email,uid FROM user_email WHERE uid=xx,若是uid不是主鍵,適當時候能夠將索引添加爲index(uid,email),以得到性能提高。運維
如不在定義了 ON UPDATE CURRENT_STAMP 的列上建立索引,維護成本過高(好在mysql有insert buffer,會合並索引的插入)函數
即便須要全部字段,減小網絡帶寬消耗,能有效利用覆蓋索引,表結構變動對程序基本無影響工具
在保證數據不會有誤的前提下,能肯定結果集數量時,多使用limit,儘快的返回結果。
轉換規則
a. 兩個參數至少有一個是 NULL 時,比較的結果也是 NULL,例外是使用 <=> 對兩個 NULL 作比較時會返回 1,這兩種狀況都不須要作類型轉換
b. 兩個參數都是字符串,會按照字符串來比較,不作類型轉換
c. 兩個參數都是整數,按照整數來比較,不作類型轉換
d. 十六進制的值和非數字作比較時,會被當作二進制串
e. 有一個參數是 TIMESTAMP 或 DATETIME,而且另一個參數是常量,常量會被轉換爲 timestamp
f. 有一個參數是 decimal 類型,若是另一個參數是 decimal 或者整數,會將整數轉換爲 decimal 後進行比較,若是另一個參數是浮點數,則會把 decimal 轉換爲浮點數進行比較
g. 全部其餘狀況下,兩個參數都會被轉換爲浮點數再進行比較。
若是一個索引創建在string類型上,若是這個字段和一個int類型的值比較,符合第 g 條。如f_phone定義的類型是varchar,但where使用f_phone in (098890),兩個參數都會被當成成浮點型。發生這個隱式轉換並非最糟的,最糟的是string轉換後的float,mysql沒法使用索引,這才致使了性能問題。若是是 f_user_id = ‘1234567’ 的狀況,符合第 b 條,直接把數字當字符串比較。
會致使索引失效,有這種搜索需求是,考慮其它方案,如sphinx全文搜索
小於5.6版本時,子查詢效率很低,不像Oracle那樣先計算子查詢後外層查詢。5.6版本開始獲得優化
超過500個值使用批量的方式,不然一次執行會影響數據庫的併發能力,由於單SQL只能且一直佔用單CPU,並且可能致使主從複製延遲
好比在一個事務裏進行多個select,多個update,若是是高頻事務,會嚴重影響MySQL併發能力,由於事務持有的鎖等資源只在事務rollback/commit時才能釋放。但同時也要權衡數據寫入的一致性。
這種查詢更多的是經過索引去優化,但order by的字段有講究,好比主鍵id與f_time都是順序遞增,那就能夠考慮order by id而非 f_time 。
與上面不一樣的是,order by以前有個範圍查詢,由前面的內容可知,用不到相似(c1,c2)的索引,可是能夠利用(c2,c1)索引。另外還能夠改寫成join的方式實現。
建議使用合理的分頁方式以提升分頁效率,大頁狀況下不使用跳躍式分頁
假若有相似下面分頁語句:
SELECT FROM table1 ORDER BY ftime DESC LIMIT 10000,10;
這種分頁方式會致使大量的io,由於MySQL使用的是提早讀取策略。
推薦分頁方式:
SELECT FROM table1 WHERE ftime < last_time ORDER BY ftime DESC LIMIT 10
即傳入上一次分頁的界值
SELECT * FROM table as t1 inner JOIN (SELECT id FROM table ORDER BY time LIMIT 10000,10) as t2 ON t1.id=t2.id
select最多致使數據庫慢,寫操做纔是鎖表的罪魁禍首
INSERT ... ON DUPLICATE KEY UPDATE ...
,插入行後會致使在一個UNIQUE索引或PRIMARY KEY中出現重複值,則執行舊行UPDATE,若是不重複則直接插入,影響1行。REPLACE INTO
相似,但它是衝突時刪除舊行。INSERT IGNORE
相反,保留舊行,丟棄要插入的新行。