轉自互聯網整理.
優化之路高級進階——表的設計及優化
優化①:創建規范化表,消除數據冗余
數據庫范式是確保數據庫結構合理,滿足各種查詢需要、避免數據庫操作異常的數據庫設計方式。滿足范式要求的表,稱為規范化表,范式產生於20世紀70年代初,一般表設計滿足前三范式就可以,在這里簡單介紹一下前三范式。
通俗的給大家解釋一下(可能不是最科學、最准確的理解)
第一范式:屬性(字段)的原子性約束,要求屬性具有原子性,不可再分割;
第二范式:記錄的惟一性約束,要求記錄有惟一標識,每條記錄需要有一個屬性來做為實體的唯一標識。
第三范式:屬性(字段)冗余性的約束,即任何字段不能由其他字段派生出來,在通俗點就是:主鍵沒有直接關系的數據列必須消除(消除的辦法就是再創建一個表來存放他們,當然外鍵除外)
當然,其實我們經常打破第三范式。。。且不可避免的,其實就是要在數據冗余和處理速度之間找到合適的平衡點。
優化②:合適的字段屬性
先舉個例子:
以前我做過的p2p中項目中,關於資金流水類型的字段的選取。本來資金流水類型總共就那么十幾種,基本固定死的,那我們就可以選擇tinyint(4)就完全足夠了,對應的是java的byte。 (要知道的是,tinyint的長度就是8位,tinyint(1)和tinyint(4)只是顯示長度)
下面以下給出幾個字段的建議:
1)數值型字段的比較比字符串的比較效率高得多,所以字段類型盡量使用最小、最簡單的數據類型。如IP地址可以使用int類型,如我上面的例子。
2)建議不要使用DOUBLE,不僅僅只是存儲長度的問題,同時還會存在精確性的問題。
3)對於整數的存儲,在數據量較大的情況下,建議區分開 TINYINT / INT / BIGINT 的選擇(當然,那已經是很老的事情了,現在其實不差這點性能)
4)char是固定長度,所以它的處理速度比varchar快得多,但缺點是浪費存儲空間,不能在行尾保存空格。在MySQL中,MyISAM建議使用固定長度代替可變長度列;InnoDB建議使用varchar類型,因為在InnoDB中,內部行存儲格式沒有區分固定長度和可變長度。
5)盡量不要允許NULL,除非必要,可以用NOT NULL+DEFAULT代替。
6)text與blob區別:blob保存二進制數據;text保存字符數據,有字符集。text和blob不能有默認值。
實際場景:text與blob主要區別是:
text用來保存字符數據(如文章,日記等),blob用來保存二進制數據(如照片等)。
blob與text在執行了大量刪除操作時候,有性能問題(產生大量的“空洞“),為提高性能建議定期optimize table 對這類表進行碎片整理。
7)自增字段要慎用,不利於數據遷移
8)強烈反對在數據庫中存放 LOB 類型數據,雖然數據庫提供了這樣的功能,但這不是他所擅長的,我們更應該讓合適的工具做他擅長的事情,才能將其發揮到極致。(反正我么碰到過LOB類型數據)
9)盡量將表字段定義為NOT NULL約束,這時由於在MySQL中含有空值的列很難進行查詢優化,NULL值會使索引以及索引的統計信息變得很復雜,可以使用0或者空字符串來代替。
10)盡量使用TIMESTAMP類型,因為其存儲空間只需要 DATETIME 類型的一半,且日期類型中只有它能夠和實際時區相對應。對於只需要精確到某一天的數據類型,建議使用DATE類型,因為他的存儲空間只需要3個字節,比TIMESTAMP還少。
優化③:索引
索引是一個表優化的重要指標,在表優化中占有極其重要的成分,所以上篇索引優化詳解沒看過的可以先看看,這里不再贅敘。
優化④:表的拆分(大表拆小表)
1、垂直拆分(其實就是列的拆分將原來的一個有很多列的表拆分成多張表)
注意:垂直拆分應該在數據表設計之初就執行的步驟,然后查詢的時候用jion關鍵起來即可;
通常我們按以下原則進行垂直拆分:
把不常用的字段單獨放在一張表;
把text,blob等大字段拆分出來放在附表中;
經常組合查詢的列放在一張表中;
缺點也很明顯,需要使用冗余字段,而且需要join操作。
2、水平拆分( 如果你發現某個表的記錄太多,例如超過一千萬條,則要對該表進行水平分割。水平分割的做法是,以該表主鍵的某個值為界線,將該表的記錄水平分割為兩個表。)
當然,我們還可以用增量法。如流水這類不會改變的數據,我們用增量查詢。
1.創建一張日充值表,記錄每天充值總額
2.每天用定時器對當前充值記錄進行結算
3.創建每月充值表,每月最后一天用定時器計算總額
4.則要查詢總額,則從月報表中匯總,再從日報表查詢當天之前的數據匯總,再加上今天的使用當天流水表記錄今天的流水,三張表加起來,匯總。這樣子效率是極好的!
優化⑤:傳說中的‘三少原則’
①:數據庫的表越少越好.
②:表的字段越少越好.
③:字段中的組合主鍵、組合索引越少越好.
當然這里的少是相對的,是減少數據冗余的重要設計理念。