1. 程式人生 > >高效能MYSQL筆記-mysql欄位型別和欄位設計規範

高效能MYSQL筆記-mysql欄位型別和欄位設計規範

1.優先使用符合業務需要的最小的資料型別
1.1 將ip用UNSIGNED INT存:內建函式INET_ATON(字串)和INTE_NTOA(整數)分別是點分十進位制字串和整數的轉換函式
1.2 非負數用無符號型別(比如前面ip值對應的數字一定為正,所以用的資料型別為無符號整形,ip是8為*4=32位,也就是而int也正好是32位,而ip對應的全是正的,如果是用有符號int存的話那就只能表示一半,所以要用無符號int)
1.3不要用TEXT,BLOB,或者把他們都分離到單獨的擴充套件表中




2.使用列舉(ENUM)型別代替字串
2.1列舉型別在內部實際儲存為整數,並且在表的.frm檔案中儲存“數字-字串”對映關係的“查詢表”
2.2可以通過SELECT 列舉型別的列+0 FROM 表名來隱式轉換來看到具體的整數
2.3不要用數字作為ENUM列舉常量(如ENUM('1','2','3')),這種雙重性容易導致混亂
2.4列舉欄位是按照內部儲存的整數而不是定義的字串進行排序,但可以用FIELD()函式顯式地指定排序順序如:SELECT e FROM enum_test ORDER BY FIELD(e,'apple','dog','fish');(e是列舉欄位),不過這會導致MySQL無法利用索引消除排序(什麼叫索引消除排序呢:就是說在查詢中對索引欄位排序,那這時其實是不用在執行一遍排序演算法的,因為B+樹儲存索引,而B+樹中維護的資訊可以很快得到索引的順序,相當於索引本身就是以有序的狀態儲存的。但這裡你把他的原來的排序規則打破了,也就是顯式地指定了排序順序,那也就是相對於你規定的排序規則,資料庫儲存的索引是無序的)
2.5列舉最不好的地方在於字串列表是固定的,新增或刪除字串必須使用ALTER TABLE,所以對於會改變的字串,不要使用列舉。




3.char 和 varchar
3.1 char是定長,varchar是變長,也就是varchar節省空間(除非使用ROW——FORMAT=FIXED建立的話)
3.2 因為varchar是變長的,所以UPDATE時如果長度變長,就會做額外的工作
3.3 下列情況使用varchar:字串列的最大長度比平均長度大很多;列的更新很少(所以碎片不是問題);使用了像UTF8這樣的字符集(每個字元都使用不同的位元組數進行儲存)
3.4 CHAR適用情況:很短,或者所有值都接近同一個長度(如MD5);列經常變更
3.5 末尾空格問題:高版本varchar會保留末尾空格;char和低版本varchar會剔除末尾空格。
3.6 CHAR(N),VARCHAR(N)中N表示字元數,而非位元組數(中文字元在UTF8中佔用3位元組)
3.7 雖然VARCHAR(N)資料型別在磁碟中存的就是他所表示的字串的大小,但是讀取到記憶體中的時候記憶體是會給他分配N*k+1or2(N<=255,1;else 2;)(k根據字符集決定)




4. 儘可能吧所有列定義為NOT NULL
4.1索引NULL列要額外的空間
4.2進行比較和計算時會對null值進行處理,可能導致索引失效




5. 時間日期資料型別
5.1 不要用字串儲存日期型資料,浪費空間
5.2 DATE能儲存從1001到9999年,精度為秒,他把日期和時間封裝到格式為YYYYMMDDHHMMSS的整數中,使用8位元組
5.3 TIMESTAMP儲存了從1970年以來的秒數,和Unix時間戳相同,只能儲存1970到2038,使用4位元組
5.4 FROM_UNIXTIME()和UNIX_TIMESTAMP()兩個函式轉換日期和Unix時間戳
5.5 DATE和TIMESTAMP中存的是時間,但是是哪裡的時間呢???:前者不管哪裡,他就是一個時間表示(與時區無關),後者是格林尼治時間。。就是說儲存時DATE就按照給的時間存,TIMESTAMP則是在先根據所在時區和給的時間戳算出對應的格林尼治時間再存,訪問時DATE就按照他存的時間返回,TIMESTAMP則是根據存的時間戳(看作格林尼治時間)和所在時區算出所在時區的對應時間。
5.6 通常用TIMESTAMP,空間效率高
5.7 MYSQL沒有提供比秒更小粒度的日期和時間值,如果需要,可以用BIGINT儲存微妙級別的時間戳,或用DOUBLE儲存秒之後的小數部分。




6.整數型別
6.1 TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT,分別用8,16,24,32,64存
6.2 整數都有UNSIGNED可選屬性 
6.3 對於儲存和計算來說INT(1)和INT(20)是相同的,INT(N)中N只是規定了一些互動工具來顯示字元的個數

7.實數型別
1.金融類要用DECIMAL
2.DECIMAL可以儲存BIGINT範圍外的整數
3.FLOAT和DOUBLE使用標準的浮點運算進行近似計算