數據庫的使用你可能忽略了這些

數據庫的管理是一個很是專業的事情,對數據庫的調優、監控通常是由數據庫工程師完成,可是開發人員也常常與數據庫打交道,即便是簡單的增刪改查也是有不少竅門,這裏,一塊兒來聊聊數據庫中很容易忽略的問題。mysql

字段長度省着點用

先說說咱們經常使用的類型的存儲長度:redis

列類型 存儲長度
tinyint 1字節
smallint 2字節
int 4字節
bigint 8字節
float 4字節
decimal(m,d) 0-4字節
datetime 8字節
timestamp 4字節
char(m) m個字節
varchar(m) 可變長度
text 可變長度

很明顯,不一樣的類型存儲的長度有很大區別的,對查詢的效率有影響,字段長度對索引的影響是很大的。算法

  • 字符串字段長度都差很少的,能夠預估長度的,用char
  • 字符串長度差別大,用varchar,限制長度,不要浪費空間
  • 整型根據大小,選擇合適的類型
  • 時間建議用timestamp
  • 建議使用decimal,不建議使用float,若是是價格,能夠考慮用int或bigint,如1元,存儲的就是100

放棄uuid(guid)的使用

不論是uuid,仍是guid,使用的時候都是爲了不同時生成重複的ID,可是建議考慮其餘方案,緣由以下:sql

  • uuid沒有順序
  • uuid太長
  • uuid規則徹底不可控

推薦的方案用bigint(首選),或者char來存儲,生成方式參考snowflake的算法,有順序、長度固定、比uuid更短,固然,也幾乎不會重複。mongodb

大表減小聯表,最好是單表查詢

單表查詢的優點不少,查詢效率極高,便於分表分庫擴展,可是不少時候你們都以爲真正實現起來不太現實,徹底失去了關係數據庫的意義,可是單表的性能優點太明顯,通常總會有辦法解決的:數據庫

  • 合理的冗餘字段
  • 配合內存數據庫(redis\mongodb)使用
  • 聯表變屢次查詢(下文會有說明)

若是考慮都後期數據量大,須要分表分庫,就應該儘早實時單表查詢,如今的數據庫分表分庫的中間件基本都沒法支持聯表查詢。即便如mycat最多支持兩個表的聯表查詢,可是也有很明顯的性能損耗。緩存

索引的正確處理方式

索引的優點這裏就很少說了,索引使用不當會有反效果:微信

  • 數據量很小的表,不須要索引
  • 一個表的索引不宜過多,建議最多就5個,索引不可能知足全部的場景,可是了個知足絕大部分的場景
  • mysql 和 sqlserver的索引差異還挺大的,須要注意。例如:
    mysql索引字段的順序對性能有很大影響,sqlserver優化過,影響很小

多查幾回比聯表可能要好

提出這個方案相信會獲得不少人的反對,可是我相信這個結論仍是很是適合數據量大的場景。多查幾回數據庫有這麼幾個弊端:網絡

  • 增長了網絡消耗
  • 增長了數據庫的鏈接數

其實,這兩個問題在如今基本均可以忽略的,數據庫和應用的鏈接基本都是內網,這個網絡鏈接的效率仍是很高的。數據庫對鏈接池的優化已經比較成熟了,鏈接數只要不是太多,影響也不會太嚴重,可是多查幾回的優點卻不少:框架

  • 單表效率更高
  • 便於後期擴展分表分庫庫
  • 有效利用數據庫自己的結果緩存
  • 減小鎖表,聯表會鎖多個表

固然,多查幾回這個度必定要把握。千萬不要在一個循環裏面查詢數據庫。咱們也應該儘可能減小查詢數據庫的次數。咱們能夠接受1次查詢變2次查詢,若是你變成10次查詢,那就要放棄了。
舉個例子:
查詢商品的時候,須要顯示分類表的分類名

select category.name,product.name from product  inner join category on p.categoryid=category.id

建議的方式:

select categoryid,name  from product 
select categoryname from category where categoryid in ('','','','')

固然,你能夠再優化一下,查詢分類名以前,對product的categoryid排序一下,這樣速度更快。由於咱們前面已經用snowflake生成了有順序的主鍵了。
補充一下,in的效率並非你想象的那麼慢,若是保持在100個節點(不少書籍介紹1000個節點,咱們保守一點),性能仍是很高的。

儘可能使用簡單的數據庫腳本

不少用過 .net Entity Framework 的人都說這個框架太慢,其實慢主要是兩點:錯誤的使用延遲加載(外鍵關聯)、生成SQL編譯太慢。Entity Framework生成的SQL腳本有太多沒用的東西,致使編譯太慢。
數據庫腳本儘可能使用簡單的,不要用太長的一個SQL腳本,會致使初次執行的時候,編譯SQL腳本花費太多的時間。

儘可能去避免聚合操做

聚合操做如count,group等,是數據庫性能的大殺手,常常會出現大面積的表掃描和索表的狀況,因此你們能看到不少平臺都把數量的計算給隱藏了,商品查詢不去實時顯示count的結果。如淘寶,就不顯示查詢結果的數量,只是顯示前100頁。
避免聚合操做的方法就是將實時的count計算結果用字段去存儲,去累加這個結果。固然,也能夠考慮用spark等實時計算框架去處理,這種高深的技術,不在這次討論範圍內。(PS:主要是我也不懂)

總結

程序的優化不少時候都是一些細節的問題,更應該注意平時的積累,阿里SQL的規範有不少能夠吸收的地方,以上也是本身工做中的一些總結,歡迎你們補充。
(完)


歡迎你們關注個人公衆號交流、學習、第一時間獲取最新的文章。
微信號:itmifen

相關文章
相關標籤/搜索