關於數據庫的幾點總結

範式與冗餘

滿足數據庫的範式的目的就是爲了減少或消除冗餘,所以兩者是一對矛盾,即滿足範式可能就會出現冗餘,而冗餘就滿足不了範式。所以在數據庫的設計中要做一個平衡。
個人經驗在以下場景可以考慮冗餘

  1. 爲了查詢性能,減少io次數,比如冗餘user_name,不需要爲了顯示用戶名而再進行一次io,而這種場景帶來的一個問題就是數據不一致,需要根據具體業務而定。
  2. 業務需要的數據冗餘,比如訂單的快照信息,因爲用戶下單那一刻的數據要快照下來以備查,防止以後產品信息的修改,影響訂單的數據。

數據庫範式的優點就是減少存儲,如果有網絡傳輸也會減少網絡帶寬,提高傳輸速度。比如說某種數據的原始數據的訂閱,儘量滿足數據範式,而需要在訂閱端對數據進行進一步的解析處理,即適當加一些冗餘,以滿足查詢性能。

總結起來就是空間和時間的平衡。

字段類型

  • char與varchar 的區別
    char 是定長而varchar 是變長,儘量使用varchar 提高磁盤的使用率。
    如果使用char 時,要注意' '的length長度。
  • int bigint
    如果業務上不會出現負數,儘量用unsigned。避免空間浪費。
  • long(unsigned int) timestamp datetime
    long 和timestmp的存儲是相對於1970-1-1 的時間戮,而timestamp實際上是int的一種封裝,都是4個字節INT,數據精確到秒級別。在MySQL 5.6.4及之後版本,可以將時間戳類型數據最高精確微秒(百萬分之一秒),數據類型定義爲timestamp(N),N取值範圍爲0-6。所以使用long 會更精確,而可讀性較差,性能相同。
    而datetime 實際上類似於string,但佔用8字節空間。不隱含時區概念,舉個例子:同樣的字段如果用datatime 存儲,在中國看和美國看(修改計算機時區)都是一致的,而timestamp和long 則會有時區的差異。一致情況下儘量用long 和timestamp,而在業務聲景需要時,比如機票的時間都是本地時間,全球來看都是這個時間,所以要用datatime。
  • 字符集的選擇
    如果是內容中包含手機表情包儘量用utf8mb4。
  • 字段爲空
    這個也是比較有爭議的討論,有人認爲數據庫應該根據業務來設計,業務場景的null 和''或0不是一個概念,那麼儘量滿足業務。而蔥技術角度思考,字段儘量不爲空,並加默認值,因爲數據的null是不會被索引的,查詢的性能會有影響。
  • float double vs big decimal
    計算機底層用十進制的科學計數法來表示float double,這種表示法會產生一定的誤差(計算機組成及彙編語言原理P17)有解釋爲什麼。所以這裏所有與錢相關的類型最都要使用bigdeciaml。

where 子句

  • where 子句儘量限制在安全範圍內,比如更新某個的訂單狀態,最好加上當前用戶的id 限制以防止被其他用戶更新。
  • update 和delete 語句會對查詢的記錄加間隙鎖,間隙鎖的作用是防止,在update或者delete的時候修改了後面插入的數據。由於間隙鎖的產生在高併發的條件下,會產生死鎖。爲避免死鎖,在批量更新和刪除時,可以先批量差出來再通過主鍵id更新。
  • where 子句不要現在函數,常見的如now(),因爲函數不走索引。
  • where 子句的查詢併發較高,字段較少且比較穩定時,需要創建複合索引,以儘量闢免全表掃描。
  • 作爲編碼原則,應儘量遵守最左匹配原因,即最大化的利用索引。

field 字段

查詢盡避免*,即減少磁盤io也減少網絡開銷。

order by

  • 需要創建索引,有必要的情況需要複合索引。
  • 爲避免深度分頁,一般分通過業務的排序字段來實現淺分頁。而order by 如果非主鍵的情況,可能會出現重複(因爲limit n 出現多條只取m條m<n 這裏存在隨機情況)對最終的查詢結果會產生影響。所以最盡最在order by 後邊加上主鍵id。以避免重複。

b+tree vs b tree

balance-tree 讀(b tree)因爲中文教科書印刷原因,很多教授讀b減樹,這裏糾正一下。



b+tree


從上圖可知b+tree 是比較適合mysql 索引結構的,兩點原因

  1. 索引塊不存在數據,只包含索引和指針,這樣可以最大化的讀取索引,從而減少索引的io操作。
  2. 數據節點間存在指針,以保證順序。
    所以索引的條件儘量保證範圍是確定的比如= >= <= like 'prefix%' 會走索引,而!= like '%' in not exist 等將不會走索引,而null值不會包含在索引中,上文已經提到。

以上爲經驗之談,可能不夠嚴謹,未免有漏洞,有問題請專業dba指正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章