1. 程式人生 > 其它 >mysql myisam和innodb區別_MySQL效能優化你真的瞭解嗎

mysql myisam和innodb區別_MySQL效能優化你真的瞭解嗎

技術標籤:mysql myisam和innodb區別mysql發生系統錯誤5mysql效能優化多個goruntine 效能變慢

今天我的好朋友皮皮蝦和我吐槽,最近資料庫的查詢效能又變慢了,為此運維的同事沒少吐槽他,寫的SQL太爛。今天我們就一起學習一下MySQL的效能優化。

在實際生產環境中找出資料庫效能變慢的方法:

  1. 觀察,跑一天,看看生產的慢SQL情況。

  2. 開啟慢查詢日誌,設定閾值,比如超過5秒鐘就是慢SQL,將它抓取。

  3. explain + 慢SQL分析

  4. show profile

  5. 進行資料庫伺服器的引數調優

本篇文章就圍繞MySQL的詳細介紹以及效能優化進行 。主要分為以下四個方面:

1、主要配置檔案

Windows下在MySQL安裝的資料夾中會有一個my.ini檔案,主要記錄著MySQL檔案的配置資訊二進位制日誌log-bin
主要用於記錄修改資料或有可能引起資料庫變更的MySQL語句,其中記錄了對MySQL資料庫執行的所有更操作,記錄語句發生時間、執行的時間長度等,一般用於資料庫的恢復以及主從複製等。二進位制日誌狀態檢視:
OFF表示沒有開啟二進位制日誌,ON表示開啟了二進位制日誌

show variables like 'log_bin';

7b118a2864ef1a8cc7601ba3c05f5059.png開啟二進位制日誌檔案的方法:
1、修改my.ini,在[mysqld]下面增加log_bin=mysql_bin,重啟MySQL後,你會發現log_bin變為了ON894d22a126a33925b85e15923e128c5b.png


tip:有人會問開啟二進位制日誌會影響伺服器的效能嗎?答案是會有一定的效能損耗,但是效能開銷是非常小的,但是開啟的好處卻遠遠大過這一點點的效能開銷。

錯誤日誌log-error
MySQL錯誤日誌是記錄MySQL執行過程中較為嚴重的警告和錯誤資訊,記錄嚴重的警告和錯誤資訊,每次啟動和關閉的詳細資訊等。

SHOW VARIABLES LIKE '%log_error%'

查詢日誌log
MySQL的查詢日誌記錄查詢的sql語句,無論這些請求是否得到了正確的執行,預設情況下是關閉的,在生產環境下,如果開啟會降低MySQL的整體效能,因為記錄日誌也需要消耗系統資源。很多情況下慢查詢日誌基本上可以定位出出現效能問題的SQL,所以這個使用的場景不是很多。

SHOW VARIABLES LIKE '%general_log%'

開啟MySQL查詢日誌的方法:

SET GLOBAL general_log = ON;

關閉MySQL查詢日誌的方法:

SET GLOBAL general_log = OFF;

儲存引擎
MySQL中資料用各種方法儲存在檔案中,使用到不同的儲存機制、索引技巧、鎖定水平。簡單的來說儲存引擎就是指表的型別以及表在計算機上的儲存方式。MySQL支援的儲存引擎,檢視方式:

SHOW ENGINES;

檢視正在使用的儲存引擎:

SHOW VARIABLES LIKE '%storage_engine%'

主要關注InnoDB、MyISAM這兩種儲存引擎:1、InnoDB儲存引擎
用於事務處理應用程式,支援外來鍵和行級索引。如果對事務的完整性有比較高的要求,在高併發條件下要求資料的一致性,資料操作除了插入和查詢之外,還包含很多更新和刪除操作,那麼InnoDB儲存引擎是比較合適的。InnoDB除了有效的降低由刪除和更新導致的鎖定,還可以確保事務的完整提交和回滾,對於那些對資料準確性要求比較高的系統是比較合適的選擇。
InnoDB儲存引擎的引數配置:

引數名說明
innodb_data_home_dirInnoDB資料檔案的目錄
innodb_additional_mem_pool_size=3MInnoDB用於儲存元資料的附加記憶體池資訊(InnoDB引擎的資料字典和內部結構),如果InnoDB需要更多就從作業系統開始分配
innodb_flush_log_at_trx_commit=1

日誌提交方式(關鍵引數):

0:每秒寫一次日誌,將資料刷入磁碟,相當於每秒提交一次事務;

1:每秒提交事務寫日誌,同時重新整理磁碟–>預設引數;

2:每提交事務寫一次日誌,但每隔一秒重新整理一次相應的磁碟檔案

nnodb_log_buffer_size=2MInnoDB用於緩衝日誌資料的緩衝區大小,一旦檔案已滿,InnoDB將其重新整理到磁碟
innodb_buffer_pool_size=107MInnoDB緩衝池用來快取索引和行資料。設定的越大,所需的磁碟IO越少,但是不能設定太大,實體記憶體競爭導致作業系統的分頁,一般考慮為實體記憶體總量的80%
innodb_log_file_size=54M日誌組中每個日誌檔案的大小
innodb_thread_concurrency=10InnoDB的核心中允許的執行緒數,一般最佳值取決於應用程式的屬性,如果值過高會導致執行緒抖動

2、MyISAM儲存引擎
如果應用是以讀操作和插入操作為主,只是很少的更新和刪除操作,並且對事務的完整性、併發性要求不高,那麼可以選擇這種儲存引擎。
MyISAM儲存引擎的引數配置:

引數名說明
myisam_max_sort_file_size=100GMySQL允許使用的臨時檔案的最大大小
myisam_sort_buffer_size=69M指定金鑰快取的大小,如果用於快速索引建立的臨時檔案比這大,那最好使用金鑰快取方法
key_buffer_size=55M鍵緩衝區的大小,用於快取MyISAM表的索引塊,一般設為小於記憶體的30%,如果只使用InnoDB引擎,此引數一般推薦設為8-64M,因為臨時表可能會使用到次快取空間
read_rnd_buffer_size=256K讀取MyISAM表緩衝區的大小
sort_buffer_size=256KMySQL中需要重建索引時或者載入資料填充到空表中時,會分配此緩衝區

兩者對比:

對比項MyISAMInnoDB
主外來鍵不支援支援
事務不支援支援
行表鎖表鎖,即使操作一條記錄也會鎖住整個表,不適合做高併發行鎖,操作時只鎖住某一行,不對其他行有影響。適合高併發操作
快取只快取索引,不快取其他真實資料不僅快取索引還要快取真實資料,對記憶體有較高要求,記憶體大小對效能有決定性影響
表空間
關注點效能事務


2.MySQL索引優化分析

效能下降,SQL執行比較慢的主要原因:1、查詢語句寫的比較爛
2、索引問題
索引:用於快速找出在某一列中有一特定值的行,本質上是資料結構。不使用索引,MySQL的查詢必須從第一條資料開始讀取整個表,那樣效率就會特別慢。而且表越大,查詢資料花費的時間越多。索引本身也很大,不可能儲存在記憶體中,以穩健的形式儲存在磁碟上。

索引的優勢:
類似於圖書館建書目索引,提高檢索效率,降低資料庫IO成本。
通過索引對資料進行排序,降低資料排序的成本,降低了CPU的消耗。

索引的劣勢:
實際上索引也是一張表,該表儲存了主鍵和索引欄位,並指向實體表的記錄,索引也要佔空間。
索引雖然提高了查詢速度,但是會降低更新表的速度,比如對錶進行增刪改時,MySQL不僅要儲存資料,還要儲存索引檔案每次更新後新增的索引列的欄位,因為每次鍵值變化索引資訊都會改變。

MySQL的索引分類:
唯一索引:索引的值必須唯一,但允許有空值
複合索引:即一個索引包含多個列

MySQL索引的結構:

哪些情況需要建立索引:
1、主鍵自動建立唯一索引
2、頻繁作為查詢條件的欄位應該建立索引
3、查詢中與其他表關聯的欄位,外來鍵關係建立索引
4、頻繁更新的欄位不適合作為索引
5、where條件裡用不到的欄位不建立索引
6、單鍵/組合索引的選擇問題(高併發傾向於建立組合索引)
7、查詢中排序的欄位,排序欄位若通過索引去訪問將大大提高排序效率
8、查詢中統計或者分組欄位

哪些不需要建立索引:
1、表記錄太少
2、經常增刪改的表
3、資料重複且分佈平均的表字段

MySQL的常見瓶頸:
CPU:CPU在飽和時一般發生在資料裝入記憶體或者從磁碟上讀取資料的時候
IO:磁碟IO瓶頸發生在裝入資料遠大於記憶體容量的時候
伺服器硬體的效能瓶頸:top,free,iostat和vmstat來檢視系統性能狀態

效能分析之explain:
使用explain關鍵字可以模擬優化器執行SQL查詢語句,直到MySQL是如何處理SQL語句的。a1a9a256a52fc637a6fb0aeaa06c67ea.pngid:select查詢的序列號,包含一組數字,表示查詢中執行select子句或操作表的順序
如果id相同,可以認為是一組,從上往下順序執行;所有組中,id值越大,優先順序越高,越先執行。select_type:SIMPLE, PRIMARY,SUBQUERY,DERIVED,UNION,UNION RESULT
主要用於區別查詢的型別。type:顯示的為訪問型別,比較重要的指標,結果值從最好到最壞依次是:
system>const>eq_ref>ref>range>index>ALL(ALL是最壞的)
得保證查詢至少達到range級別,最好能達到ref。possible_keys:顯示可能應用在這張表中的索引,如果涉及到欄位上存在索引,就會列出,但是不一定會使用。key:實際使用的索引,如果為NULL,則沒有使用key_len:表示索引中使用的位元組數。ref:顯示索引的那一列被使用了。row:根據表統計資訊及索引選用情況,大致估算找出所需記錄所需讀取的行數。Extra:一些重要的額外資訊。
1.Using filesort:MySQL會對資料使用一個外部的索引排序,而不是按照表內的索引順序進行讀取。
2.Using temporary:使用臨時表儲存中間結果,MySQL在對查詢結果排序時使用臨時表。常見於排序和分組查詢。
3.Using index:表示相應的select操作使用了覆蓋索引,避免訪問了表的資料行,效率不錯。

索引失效的原因:
1、使用全值匹配
2、如果索引有多列,查詢從索引的最左前列開始並且不跳過索引的列
3、索引列上做了一些操作(計算、函式等),會導致索引失效,進而全表掃描
4、MySQL在使用不等於的時候會無法使用索引導致全表掃描
5、is null,is not null 也無法使用索引
6、字串不加單引號,會導致索引失效
7、少用or,用它來連線會使索引失效
8、like以萬用字元開頭(’%abc…’)MySQL索引會失效,變成全表掃描

SQL優化
優化原則:小表驅動大表,小的資料集驅動大的資料集

select * from A where id in (select id from B)當B表的資料集小於A表的資料集時,用in優於exist

伺服器調優以及引數設定
order by 子句導致變慢,可以檢視是否是sort_buffrt_size引數,和max_length_for_sort_data引數的問題
在生產環境中,手工分析日誌,查詢、分析SQL是個體力活,可以使用MySQL提供的日誌分析工具mysqldumpslow。
診斷SQL:show profile;

showprofilecpu,blocioforquery+sqlID;

出現這四種都有問題:
converting HEAP to MyISAM查詢結果太大,記憶體都不夠用了往磁碟上搬。
Creating tmp table建立臨時表:1、拷貝資料到臨時表 2、用完再刪除
Copying to tmp table on disk把記憶體中臨時表複製到磁碟
locked

3.MySQL查詢分析

SQL的執行順序:

SELECTDISTINCTFROMJOINONWHEREGROUPBYHAVINGORDERBYLIMIT

4.MySQL鎖機制

表鎖:偏向於MyISAM儲存引擎,開銷小,加鎖快;無死鎖;鎖的粒度比較大,發生鎖衝突的概率最高,併發度最低。
MyISAM 在執行查詢語句前,會自動給涉及的所有表加鎖,在執行增刪改操作前,會自動給涉及的表加寫鎖。
MySQL的表級鎖有兩種模式:
1、讀鎖
2、寫鎖
對MyISAM表的讀操作(加讀鎖),不會阻塞其他程序對同一表的讀請求,但會阻塞寫請求。只有當讀鎖釋放後,才會執行其他程序的寫操作。
對MyISAM表的寫操作(加寫鎖),會阻塞其他程序對同一表的讀和寫操作,只有當寫鎖釋放後,才可以執行讀和寫。

行鎖:偏向於InnoDB儲存引擎,開銷大,加鎖慢;會出現死鎖;鎖的粒度最小,發生所衝突概率最低,併發度也最高。
InnoDB與MyISAM最大的不同點:一是支援事務(TRANSACTION);二是採用行級鎖。
在MySQL4.5以後的版本中預設是InnoDB儲存引擎,為了測試行鎖,將表中自動更新資料關閉。

setautocommit=0;

在不同的session中你會發現,你更新了表的資料,其他session沒法同步,必須要

commit;

之後,在其他session中檢視資料才會發現更新完全。

如何鎖定一行:

begin;select * from XX where id = 1 for update;commit;

優化的建議:
儘可能所有的 資料檢索通過索引來完成,避免無索引行鎖變表鎖
合理設計索引,儘量縮小鎖的範圍
儘可能較少檢索條件,避免間隙鎖
儘量控制事務大小,減少鎖定資源量和時間長度
儘可能低級別事務隔離