《深入淺出MySQL--資料庫開發、優化與管理維護》讀書筆記--開發篇
本文是《深入淺出MySQL--資料庫開發、優化與管理維護》的讀書筆記,其中也包含了我自己的一些理解,不一定全對,先記錄下來再說。
最近做新專案,使用MySQL作為資料庫,之前只有Oracle的使用經驗。剛開始使用MySQL的時候,感覺十分不習慣,現在回想起來,如果專案剛啟動時可以讀到這本書,想必我會輕鬆許多。
資料型別的選擇
資料庫裡的資料最終需要持久化到硬碟上,而硬碟的I/O效率通常都比較低,那麼提高I/O效率可以有效的改善應用的效能表現。雖然硬碟價格很低,但考慮到I/O效率,儲存資料時務必要依據業務需求,尋求佔用空間最省的方式來儲存資料,以期提高I/O的效率。
- 對於字串,要根據儲存引擎來進行選擇。如果使用InnoDB,則推薦使用varchar,效率未必會比char低。
- 對於精度要求比較高的應用,建議使用定點數來儲存數值,另外從程式設計的角度來看,對精度有要求的業務,應當避免使用浮點型別。
- 對於含有TEXT或者BLOB的表來說,如果經常會做刪除和修改操作,則建議經常使用optimize table命令來對錶做碎片處理,優化儲存;另外,假如TEXT或者BLOB欄位不經常被檢索,從優化I/O效率的角度考慮,可以把對應欄位抽取出來,用單獨的表來儲存資料。
- 日期型別要根據實際需要選擇能夠滿足應用的最小儲存的日期型別。DATETIME和TIMESTAMP相比,都可以儲存年、月、日、時、分、秒,但DATETIME表示的範圍比較大,而TIMESTAMP可以支援時區,各有所長。
字符集
MySQL的字符集包含字符集(CHARACTER)和校對規則(COLLATION)兩個概念。字符集用來定義MySQL儲存字串的方式,校對規則則定義了字串比較的方式;字符集和校對規則是一對多的關係,即一種字符集可以支援多種校對規則。
校對規則的命名方式,以字符集的名稱開頭,以_ci/_cs/_bin結束,_ci表示大小寫不敏感,_cs表示大小寫敏感,_bin表示基於字元編碼的值來比較、與儲存的語言自身無關。比如對於字符集utf8,對應的校驗規則有utf8_ci、utf8_cs、utf8_bin。
MySQL資料例項可以在伺服器級別、資料庫級別、表級和欄位級設定字符集和校對規則,作用範圍不同。
注意點:
- 從已有經驗看,使用utf8作為預設的字符集,開發過程會比較輕鬆加愉快,因為這樣可以簡單的搞定中文和英文。
- 修改已存在的資料庫、表的字符集或者校對規則時,不會對已存在的資料產生影響。如果系統執行一段時間之後期望調整字符集和校驗規則,同時期望修正已有的資料,那麼需要將資料匯出,調整字符集之後重新匯入資料庫例項。
- 應用和MySQL通訊時,當前MySQL提供了三個引數來控制字符集,character_set_client、character_set_connection、character_set_results,三者如無明確設定,一般是一樣的;三者假如不同,寫入的資料和最終讀出的資料可能會存在差異,因此開發過程中應當避免設定這三個引數。
索引的設計和使用
索引用於快速找到在某個列中有一特定值的行,如果沒有索引,那麼就需要從第一行開始、到最後一行結束,遍歷表的全部記錄才能提到相關行,那麼I/O的代價就太高,效率低就是自然了。
設計索引或者建立索引的原則
- 索引可以有效的提升查詢資料的效率,但索引數量不是多多益善,索引越多,維護索引的代價自然也就水漲船高。對於插入、更新、刪除等DML操作比較頻繁的表來說,索引過多,會引入相當高的維護代價,降低DML操作的效率,增加相應操作的時間消耗。另外索引過多的話,MySQL也會犯選擇困難病,雖然最終仍然會找到一個可用的索引,但無疑提高了選擇的代價。
- 索引欄位的選擇,最佳候選列應當從where子句的條件中提取,如果where子句中的組合比較多,那麼應當挑選最常用、過濾效果最好的列的組合。
- 使用唯一索引,區分度越高,使用索引的效率越高。
- 使用短索引,索引建立之後也是使用硬碟來儲存的,因此提升索引訪問的I/O效率,也可以提升總體的訪問效率。假如構成索引的欄位總長度比較短,那麼在給定大小的儲存塊內可以儲存更多的索引值,相應的可以有效的提升MySQL訪問索引的I/O效率。
- 利用最左字首,N個列組合而成的組合索引,那麼相當於是建立了N個索引,如果查詢時where子句中使用了組成該索引的前幾個欄位,那麼這條查詢SQL可以利用組合索引來提升查詢效率。
Hash索引的特點
- 只能作=或者!=/<>的比較。
- 優化器無法使用索引來加速order by操作。
- 無法確定兩個值之間有多少行。
- 使用關鍵字檢索時,一次只能檢索到一行。
如果覺得不好理解的話,對照java.util.HashMap的使用方法就好懂了。
BTree索引可以使用的操作符相對要多一些,比如可以使用>、=、<=、between、!=或者<>、like,相應的適用範圍會廣一些;在特定場景下,相比於Hash索引,效率會有所損失。
檢視的使用
相比於普通的表,檢視的優勢
- 簡單,使用檢視的使用者完全不需要關注檢視背後的表的結構、關聯條件和篩選條件,站在檢視定義者的角度來看,使用者訪問到的是過濾好的結果集。
- 安全,通過檢視可以方便的控制使用者可以訪問到的行與列的集合,但普通的表則無法做到。
- 資料獨立,或者可維護性好,通過提供檢視,開發者可以遮蔽表結構、表名對使用者的影響,相關的變動不會影響到檢視的使用者。
不過檢視也有缺點,比如對檢視返回的結果集做過濾時,無法使用索引,假如檢視返回的結果集比較大,而需要的結果集比較小時,查詢的效率其實是比較低的。
我印象裡,通過檢視是不允許修改資料的,但現在這個觀念要改改了。通過使用MySQL和Oracle提供的檢視是可以修改原表中的資料的,只不過有些限制,使用時需要詳細閱讀官方文件。我平日的工作裡,檢視都很少用到,所以這部分資料看看就過了,假如以後有機會用的話,那時再來仔細研究也不遲。
鎖定語句
使用mysqldump命令匯出資料時,會發現lock table和unlock table的命令,這不同於Oracle,初次看到時感覺蠻還蠻神祕的。
lock table,用來鎖定當前執行緒使用的表,如果表被其它執行緒鎖定,則當前執行緒將會等待;同一執行緒中重複執行lock table會使用前一次鎖定的表被釋放鎖定。
unlock table,用來釋放當前執行緒獲得到的任何鎖定;與DB的通訊連線物件關閉時,當前執行緒中鎖定的表將會自動釋放鎖定。
使用lock table和unlock table的意義在哪裡?大批量資料短時間內載入至表內時,為了減少衝突,提高效率,這應該是一種場景,其它場景我暫時還想不到。
事務控制
MySQL提供了set autocommit、start transaction、commit和rollback等命令來實現事務的控制。
- start transaction或者begin用來開啟新的事務。
- commit和rollback用來提交或者回滾事務。
- set autocommit可以修改當前連線的提交方式。
Oracle只需要設定set autocommit,即可以用手動方式控制事務,但MySQL可能會有所不同,需要在辦公室嘗試下。
分散式事務,目前還沒有用到過,待後續有機會使用的時候再仔細閱讀資料。
SQL Mode
相比於Oracle,這個東東是MySQL獨有的特性。應該兼顧資料庫移植性、效能和效率、開發正確性和業務場景幾方面考慮,選擇合適的模式。
分割槽
分割槽表是一個非常強大的特性,利用這個特性,可以帶來如下好處
- 透明的管理儲存有海量資料的大表,由資料庫來管理對不同分割槽的訪問,使用者完全不必關心。
- 可以有效的提升資料的訪問效率和吞吐量,對不同分割槽的訪問可以併發進行,互不影響。
- 簡化表的管理,當部分分割槽的資料不需要時,可以通過刪除相關的分割槽來快速清理資料,而不必使用傳統的delete語句,引入不必要的複雜性。
- 。。。
之前的專案使用Oracle來儲存資料,應用了Oracle的分割槽技術;現在的專案由於資料量及業務複雜度的原因,暫時還沒有應用MySQL的分割槽,所以沒有什麼使用經驗可以分享。
------------------------------
歡迎訪問Jackie的家,http://jackieathome.sinaapp.com/,如需轉載文章,請註明出處。