關於MySQL 建表的一些建議
MySQL作為關係型資料庫,被用來儲存持久化的資料,避免不了需要建立表。如果沒有利用ORM(物件關係模型)來自動建立表,則需要開發者通過圖形介面(Navicat)或者手寫MySQL語句。
由於在生產環境下,我們對MySQL資料庫的操作通常是通過命令列進行操作,因此,建議建表的時候也手寫MySQL語句(不建議用圖形介面建表)。
1、添加註釋的格式
在編寫MySQL語句時,我們通常會被要求加上註釋,推薦的註釋格式為:
------------------------------------------------- -- 建立表 tb_example 建立示例表 ------------------------------------------------- create table tb_example( …. )…
理由:這種註釋格式MySQL解析器也會認為是註釋的,然後,會正確執行你的create table相關語句。我們通常將要更改的sql語句整理到一個1.0.0.sql檔案中,然後,你只需要登入MySQL客戶端,輸入:source /檔案目錄/1.0.0.sql。因此,這樣的註釋可以達到一舉兩得的目的。
2、指定表的引擎和預設的編碼格式以及該表的說明
示例語句如下:create table tb_example(
….
)engine=innodb default charset=utf8 comment ‘這是一張示例表’;
理由:上述顯示的指定使用的引擎為innodb,在5.6之前預設的引擎是MyISAM,而現在主流推薦效能較好的是innodb,具體參考:高效能MySQL 這本書
3、一個經典的建表語句示例並分析
示例語句如下:
create table tb_example( id int unsigned not null auto_increment comment '主鍵id', app_id int unsigned not null default '0' comment '應用id', app_name varchar(255) not null default '' comment '應用名', click_cnt int unsigned not null default '0' comment '點選數', disp_cnt int unsigned not null default '0' comment '展示數', status tinyint unsigned not null default '0' comment '狀態: 1-啟用;0-禁用', click_rate float unsigned not null default '0' comment '點選率=點選數/展示數', note text not null default '' comment '備註', date varchar(255) not null default '統計日期', mtime int unsigned not null comment '修改時間', ctime int unsigned not null comment '建立時間', primary key ("id"), unique key unique_date_appid ("date","app_id"), key idx_date ("date"), key idx_ctime ("ctime") )engine=innodb default charset=utf8 comment '這是一張示例表';
需要注意的點如下:
1)所有的欄位要加commet註釋
由於我們建立的表也可能被其他人所用,因此加上comment註釋,其他人或者我們自己可以通過命令show create tabletb_example來查看錶的結果資訊。
2)、int 符號確定
如果確定整形為非負數,就將int設定為無符號型的,即int unsigned,可以多一半的值範圍,又能避免插入負數。int設定為無符號的場景在很多場合都使用。
3)、不定長varchar的長度設定
對於不定長字串varchar如果不確定字串長度(且知道字串長度小於255)可以設定為vachar(255),此時,儲存空間只比正常的多一個位元組(與設定varcahr(10)額外儲存的空間是一樣的),又能夠最大限度的利用varchar的特定。注意:超過255則用於儲存該長度的空間會多於一個位元組。具體參考:高效能MySQL。
4)、有限狀態的型別設定
對於表示狀態數值的資料型別建議設定為tinyint unsigned(只佔用一個位元組的空間) 可以表示0到255的範圍。注意:無需用int,佔用四個位元組的空間。
5)欄位建立時間ctime和修改時間mtime
每個表中儘量加上欄位建立時間ctime和欄位修改時間mtime,便於後期排查問題,知道該條記錄是何時插入,何時修改。
6)、日期時間設定為int時的查詢
這裡的ctime表示建立時間,用的是unix時間戳來儲存,但是不能設定預設值unix_timestamp(),我們在實際查詢的時候,可以使用from_unixtime(ctime)來將unix時間戳轉為date日期格式。
示例如下:
insert into tb_example(app_id, app_name, click_cnt, disp_cnt, status, click_rate, note, date, mtime, ctime) values (1, 'timApp', 12, 6, 1, 0.50, '這是備註', '20170815', 1502796713, 1502796713);
select *, FROM_UNIXTIME(mtime), FROM_UNIXTIME(ctime) from tb_example;
效果如下:
7)所有的欄位儘量設定為not null。
8)儘可能的設定default的值
比如:app_name 中通過設定default ‘’,click_cnt設定default ‘0’。
9)將有可能要進行查詢的欄位設定為索引
比如:key idx_date(“date”),這裡因為可能會查詢一段時間內的資料,因此新增欄位“date”的索引。注意:一般索引的命名規則是idx_欄位名
10)設定唯一索引
根據業務確定哪些欄位或者欄位組合的值是唯一的,則將該欄位或欄位組合設定為唯一索引。
比如:unique keyunique_date_appid(“date”, “app_id”) 這裡因為根據業務我們只要對於具體的某一天具體的某個應用的記錄一定只能有一條,因此,設定聯合唯一索引可以防止改天對應的該應用的資料重複插入。注意:唯一索引的命名規則為:unique_欄位1_欄位2。
一個小知識點:
由於我們添加了唯一索引unique_date_appid,如果插入重複的date 和 app_id組合,則會報聯合索引重複錯誤,比如,再次執行:
insert into tb_example(app_id, app_name, click_cnt, disp_cnt, status, click_rate, note, date, mtime, ctime) values (1, 'timApp', 12, 6, 1, 0.50, '這是備註', '20170815', 1502796713, 1502796713);
提示:
但是,我們在很多場景時,不希望執行SQL語句報錯,而是提示重複插入,此時,可以利用insert ignore into語句,將上述SQL語句改為:
insert ignore into tb_example(app_id, app_name, click_cnt, disp_cnt, status, click_rate, note, date, mtime, ctime) values (1, 'timApp', 12, 6, 1, 0.50, '這是備註', '20170815', 1502796713, 1502796713);
提示:
我們可以通過返回結果result進行判斷,如果result為0,則表示重複插入。