標簽:union all 分組 字段名 空間 編號 from 表達 最大 time
MySQL數據庫與 Oracle、 SQL Server 等數據庫相比,有其內核上的優勢與劣勢。我們在使用MySQL數據庫的時候需要遵循一定規范,揚長避短。本規范旨在幫助或指導RD、QA、OP等技術人員做出適合線上業務的數據庫設計。在數據庫變更和處理流程、數據庫表設計、
SQL編寫等方面予以規范,從而為公司業務系統穩定、健康地運行提供保障。
以下所有規范會按照【高?!?、【強制】、【建議】三個級別進行標注,遵守優先級從高到低。
對于不滿足【高?!亢汀緩娭啤績蓚€級別的設計,DBA會強制打回要求修改。
庫通配名_編號
,編號從0開始遞增,比如wenda_001
以時間進行分庫的名稱格式是“庫通配名_時間”create database db1 default character set utf8;
。auto_increment(2)
標識表里每一行主體的字段不要設為主鍵,建議設為其他字段如user_id
,order_id
等,并建立unique key索引(可參考cdb.teacher
表設計)。因為如果設為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 in et_ntoa(3232236044);
PHP: ip2long(‘192.168.2.12’); long2ip(3530427185);
enum
,set
。 因為它們浪費空間,且枚舉值寫死了,變更不方便。推薦使用tinyint
或smallint
。blob
,text
等類型。它們都比較浪費硬盤和內存空間。在加載表數據時,會讀取大字段到內存里從而浪費內存空間,影響系統性能。建議和PM、RD溝通,是否真的需要這么大字段。Innodb中當一行記錄超過8098字節時,會將該記錄中選取最overflow-page
里。不幸的是在compact
行格式下,原始page
和overflow-page
都會加載。int
,程序端乘以100和除以100進行存取。因為int
占用4字節,而double
占用8字節,空間浪費。varchar
存儲。因為varchar
是變長存儲,比char
更省空間。MySQL server層規定一行所有文本最多存65535字節,因此在utf8字符集下最多存21844個字符,超過會自動轉換為mediumtext
字段。而text
在utf8字符集下最多存21844mediumtext
最多存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()
來進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
。一個較為規范的建表語句為:
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 b
可以利用key(a,b)
。order by
、group by
、distinct
這些查詢的語句,where條件過濾出來的結果集請保持在1000行以內,否則SQL會很慢。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…
。標簽:union all 分組 字段名 空間 編號 from 表達 最大 time
原文地址:https://www.cnblogs.com/zeenzhou/p/15054759.html