一.設計規範
- 建表約束
- 必須有字段id(主鍵id,一般設置爲自增(步數爲1),當併發性需求較高的時候,不建議自增,可以自定義實現機制), create_time(建表時間), update_time(更新時間,設置爲自動更新)。
- 表名和字段名必須使用小寫字母或數字,禁止數字開頭,同時使用下劃線分割不同的單詞,Windows環境下Mysql忽略大小寫,Linux下大小寫是有區分的,因此爲了統一,全部是小寫字母加數字,同時命名不能用複數名詞,表明和字段名應用來表示含義。
- 表示有是否含義的字段時,必須用is_XXX來表示字段名,用tinyint unsigned(1是, 0否),當然也可以使用char(1)來表示'Y'(是), 'N'(否)。
- 同時禁止使用MySql保留字段,desc,range等,用過的同學應該知道這個會報錯。
- 主鍵的索引名必須爲pk_xxx,唯一索引名爲uk_xxx,普通索引名爲idx_xxx。
- 對於數字類型的定義比如bigint(1)與bigint(5)的原理和佔用空間都是一樣的,不同的長度是不同工具對數字的表形式不同,兩者沒有任何差別。
- 小數類型用decimal來儲蓄,儘量根據單位換算用Bigint unsigned等整形來表示,因爲MySql小數的運算相比整數消耗資源會更多一點。
- char用來表示定長字符,varchar用來儲蓄可變字符,根據需求進行字段長度的設置,可以多餘,但要適量。
- 對於業務上不發生改變的字段設爲枚舉,在MySql中枚舉的儲蓄也更加的緊湊,查詢的效率也更好點。
- 對於需要用有限數字來表示字段信息時,不要用‘0’來表示某種狀態,某些情況下JAVA中部分字段的默認值爲‘0’,可能會發生一些不必要的錯誤,正
- 索引約束
- 業務上唯一的字段,索引必須爲唯一索引。比如user_id(假設每個用戶只有一個id,若此字段需要建立索引,必須使用唯一索引。
- 在varchar字段上建立索引時,索引長度必須指定,根據業務情況的區分度來設置,一半20的區分度爲90%。
- 建立組合索引時,區分度高的在左邊。
- 同時,索引的數量單表至多6個,因爲索引的維護(頻繁的刪除和插入操作),會帶來比較高的資源消耗,因此不要在頻繁刪除和更新的字段加索引。
- 案列表
-
CREATE TABLE `product` ( `id` BIGINT ( 20 ) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID', `uuid` CHAR ( 32 ) NOT NULL COMMENT '產品UUID', `user_uuid` CHAR ( 32 ) NOT NULL COMMENT '用戶UUID', `pack_amount` SMALLINT ( 6 ) NOT NULL COMMENT '打包價格\r\n', `term` INT ( 10 ) UNSIGNED NOT NULL COMMENT '借款限期,單位-天', `remark` VARCHAR ( 5 ) DEFAULT '' COMMENT '備註', `product_type` TINYINT ( 4 ) NOT NULL COMMENT '產品類型(1:賺,2:借款,3:轉售)', `status` TINYINT ( 4 ) UNSIGNED NOT NULL COMMENT '產品狀態', `expend_rate` DECIMAL ( 16, 2 ) NOT NULL COMMENT '利率', `effective_time` datetime NOT NULL COMMENT '標的發佈的有效期(時間戳)', `create_time` datetime NOT NULL COMMENT '創建時間', `update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間', PRIMARY KEY ( `id` ), UNIQUE KEY `idx_uuid` ( `uuid` ), KEY `idx_user_uuid` ( `user_uuid` ), KEY `idx_create_time` ( `create_time` ) ) ENGINE = INNODB AUTO_INCREMENT = 2 DEFAULT CHARSET = utf8 COMMENT = '產品基礎信息表';
-
二.優化策略
- 字段的選取(最小原則)
- 越小的數據類型,通常處理的速度更快,因爲佔用的磁盤,內存,CPU緩存更少,處理時需要的CPU週期也更短。對於不確定的數值範圍,選取最小的可儲蓄類型。
數據類型 | 數值範圍 | 字節 | 常用場景 |
tinyint unsigned | 0-255 | 1 | 表示人的年齡等 |
smallint unsigned | 0-65535 | 2 | 烏龜年齡等 |
int unsigned | 0-42.9億 | 4 | 恐龍化石時間等 |
bigint unsigned | 0-10^19 | 8 | 太陽的年齡 |
char(N) | 最大爲N個字節 | N | 對於固定長度的字段(比如人名) |
varchar(N) | 最大爲N個字節,N儘量小於255/5000 | N | 根據業務需求 |
datatime | 1601-9999年 | 8 | 常用的日期儲蓄 |
timestamp | 1601-9999年 | 4 | 有自動更新機制,update_time |
- 簡單原則
- 簡單的數據類型需要的CPU週期更短,整形比字符整體的操作代價少很多,建議IP的儲蓄用整型。
- 儘量避免使用NULL
- 通常情況下,字段設置爲NOT NULL,NULL爲默認屬性,對於查詢來說有NULL的列,MySql優化很難,查詢起來會更麻煩,佔用的儲蓄空間可更多
三.SQL優化(常用)
- 查詢優化,在where以及order by 涉及的字段上建立索引。
- 避免使用where 屬性 = null,這樣MySQL會進行全局查詢。
- 避免在where使用 != 或 < > 等字段。
- 避免where 與 or 進行連接查詢,使用 union all 進行代替.
- 避免使用 in 和 not in 等,連續的範圍儘量用between
- 避免使用like "%XX%".
- 避免where 的字段使用表達式操作.where num/2 = x等
- 避免where的字段使用函數操作。
- 字段含有大量的相同值比如(sex..),索引的優化沒有效果,,MySQL根據字段的內容進行優化,因此進行建立索引;
- 索引提高的select 的效率,但降低了insert ,update的效率,建議索引最多建立6個.
- 字段的內容如果都爲數字的話,避免使用字符作爲屬性,字符根據每個字符進行比較,數字只會比較一次;
- select * from table,儘量使用字段代替 * ,減少查詢量,即使需要查詢字段也要用全部字段代替 *。