數據庫的使用你可能忽略了這些
數據庫的管理是一個非常專業的事情,對數據庫的調優、監控一般是由數據庫工程師完成,但是開發人員也經常與數據庫打交道,即使是簡單的增刪改查也是有很多竅門,這里,一起來聊聊數據庫中很容易忽略的問題。
字段長度省著點用
先說說我們常用的類型的存儲長度:
很明顯,不同的類型存儲的長度有很大區別的,對查詢的效率有影響,字段長度對索引的影響是很大的。
- 字符串字段長度都差不多的,可以預估長度的,用char
- 字符串長度差異大,用varchar,限制長度,不要浪費空間
- 整型根據大小,選擇合適的類型
- 時間建議用timestamp
- 建議使用decimal,不建議使用float,如果是價格,可以考慮用int或bigint,如1元,存儲的就是100
放棄uuid(guid)的使用
不管是uuid,還是guid,使用的時候都是為了避免同時生成重復的ID,但是建議考慮其他方案,原因如下:
- uuid沒有順序
- uuid太長
- uuid規則完全不可控
推薦的方案用bigint(***),或者char來存儲,生成方式參考snowflake的算法,有順序、長度固定、比uuid更短,當然,也幾乎不會重復。
大表減少聯表,***是單表查詢
單表查詢的優勢很多,查詢效率極高,便于分表分庫擴展,但是很多時候大家都覺得真正實現起來不太現實,完全失去了關系數據庫的意義,但是單表的性能優勢太明顯,一般總會有辦法解決的:
- 合理的冗余字段
- 配合內存數據庫(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的規范有很多可以吸取的地方,以上也是自己工作中的一些總結,歡迎大家補充。