總結做爲開發人員重點注意的內容!這是一篇有關高性能MYSQL第四章schema相關的筆記。java
在項目中,數據庫表列有兩個text字段,用來存儲大文本,在數據規模達到40萬後,若是查詢沒命中索引,發現耗時會達到5s以上,在表中刪除這兩個大字段後,就算全表掃描,耗時也不過0.6s左右。mysql
解決方案:sql
datetime 和 timestamp 比較數據庫
相同點: 都能存儲日期、時間,精確到秒。服務器
不一樣點: timestamp 只佔 datetime 一半存儲空間,具有時區功能,同時容許的時間範圍小得多。框架
類型及存儲空間函數
int(11) 其中11只是指定顯示寬帶,對存儲空間無任何影響。性能
能夠指定類型爲unsinged,但java不支持unsinged, 使用相同類型可能會有麻煩。操作系統
精確類型:decimal, 不精確類型: double, float。設計
decimal 支持存儲和計算的精確。計算性能比浮點類型差一點。
decimal(11,4)表示支持4位精確小數,整數部分最多隻能有7位數字。
decimal類型4個字節存儲9個數字,decimal(18,9)佔用9個字節,前面9位整數佔4個字節,小數點1個字節,後面小數佔4個字節。
mysql5.0版本及以上,decimal 最多存儲65個數字。
浮點類型在表示一樣範圍,一般比decimal使用更少的空間。
在數據量比較大的狀況下,能夠用bigint代替decimal, 將小數的位數乘以相應的倍數轉爲bigint,可避免不精確的問題。
varchar 和char
varchar存儲可變長的字符串,使用額外的1個或兩個字節額外存儲空間,表示字符串的長度。
varchar在table指定row_format=fixed狀況下,也是定長的,這會致使空間的浪費。
varchar(256)使用一個字節存儲字符字符數。varchar(1000)使用兩個字節存儲字符數。
update varchar字段可能會致使列變得更長,innodb存儲引擎會致使出現分裂頁的狀況出現,myisam將行拆分紅不一樣的段存儲。
varchar適用場景:最長字符串比平均字符串長度長不少。
char是定長的,不容易產生碎片,適用於存儲密碼或md5值, 或表示性別,F/M, varchar(1)須要兩個字節,char(1)須要一個字節。
char 會截斷末尾的空格。
varchar(5)和varchar(100)都能存儲5個字符,但varchar(100)性能會比varchar(5)糟糕,因此最好選擇合適的長度。
text與blob類型
text存儲大文本,blob存儲二進制數據。
大文本有關的類型: tinytext, smalltext, text, mediumtext, longtext。
二進制有關的類型: tinyblob, smallbolob, blob, mediumblob, longblob。
當text,blob太大時,會做爲一個對象單獨存儲,行中使用指針指向數據位置。
我的建議少用或不用這種類型,或拆除到詳情表,減小對查詢帶來影響
enum類型
字段定義:animal enum("dog", "fish", "cat")
enum 實際存儲爲整數,並在.frm文件中保存字符串-整數
對應關係。
看個列子更容易明白:
create table enum_test( id int auto_increment, animal enum("dog", "fish", "cat"), primary key(id) ); insert into enum_test(animal) values ("dog"), ("cat"), ("dog"), ("fish") ;
對該表進行查詢:
select animal+0, animal from enum_test order by animal ;
能夠看到排序是按照整數排序的,即定義的順序進行排序,而不是字符串序。
解決方案:定義時按照字符串序定義。
自定義順序排序使用field函數,但這樣將沒法使用索引:
select animal+0, animal from enum_test order by field(animal, "cat", "fish", "dog");
字段join效率比較: enum join enum > varchar join varchar > enum join varchar = varchar join enum。
使用alter talbe 在枚舉類型中添加字符串時,會重建整個表,除非老是在末尾添加值。
壞處:當枚舉值爲數字時,很容易發生困惑,儘可能避免這種狀況。
datetime類型:
timestamp:
不推薦本身使用整數值來存儲時間,這和內部存儲沒什麼差異,沒帶來什麼好處卻多了額外的處理邏輯。
書中推薦使用timestamp, 我的推薦使用datetime,timestamp花活太多。
bit類型
bit列能夠存儲多個true/false值,bit(17)能夠存儲17個true/false值,myisam 使用一個比特來存儲一個單獨的true/false值,innodb使用最小的整數值來存儲bit列的值。
myisam: bit(17)使用17個比特存儲。
innodb: tinyint 便可存儲。
高性能mysql認爲應該慎用這個類型,因此就不深究了。
set 類型
好處: 存儲使用打包的位存儲,佔用空間少。
壞處: 沒法經過索引查找,修改列定義代價較高:須要alter table。
權限控制使用例子:
create table acl_test( id int not null auto_increment, perms set('can_read', 'can_write', 'can_delete'), primary key(id) ); insert into acl_test(perms) values ('can_read,can_write'), ('can_read,can_delete') ; select * from acl_test where find_in_set('can_write', perms) ;
查詢結果:
主鍵最好選擇自增id爲主鍵,對數據性能比較好,同時相對應orm也支持,可能存在某些orm層框架不支持聯合主鍵的狀況。
ip與int轉換函數: inet_aton(), inet_ntoa()。