1. 程式人生 > >Mysql優化總結(一)

Mysql優化總結(一)

一,前言

​ 資料庫(Database)是按照資料結構來組織、儲存和管理資料的倉庫。

​ MySQL 是一個關係型資料庫管理系統,由瑞典 MySQL AB 公司開發,目前屬於 Oracle 公司。MySQL 是一種關聯資料庫管理系統,關聯資料庫將資料儲存在不同的表中,而不是將所有資料放在一個大倉庫內,這樣就增加了速度並提高了靈活性。

  • MySQL是開源的,所以不需要支付任何費用。
  • MySQL使用標準的SQL資料語言形式。
  • MySQL可以處理擁有千萬條記錄的大型資料庫。
  • MySQL支援多種語言,如C,PHP,Java等。

  本篇部落格是總結MySQL儲存機制及SQL優化方面的內容。

二,MySQL邏輯架構

​ 分析:

  • 第一層是大多數基於網路的客戶端/伺服器的工具或者服務都有類似的架構。如連線處理,授權認證等。
  • 第二層架構中,大多數的MYSQL的核心服務功能都在這一層,包括查詢解析、分析、優化、快取以及所有的內建函式(日期時間等),所有跨儲存引擎的功能都在這一層實現:儲存過程、觸發器、檢視等層。
  • 第三層包含了儲存引擎。儲存引擎負責Mysql中的資料的儲存和提取。
    Mysql支援各種不同的儲存引擎,每個儲存引擎都有它的優勢和劣勢。伺服器通過API和儲存引擎進行通訊。這些API介面遮蔽了不同儲存引擎之間的差異,使的這些差異對上層的查詢過程透明。儲存引擎不會解析SQL(InnoDB是個例外,它會解析外來鍵定義),不同的儲存引擎之間也不能互相通訊,而只是簡單的響應上層伺服器的請求。

​ 快取:當客戶端請求到來時,先去查詢快取中是否存在資料,沒有再去資料庫中查詢。

**分析器:**對sql語句的分析,比如SELECT username FROM users; ,分析器分析出先執行FROM users,然後再執行SELECT username。

​ 優化器:上面只是舉了一個簡單的例子,而優化器作用在於選擇那種執行方式,是執行SQL效率最快的。因為分析器對一條SQL語句會分析出多種不同的結果,而優化器就會對以上的分析結果選擇它認為最優的結果來執行。但是,需要注意的是,優化器認為最優的執行方案,並不一定是我們認為的最優執行方案。因此再SQL語句量較大的情況下,就需要程式設計師手動對語句進行優化。

​ 下面再來說說MySQL的儲存引擎。

三,儲存引擎

​ 以博主的MySQL作為案例,執行select version();語句可以檢視資料庫版本。

​ 接著再來看看MySQL都支援哪些儲存引擎。

​ 在倒數第二個,可以看出MySQL預設的儲存引擎是InnoDB,再細看Transactions中只有InnoDB是支援事務的,其他儲存引擎都是不支援的。這是在MySQL5.5之後支援的引擎,所以說在5.5之前MySQL是不支援事務的。

​ 最長用的兩種儲存引擎為InnoDB和Myisam,請看兩者之間的區別(MySQL5.6)。

特點 InnoDB myisam
事務 支援事務 不支援
行鎖 表鎖
B樹索引 支援 支援
全文索引 不支援 支援
外來鍵 支援(唯一支援的) 不支援

​ 那麼如何選擇兩種儲存引擎,可以從以下幾個方面考慮。

​ 事務:

​ 如果應用需要事務支援,那麼InnoDB是較號的選擇。如果不需要事務,並且主要是select和insert操作,則MyISAM是個不錯的選擇,比如日誌型系統。

​ 備份:

​ 備份的需求也會影響儲存引擎的選擇。如果需要線上熱備份,則選擇InnoDB就是基本的要求。

​ 資料恢復:

​ 資料量比較大的時候,系統崩潰後如何快速恢復是一個需要考慮的額問題。相對而言,MyISAM崩潰後發生損壞的概率比InnoDB高的多,而且恢復也慢,因此即使不需要事務,通常也應該選擇InnoDB引擎。

​ 對於不同儲存引擎的選擇,對資料庫的效能都會帶來較大的影響,除了MySQL預設支援的儲存引擎之外,還有很多第三方儲存引擎。

​ 通常情況下,導致SQL效能下降還有以下幾方面:

  • 查詢語句編寫不合理
  • 索引失效
  • 關聯查詢資料太多
  • 伺服器的引數設定問題

下面總結一些關於SQL優化方面的內容。

四,資料型別優化

4.1,資料型別的選擇原則。

​ 更小的通常更好:

​ 一般情況選擇可以正確儲存資料的最小資料型別。因為更小的資料型別通常更快,因為佔用磁碟、記憶體和CPU快取會越小。

​ 簡單就好:

​ 簡單資料型別的操作通常需要更少的CPU消耗。

​ 儘量避免NULL:

​ 一般情況下最好執行列為NOT NULL,除非特殊需要。因為如果查詢中包含為NULL的列,從SQL優化角度考慮,對建立索引,索引的統計等都會帶來較大的困難,且優化起來也是較為複雜的,因此說盡量避免NULL值。

4.2,具體型別的選擇

​ 1,整數型別:選擇合適的位元組大小作為資料的型別。

  • tinyint:8位位元組
  • smallint:16位位元組
  • mediumint:24位位元組
  • int:32位位元組
  • bigint:64位位元組
  • unsigned屬性:新增unsigned屬性表示該欄位不允許負數,正數的上限大致可以提高一倍。
    比如tinyint unsigned可以儲存0-255的範圍。而tinyint是-128~127的範圍。有符號和無符號佔用空間大小相同,具有相同的效能。

int(11)是指定整數型別的寬度,它不會限制值得合法範圍,對於儲存和計算而言,int(1)和int(20)沒什麼區別

​ 2,實數型別

  • float:32位
  • double:64位
  • decimal:decimel需要額外的空間和計算開銷,所以應該儘量只對小數進行精準計算時才使用decimel,例如儲存金額。

​ 3,字串型別

  • varchar:是可變長的字串,它比定長更節省空間。varchar需要使用1~2個額外位元組記錄字串的長度。varchar節省了儲存空間,所以對效能也有幫助,
    但是由於長度可變,在update時可能使行變得比原來更長,這就導致需要進行額外的工作。至於如何進行空間增長取決於不同的儲存引擎。當字串列的最大長度比平均長度要大很多,並且列的更新很少時比較適合使用varchar。
  • char:定長字串,mysql根據定義的字串長度分配足夠的空間。
    char非常適合儲存很短的字串,或者值得長度都很接近的欄位。例如char非常適合存放密碼的md5值,因為這是一個定長的值。對於經常變更的欄位,使用char也更為合適,因為定長的char型別不容易產生碎片。對於非常短的列,儲存空間也更有優勢,比如char(1)只會佔用一個位元組,而varchar(1)會用到兩個位元組,因為還有一個位元組用來記錄varchar的長度。
  • blob和text:兩者都是用於儲存很大的資料而設計的字串資料型別,
    分別採用二進位制和字元的方式儲存。

varchar(5)和varchar(200)儲存'hello'的空間開銷是一樣的。但是varchar(5)對效能提升有很大的優勢。更長的列會消耗更多的記憶體,因為mysql通常會分配固定大小的記憶體塊來儲存內部值。尤其是使用記憶體臨時表進行排序等操作時會特別糟糕。所以最好的策略是隻分配真正需要的空間

​ 4,時間和日期型別

  • datetime:能儲存大範圍的值,從1001年到9999年,精度為秒。它把日期和時間封裝到YYYYMMDDHHMMSS的整數中,使用8個位元組的儲存空間 。
  • timestamp:儲存了從1970年1月1日以來的毫秒數,timestamp只使用了4個位元組的儲存空間,因此它的範圍比datetime小的多;但是隻能表示從1970年到2038年。另外timestamp也依賴於時區。

除了特殊行為之外,通常應該儘量使用timestamp,
因為它比datetime空間效率更高。

五,總結

​ 下面將總結索引方面的優化,包括B-Tree和B+Tree兩種資料結構的原理,由於放在一起篇幅較長,所以就分成兩個部落格,這些內容會在下一篇部落格中進行詳細總結。

​ 以上內容均是自主學習總結,如有不適之處,歡迎留言指正。

感謝閱讀