命名規範:mysql
1表名,字段名,索引名稱使用小寫字母,數字採用下劃線進行分割sql
2.表名採用模塊名3個縮小字符 ‘前綴’以後順序爲代表數據庫
3.表名,字段名不超過32個字符緩存
4.存儲屍體數據的表,名稱使用名詞,單數併發
5.索引 採用‘inx’開頭分佈式
6.不使用保留字函數
7.存儲實體表間多對多關係,名稱建議採用‘noun_verb_noun’好比‘member_like_tag’高併發
在sql語句中保留字一概使用大寫性能
字符串使用單引號優化
好比:
SELECT id,title FROM xiaoqu WHERE id=1
SELECT id,title FROM xiaoqu WHERE areacoe=’10002’;
錯誤寫法:
-- 錯誤
select ID, title from XiaoQu where id = 1
SELECT id, title FROM xiaoqu WHERE areacode = "000100010001"
關於表的設計
默認使用innodb存儲引擎
字符集使用utf-8
>charset 爲‘utf-8’;校驗規則 collation ‘utf_gereral_ci’
效率優先,提示性能
適當的犧牲範式,加入冗餘
會增長代碼複雜度
關於正確的使用時間類型:
精確到秒 採用timestamp
精確到時間 使用date
通常不適用datetime
每一個表都應該含有插入時間和更新時間 這個字段
不容許用字符串去存儲時間
字段儘可能定義爲not null
給默認值 ‘’
爲何要這樣作的緣由,進行查詢的優化,可能這個字段會添加索引(爲null狀況下,會額外增長建立索引的開銷) 含有null的複合索引無效
相似於性別這樣的固定狀態的東西 優先使用enum和set
enum佔用一個字節,轉爲數值進行運算
set視節點定,最多使用8個字節
用好數值類型
原則:適用就好,越小越好
> TINYINT< SMALLINT < MEDIUMINT < INT < BIGINT
>
> 1 Byte/2 Bytes/3 Bytes/4 Bytes/8 Bytes
> FLOAT(4B)/DOUBLE(8B)
>
> DECIMAL(M,D) (M+2 B)
關於金錢這樣常常參與運算的數據類型使用整形,不適用浮點數類型
> 例如金額能夠用分爲單位,而後採用 `INT`。若是依然要以元爲單位,能夠採用 `DECIMAL`。
數值類型和字符串類型進行比較
數值類型的效率更高,查詢更快速,佔用空間小
### 使用 INT UNSIGNED 來存儲 IPv4 地址
> 使用 `INET_ATON` 將 IP 地址的字符串形式轉換成數字形式;使用 `INET_NTOA` 將 IP 地址數字形式轉換成字符串形式,以便查看。
>
> 當要查詢某段的 IP 時,請參考如下示例:
### 不直接存儲圖片、音頻、視頻等大容量內容
> 請使用分佈式文件系統來存儲圖片、音頻、視頻等內容。數據庫裏只存儲文件的位置。
### 少用並拆分TEXT/BLOB
> TEXT類型處理性能遠低於VARCHAR
爲何儘可能不要使用text/blob這樣的字段
強制生成硬盤臨時表
浪費空間
varchar(65535)=>64K
如需使用請拆分到獨立的表進行存放;
一張表中若是有不少的字段,是壞的設計
請考慮io高效,表修復,alter快/高併發
> 一個表有不少不少字段,是壞設計的味道。請再認真考慮設計是否正確。
> IO高效/表修復快/Alter快/高併發
> 以1G Size 500W Rows來評估
>
> - 順序讀取需N秒
> - 單行不超過200Byte
> - 單表不超50個INT字段,不超20個CHAR(10)字段
> - 單表字段數上限控制在20-50個
關於索引:
合理的建立索引:
索引的做用,優化查詢
減慢更新
索引的添加綜合評估數據的密度和數據的分佈
結合核心sql優先考慮覆蓋索引
### 使用數字主鍵
> 存儲實體數據的表,其主鍵應該是數字類型。
### 不使用聯合主鍵
> 存儲實體數據的表,不使用聯合主鍵。
> 存儲實體表間多對多對應關係的表(僅有兩個字段)容許例外。
### 不使用外鍵
> 全部的表不創建外鍵約束。
### 聯合索引字段數不超過 5 個
> 一個聯合索引的字段數太多,極可能是設計得很差,還很難符合命名的規範。
### 前綴索引長度不超過 8 個字符
> 對字符串類型的字段創建索引,採用前綴索引,且長度不超過 8 個字符。
### 不使用負向查詢
> 負向查詢是指,若是查詢條件描述的是不要什麼數據,其他的都要。例如 `!=`、`<>`、`NOT EXISTS`、`NOT IN` 以及 `NOT LIKE` 等就是負向查詢,它們利用索引將會很辛苦。
### 一次查詢的結果集不超過 100 行
> 必要時使用 `LIMIT 100`
### LIMIT m, n,其中 m 應當小於 500
> 使用 `SELECT ... LIMIT offset, row_count` 或者 `SELECT ... LIMIT row_count OFFSET offset` 時,當 offset 小於 500 時,容許使用。
>
sql
-- 容許
SELECT ... FROM property WHERE broker_id=? ORDER BY update_time LIMIT 40, 20
-- 不容許
SELECT ... FROM property WHERE areacode=? ORDER BY update_time LIMIT 4000, 20
避免使用count()函數;
> 能不使用就不使用,儘可能用其餘方法來解決。
-- 正確
SELECT 1 FROM propertys WHERE broker_id=? LIMIT 1
-- 錯誤
SELECT COUNT(*) FROM propertys WHERE broker_id=?
在代碼中能夠經過獲取size(),或者length得到長度
### 一次 COUNT() 可能掃描的行數應當確保小於 500 行
> `COUNT()` 函數須要掃描全部的結果集以後才能得出結果。而結果集的大小須要業務知識來判斷(`EXPLAIN` 方法只能來來檢驗某一個條件下的當前狀況)。所以須要使用 `COUNT()` 查詢的代碼應當通過審閱。
爲何使用count(*) 除非真的想統計nullable的字段;
### 不在索引列作運算
> 不在索引列進行數學運算或函數運算
> - 沒法使用索引
> - 致使全表掃描
舉例:
root:xxx_db> select BrokerId from ajk_propertys where proid-100=101960636;
1 row in set (5.11 sec)
儘可能不要再數據庫上作運算
複雜的sql運算轉移到程序端cpu
簡單實用mysql
### 同數據類型的列值比較
> 原則:數字對數字,字符對字符
> 字符列與數值類型比較
> 數值列於字符列比較
> - 同時轉換爲雙精度進行比較
> 字符列於數值列比較
> - 字符列整列轉數值,不會使用索引
sql
-- 禁止
SELECT id FROM property WHERE NOW() - update_time < 3600
SELECT id FROM property WHERE update_time + 3600 > NOW()
-- 改成
SELECT id FROM property WHERE update_time > NOW() - 3600
sql
-- 禁止
SELECT id FROM property WHERE CHAR_LENGTH(title) > 20
sql
-- 假設字段 property.status 的類型爲 TINYINT
-- 禁止
SELECT id FROM property WHERE status = '1'
-- 改成
SELECT id FROM property WHERE status = 1
### 禁止隱式類型轉換
> 不只在查詢條件中禁止隱示類型轉換,`INSERT`,`UPDATE` 也不容許隱式類型轉換。
```
sql
-- 假設字段 property.status 的類型爲 TINYINT
-- 禁止
INSERT INTO property (..., status) VALUES (..., '1')
UPDATE property SET status = '1' WHERE id = '43'
-- 改成
INSERT INTO property (..., status) VALUES (..., 1)
UPDATE property SET status = 1 WHERE id = 43
### 禁止使用 % 前導查詢
> 儘可能不使用 `LIKE` 查詢,不得不用的狀況下也禁止使用 `%` 前導查詢。
> - 使用不了索引
> - 致使全表掃描
### 禁止SQL語句拼接
> 應用程序不能有拼接語句出現
拒絕3B
大sql(拆分)
大事物 (contrller 不適用事物,在service層開啓)
大批量(使用load data)
> 大SQL VS 多個簡單SQL
>
> - 傳統設計思想,BUT Mysql NOT
> - 一條SQL只能在一個CPU運算
> - 1000+ QPS的高併發中,1秒大SQL可能把數據庫都堵死
> 拒絕大SQL,拆解成多條簡單SQL
> - 簡單SQL緩存命中率更高
> - 減小鎖表時間,特別是MYISAM
> - 用上多CPU
> 不一樣字段,將or改成union
> - 減小對不一樣字段進行 or 查詢
> - Merge index 每每很弱智
保持事物鏈接儘可能短小
即開即用,用完就關
減小鎖資源佔用
不破壞一致性的前提小,使用多個短事物代替長事物;
> 統一字符集爲UTF8
> 禁用子查詢
> - 大部分狀況優化較差
> - 特別是Where中使用IN id的子查詢
> - 通常可用JOIN改寫
### 約定類規範(二)
> 永遠不在程序端顯示加鎖
> - 永遠不在程序端對數據庫顯式加鎖
> - 外部鎖對數據庫不可控
> - 高併發是災難
> - 極難調試和排查
> 可採用事務操做
```舉例:Select GET_LOCK(‘str’)```### 約定類規範(三)> 請不要使用存儲過程> 請不要使用trigger