mysql myisam和innodb區別_MySQL效能優化你真的瞭解嗎
技術標籤:mysql myisam和innodb區別mysql發生系統錯誤5mysql效能優化多個goruntine 效能變慢
今天我的好朋友皮皮蝦和我吐槽,最近資料庫的查詢效能又變慢了,為此運維的同事沒少吐槽他,寫的SQL太爛。今天我們就一起學習一下MySQL的效能優化。
在實際生產環境中找出資料庫效能變慢的方法:
觀察,跑一天,看看生產的慢SQL情況。
開啟慢查詢日誌,設定閾值,比如超過5秒鐘就是慢SQL,將它抓取。
explain + 慢SQL分析
show profile
進行資料庫伺服器的引數調優
本篇文章就圍繞MySQL的詳細介紹以及效能優化進行 。主要分為以下四個方面:
1、主要配置檔案
Windows下在MySQL安裝的資料夾中會有一個my.ini檔案,主要記錄著MySQL檔案的配置資訊二進位制日誌log-bin
主要用於記錄修改資料或有可能引起資料庫變更的MySQL語句,其中記錄了對MySQL資料庫執行的所有更操作,記錄語句發生時間、執行的時間長度等,一般用於資料庫的恢復以及主從複製等。二進位制日誌狀態檢視:
OFF表示沒有開啟二進位制日誌,ON表示開啟了二進位制日誌
show variables like 'log_bin';
開啟二進位制日誌檔案的方法:
1、修改my.ini,在[mysqld]下面增加log_bin=mysql_bin,重啟MySQL後,你會發現log_bin變為了ON
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_dir | InnoDB資料檔案的目錄 |
innodb_additional_mem_pool_size=3M | InnoDB用於儲存元資料的附加記憶體池資訊(InnoDB引擎的資料字典和內部結構),如果InnoDB需要更多就從作業系統開始分配 |
innodb_flush_log_at_trx_commit=1 | 日誌提交方式(關鍵引數): 0:每秒寫一次日誌,將資料刷入磁碟,相當於每秒提交一次事務; 1:每秒提交事務寫日誌,同時重新整理磁碟–>預設引數; 2:每提交事務寫一次日誌,但每隔一秒重新整理一次相應的磁碟檔案 |
nnodb_log_buffer_size=2M | InnoDB用於緩衝日誌資料的緩衝區大小,一旦檔案已滿,InnoDB將其重新整理到磁碟 |
innodb_buffer_pool_size=107M | InnoDB緩衝池用來快取索引和行資料。設定的越大,所需的磁碟IO越少,但是不能設定太大,實體記憶體競爭導致作業系統的分頁,一般考慮為實體記憶體總量的80% |
innodb_log_file_size=54M | 日誌組中每個日誌檔案的大小 |
innodb_thread_concurrency=10 | InnoDB的核心中允許的執行緒數,一般最佳值取決於應用程式的屬性,如果值過高會導致執行緒抖動 |
2、MyISAM儲存引擎
如果應用是以讀操作和插入操作為主,只是很少的更新和刪除操作,並且對事務的完整性、併發性要求不高,那麼可以選擇這種儲存引擎。
MyISAM儲存引擎的引數配置:
引數名 | 說明 |
myisam_max_sort_file_size=100G | MySQL允許使用的臨時檔案的最大大小 |
myisam_sort_buffer_size=69M | 指定金鑰快取的大小,如果用於快速索引建立的臨時檔案比這大,那最好使用金鑰快取方法 |
key_buffer_size=55M | 鍵緩衝區的大小,用於快取MyISAM表的索引塊,一般設為小於記憶體的30%,如果只使用InnoDB引擎,此引數一般推薦設為8-64M,因為臨時表可能會使用到次快取空間 |
read_rnd_buffer_size=256K | 讀取MyISAM表緩衝區的大小 |
sort_buffer_size=256K | MySQL中需要重建索引時或者載入資料填充到空表中時,會分配此緩衝區 |
兩者對比:
對比項 | MyISAM | InnoDB |
主外來鍵 | 不支援 | 支援 |
事務 | 不支援 | 支援 |
行表鎖 | 表鎖,即使操作一條記錄也會鎖住整個表,不適合做高併發 | 行鎖,操作時只鎖住某一行,不對其他行有影響。適合高併發操作 |
快取 | 只快取索引,不快取其他真實資料 | 不僅快取索引還要快取真實資料,對記憶體有較高要求,記憶體大小對效能有決定性影響 |
表空間 | 小 | 大 |
關注點 | 效能 | 事務 |
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語句的。id: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;
優化的建議:
儘可能所有的 資料檢索通過索引來完成,避免無索引行鎖變表鎖
合理設計索引,儘量縮小鎖的範圍
儘可能較少檢索條件,避免間隙鎖
儘量控制事務大小,減少鎖定資源量和時間長度
儘可能低級別事務隔離