## 1、選擇合適的數據類型
`數據類型的選擇,重點在于'合適'二字,如何確定選擇的數據類型是否合適?`
* 使用可以存下你的數據的最小的數據類型。
* 使用簡單的數據類型。Int 要比 varchar 類型在 MySQL 處理上簡單。
* 使用int來存儲日期時間,利用FROM\_UNIXTIME\(\),UNIX\_TIMESTAMP\(\)兩個函數來進行轉換;
* 盡可能的使用 not null 定義字段。
* 盡量少用text類型,非用不可時最好考慮分表。
* 使用bigint來存儲IP地址,利用INET\_ATON\(\),INET\_NTOA\(\)兩個函數來進行轉換;
## 2、數據庫表的范式化優化
* 范式化是指數據庫設計的規范,目前說到范式化一般是指第三設計范式,也就是要求數據表中不存在非關鍵字段對任意候選關鍵字段的傳遞函數依賴則符合第三范式。

* 上圖存在以下傳遞函數依賴關系:
\(商品名稱\)->\(分類\)->\(分類描述\)
也就是說存在非關鍵字段"分類描述"對關鍵字段"商品名稱"的傳遞函數依賴。
* 不符合第三范式要求的表存在下列問題:
* 數據冗余:\(分類,分類描述\)對于每一個商品都會進行記錄;
* 數據的插入異常;
`當表中沒有飲料商品時,就沒有地方記錄飲料分類的相關信息。`
* 數據的更新異常;
`當想更新飲料商品的描述信息,就要把表中所有的飲料分類描述信息更新`
* 數據的刪除異常。
`刪除飲料的所有商品后,也就無法選擇飲料這個分類,此稱為'刪除異常'`

## 3、數據庫表的反范式化優化
`反范式化是指為了查詢效率的考慮把原本符合第三范式的表‘適當’的增加冗余,以達到優化查詢效率的目的,反范式化是一種以空間來換取時間的操作。`

* 思考如何查詢訂單信息?
```sql
SELECT b.用戶名,b.電話,b.地址,a.訂單ID,SUM(C.商品價格*c.商品數量) as 訂單價格
FROM '訂單表' a
JOIN '用戶表' b ON a.用戶ID=b.用戶ID
JOIN '訂單商品表' c ON c.訂單ID=b.訂單ID
GROUP BY b.用戶名,b.電話,b.地址,a.訂單ID
```
* 對上面的表進行了反范式化后

```sql
SELECT a.用戶名,a.電話,a.地址,a.訂單ID,a.訂單價格 FROM '訂單表' a;
```
## 4、數據庫表的垂直拆分
所謂的垂直拆分,就是把原來一個有很多列的表拆分成多個表,這解決了表的寬度問題。通常垂直拆分可以按以下原則進行:

* 把不常用的字段單獨存放到一個表中。
* 把大字段單獨存放到一個表中。
* 把經常一起使用的字段放到一起。
>垂直拆分更多時候就應該在數據表設計之初就執行的步驟,然后查詢的時候用jion關鍵起來即可;
## 5、數據庫表的水平拆分
表的水平拆分主要是為了解決單表的數據量過大的問題,水平拆分的表每一個表的結構都是完全一致的。
常見的拆分方法為:
* 對 customer\_id 進行 hash 運算,如果要拆分成5個表則使用mod\(customer\_id,5\) 取出0-4個值;
* 針對不同的hashID把數據存到不同的表中。
### 水平拆分的一些技巧
**1. 拆分原則**
通常情況下,我們使用取模的方式來進行表的拆分;比如一張有400W的用戶表`users`,為提高其查詢效率我們把其分成4張表`users1,users2,users3,users4`
通過用ID取模的方法把數據分散到四張表內`Id%4+1 = [1,2,3,4]`
然后查詢,更新,刪除也是通過取模的方法來查詢
```
$_GET['id'] = 17,
17%4 + 1 = 2,
$tableName = 'users'.'2'
Select * from users2 where id = 17;
```
在insert時還需要一張臨時表uid_temp來提供自增的ID,該表的唯一用處就是提供自增的ID;
```
insert into uid_temp values(null);
```
得到自增的ID后,又通過取模法進行分表插入;
>注意,進行水平拆分后的表,字段的列和類型和原表應該是相同的,但是要記得去掉auto_increment自增長
**另外**
* 部分業務邏輯也可以通過地區,年份等字段來進行歸檔拆分;
* 進行拆分后的表,只能滿足部分查詢的高效查詢需求,這時我們就要在產品策劃上,從界面上約束用戶查詢行為。比如我們是按年來進行歸檔拆分的,這個時候在頁面設計上就約束用戶必須要先選擇年,然后才能進行查詢;
* 在做分析或者統計時,由于是自己人的需求,多點等待其實是沒關系的,并且并發很低,這個時候可以用union把所有表都組合成一張視圖來進行查詢,然后再進行查詢;
```
Create view users as select from users1 union select from users2 union.........
```