MySQL數據庫與 Oracle、 SQL Server 等數據庫相比,有其內核上的優點與劣勢。咱們在使用MySQL數據庫的時候須要遵循必定規範,揚長避短。本規範旨在幫助或指導RD、QA、OP等技術人員作出適合線上業務的數據庫設計。在數據庫變動和處理流程、數據庫表設計、SQL編寫等方面予以規範,從而爲公司業務系統穩定、健康地運行提供保障。前端
如下全部規範會按照【高危】、【強制】、【建議】三個級別進行標註,遵照優先級從高到低。git
對於不知足【高危】和【強制】兩個級別的設計,DBA會強制打回要求修改。github
庫通配名_編號
,編號從0開始遞增,好比wenda_001
以時間進行分庫的名稱格式是「庫通配名_時間」create database db1 default character set utf8;
。auto_increment
(2)標識表裏每一行主體的字段不要設爲主鍵,建議設爲其餘字段如user_id
,order_id
等,並創建unique key索引(可參考cdb.teacher
表設計)。由於若是設爲主鍵且主鍵值爲隨機插入,則會致使innodb內部page分裂和大量隨機I/O,性能降低。create_time
和最後更新時間字段update_time
,便於查問題。NOT NULL
屬性,業務能夠根據須要定義DEFAULT
值。由於使用NULL值會存在每一行都會佔用額外存儲空間、數據遷移容易出錯、聚合函數計算結果誤差等問題。blob
、text
等大字段,垂直拆分到其餘表裏,僅在須要讀這些對象的時候纔去select。user_name
屬性在user_account
,user_login_log
等表裏冗餘一份,減小join查詢。tmp_
開頭。備份表用於備份或抓取源錶快照,名稱必須以bak_
開頭。中間表和備份表按期清理。alter table
,必須通過DBA審覈,並在業務低峯期執行。由於alter table
會產生表鎖,期間阻塞對於該表的全部寫入,對於業務可能會產生極大影響。auto_increment
屬性),推薦使用bigint
類型。由於無符號int
存儲範圍爲-2147483648~2147483647
(大約21億左右),溢出後會致使報錯。status
、類型type
等字段推薦使用tinytint
或者smallint
類型節省存儲空間。int
類型,不推薦用char(15)
。由於int
只佔4字節,能夠用以下函數相互轉換,而char(15)
佔用至少15字節。一旦表數據行數到了1億,那麼要多用1.1G存儲空間。SQL:select inet_aton('192.168.2.12'); select inet_ntoa(3232236044);
PHP: ip2long(‘192.168.2.12’); long2ip(3530427185);
web
enum
,set
。 由於它們浪費空間,且枚舉值寫死了,變動不方便。推薦使用tinyint
或smallint
。blob
,text
等類型。它們都比較浪費硬盤和內存空間。在加載表數據時,會讀取大字段到內存裏從而浪費內存空間,影響系統性能。建議和PM、RD溝通,是否真的須要這麼大字段。Innodb中當一行記錄超過8098字節時,會將該記錄中選取最長的一個字段將其768字節放在原始page裏,該字段餘下內容放在overflow-page
裏。不幸的是在compact
行格式下,原始page
和overflow-page
都會加載。int
,程序端乘以100和除以100進行存取。由於int
佔用4字節,而double
佔用8字節,空間浪費。varchar
存儲。由於varchar
是變長存儲,比char
更省空間。MySQL server層規定一行全部文本最多存65535字節,所以在utf8字符集下最多存21844個字符,超過會自動轉換爲mediumtext
字段。而text
在utf8字符集下最多存21844個字符,mediumtext
最多存2^24/3個字符,longtext
最多存2^32個字符。通常建議用varchar
類型,字符數不要超過2700。timestamp
。由於datetime
佔用8字節,timestamp
僅佔用4字節,可是範圍爲1970-01-01 00:00:01
到2038-01-01 00:00:00
。更爲高階的方法,選用int
來存儲時間,使用SQL函數unix_timestamp()
和from_unixtime()
來進行轉換。詳細存儲大小參加下圖:redis
id int/bigint auto_increment
,且主鍵值禁止被更新。pk_
」開頭,惟一鍵以「uk_
」或「uq_
」開頭,普通索引以「idx_
」開頭,一概使用小寫格式,以表名/字段的名稱或縮寫做爲後綴。BTREE
;MEMORY表能夠根據須要選擇HASH
或者BTREE
類型索引。userid
的區分度可由select count(distinct userid)
計算出來。key(a,b)
,則key(a)
爲冗餘索引,須要刪除。partition-key
)必須有索引,或者是組合索引的首列。alter table
操做,必須在業務低峯期執行。utf8
或utf8mb4
。utf8
。一個較爲規範的建表語句爲:sql
CREATE TABLE user ( `id` bigint(11) NOT NULL AUTO_INCREMENT, `user_id` bigint(11) NOT NULL COMMENT ‘用戶id’ `username` varchar(45) NOT NULL COMMENT '真實姓名', `email` varchar(30) NOT NULL COMMENT ‘用戶郵箱’, `nickname` varchar(45) NOT NULL COMMENT '暱稱', `avatar` int(11) NOT NULL COMMENT '頭像', `birthday` date NOT NULL COMMENT '生日', `sex` tinyint(4) DEFAULT '0' COMMENT '性別', `short_introduce` varchar(150) DEFAULT NULL COMMENT '一句話介紹本身,最多50個漢字', `user_resume` varchar(300) NOT NULL COMMENT '用戶提交的簡歷存放地址', `user_register_ip` int NOT NULL COMMENT ‘用戶註冊時的源ip’, `create_time` timestamp NOT NULL COMMENT ‘用戶記錄建立的時間’, `update_time` timestamp NOT NULL COMMENT ‘用戶資料修改的時間’, `user_review_status` tinyint NOT NULL COMMENT ‘用戶資料審覈狀態,1爲經過,2爲審覈中,3爲未經過,4爲還未提交審覈’, PRIMARY KEY (`id`), UNIQUE KEY `idx_user_id` (`user_id`), KEY `idx_username`(`username`), KEY `idx_create_time`(`create_time`,`user_review_status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='網站用戶基本信息';
*
。由於select *
會將不應讀的數據也從MySQL裏讀出來,形成網卡壓力。且表字段一旦更新,但model層沒有來得及更新的話,系統會報錯。insert into t1 values(…)
,道理同上。insert into…values(XX),(XX),(XX)…
。這裏XX的值不要超過5000個。值過多雖然上線很很快,但會引發主從同步延遲。UNION
,推薦使用UNION ALL
,而且UNION
子句個數限制在5個之內。由於union all
不須要去重,節省數據庫資源,提升性能。select… where userid in(….500個之內…)
,這麼作是爲了減小底層掃描,減輕數據庫壓力從而加速查詢。hint
,如sql_no_cache
,force index
,ignore key
,straight join
等。由於hint
是用來強制SQL按照某個執行計劃來執行,但隨着數據量變化咱們沒法保證本身當初的預判是正確的,所以咱們要相信MySQL優化器!SELECT|UPDATE|DELETE|REPLACE
要有WHERE子句,且WHERE子句的條件必需使用索引查找。where length(name)='Admin'
或where user_id+2=10023
。where a=1 or b=2
優化爲where a=1… union …where b=2, key(a),key(b)
。select a,b,c from t1 limit 10000,20;
優化爲: select a,b,c from t1 where id>10000 limit 20;
。update t1 join t2…
。select a from db1.table1 alias1 where …
。INSERT|UPDATE|DELETE|REPLACE
語句操做的行數控制在2000之內,以及WHERE子句中IN列表的傳參個數控制在500之內。auto_increment
屬性字段的表的插入操做,併發須要控制在200之內。repeatable-read
。unique key
,如update … where id=XX
; 不然會產生間隙鎖,內部擴大鎖定範圍,致使系統性能降低,產生死鎖。order by
,和業務溝通能不排序就不排序,或將排序放到程序端去作。order by
、group by
、distinct
這些語句較爲耗費CPU,數據庫的CPU資源是極其寶貴的。order by
、group by
、distinct
這些SQL儘可能利用索引直接檢索出排序好的數據。如where a=1 order by
能夠利用key(a,b)
。order by
、group by
、distinct
這些查詢的語句,where條件過濾出來的結果集請保持在1000行之內,不然SQL會很慢。update|delete t1 … where a=XX limit XX;
這種帶limit的更新語句。由於會致使主從不一致,致使數據錯亂。建議加上order by PK
。update t1 set … where name in(select name from user where…);
效率極其低下。insert into …on duplicate key update…
在高併發環境下,會形成主從不一致。update t1,t2 where t1.id=t2.id…
。轉自: https://github.com/jly8866/ar...