亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > MySQL > 正文

mysql 性能的檢查和優化方法

2024-07-24 13:09:24
字體:
來源:轉載
供稿:網友
mysql在遇到嚴重性能問題時,一般都有這么幾種可能
 
1、索引沒有建好; 
2、sql寫法過于復雜; 
3、配置錯誤; 
4、機器實在負荷不了; 
1、索引沒有建好 
如果看到mysql消耗的cpu很大,可以用mysql的client工具來檢查。 
linux下執行 
/usr/local/mysql/bin/mysql -hlocalhost -uroot -p 
輸入密碼,如果沒有密碼,則不用-p參數就可以進到客戶端界面中。 
看看當前的運行情況 
show full processlist 
可以多運行幾次 
這個命令可以看到當前正在執行的sql語句,它會告知執行的sql、數據庫名、執行的狀態、來自的客戶端ip、所使用的帳號、運行時間等信息 
在我的cache后端,這里面大部分時間是看不到顯示任何sql語句的,我認為這樣才算比較正常。如果看到有很多sql語句,那么這臺mysql就一定會有性能問題 
如果出現了性能問題,則可以進行分析: 
1、是不是有sql語句卡住了? 
這是出現比較多的情況,如果數據庫是采用myisam,那么有可能有一個寫入的線程會把數據表給鎖定了,如果這條語句不結束,則其它語句也無法運行。 
查看processlist里的time這一項,看看有沒有執行時間很長的語句,要留意這些語句。 
2、大量相同的sql語句正在執行 
如果出現這種情況,則有可能是該sql語句執行的效率低下,同樣要留意這些語句。 
然后把你所懷疑的語句統統集合一下,用desc(explain)來檢查這些語句。 
首先看看一個正常的desc輸出: 
mysql> desc select * from imgs where imgid=1651768337; 
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+ 
| 1 | SIMPLE | imgs | const | PRIMARY | PRIMARY | 8 | const | 1 | | 
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+ 
1 row in set (0.00 sec) 
注意key、rows和Extra這三項,這條語句返回的結果說明了該sql會使用PRIMARY主鍵索引來查詢,結果集數量為1條,Extra沒有顯示,證明沒有用到排序或其他操作。由此結果可以推斷,mysql會從索引中查詢imgid=1651768337這條記錄,然后再到真實表中取出所有字段,是很簡單的操作。 
key是指明當前sql會使用的索引,mysql執行一條簡單語句時只能使用到一條索引,注意這個限制;rows是返回的結果集大小,結果集就是使用該索引進行一次搜索的所有匹配結果;Extra一般會顯示查詢和排序的方式,。 
如果沒有使用到key,或者rows很大而用到了filesort排序,一般都會影響到效率,例如: 
mysql> desc select * from imgs where userid="7mini" order by clicks desc limit 10; 
+----+-------------+-------+------+---------------+------+---------+------+-------+-----------------------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 
+----+-------------+-------+------+---------------+------+---------+------+-------+-----------------------------+ 
| 1 | SIMPLE | imgs | ALL | NULL | NULL | NULL | NULL | 12506 | Using where; Using filesort | 
+----+-------------+-------+------+---------------+------+---------+------+-------+-----------------------------+ 
1 row in set (0.00 sec) 
這條sql結果集會有12506條,用到了filesort,所以執行起來會非常消耗效率的。這時mysql執行時會把整個表掃描一遍,一條一條去找到匹配userid="7mini"的記錄,然后還要對這些記錄的clicks進行一次排序,效率可想而知。真實執行時如果發現還比較快的話,那是因為服務器內存還足夠將12506條比較短小的記錄全部讀入內存,所以還比較快,但是并發多起來或者表大起來的話,效率問題就嚴重了。 
這時我把userid加入索引: 
create index userid on imgs (userid); 
然后再檢查: 
mysql> desc select * from imgs where userid="7mini" order by clicks desc limit 10; 
+----+-------------+-------+------+---------------+--------+---------+-------+------+-----------------------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 
+----+-------------+-------+------+---------------+--------+---------+-------+------+-----------------------------+ 
| 1 | SIMPLE | imgs | ref | userid | userid | 51 | const | 8 | Using where; Using filesort | 
+----+-------------+-------+------+---------------+--------+---------+-------+------+-----------------------------+ 
1 row in set (0.00 sec) 
嗯,這時可以看到mysql使用了userid這個索引搜索了,用userid索引一次搜索后,結果集有8條。然后雖然使用了filesort一條一條排序,但是因為結果集只有區區8條,效率問題得以緩解。 
但是,如果我用別的userid查詢,結果又會有所不同: 
mysql> desc select * from imgs where userid="admin" order by clicks desc limit 10; 
+----+-------------+-------+------+---------------+--------+---------+-------+------+-----------------------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 
+----+-------------+-------+------+---------------+--------+---------+-------+------+-----------------------------+ 
| 1 | SIMPLE | imgs | ref | userid | userid | 51 | const | 2944 | Using where; Using filesort | 
+----+-------------+-------+------+---------------+--------+---------+-------+------+-----------------------------+ 
1 row in set (0.00 sec) 
這個結果和userid="7mini"的結果基本相同,但是mysql用userid索引一次搜索后結果集的大小達到2944條,這2944條記錄都會加入內存進行filesort,效率比起7mini那次來說就差很多了。這時可以有兩種辦法可以解決,第一種辦法是再加一個索引和判斷條件,因為我只需要根據點擊量取最大的10條數據,所以有很多數據我根本不需要加進來排序,比如點擊量小于10的,這些數據可能占了很大部分。 
我對clicks加一個索引,然后加入一個where條件再查詢: 
create index clicks on imgs(clicks); 
mysql> desc select * from imgs where userid="admin" order by clicks desc limit 10; 
+----+-------------+-------+------+---------------+--------+---------+-------+------+-----------------------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 
+----+-------------+-------+------+---------------+--------+---------+-------+------+-----------------------------+ 
| 1 | SIMPLE | imgs | ref | userid,clicks | userid | 51 | const | 2944 | Using where; Using filesort | 
+----+-------------+-------+------+---------------+--------+---------+-------+------+-----------------------------+ 
1 row in set (0.00 sec) 
這時可以看到possible_keys變成了userid,clicks,possible_keys是可以匹配的所有索引,mysql會從possible_keys中自己判斷并取用其中一個索引來執行語句,值得注意的是,mysql取用的這個索引未必是最優化的。這次查詢mysql還是使用userid這個索引來查詢的,并沒有按照我的意愿,所以結果還是沒有什么變化。改一下sql加上use index強制mysql使用clicks索引: 
mysql> desc select * from imgs use index (clicks) where userid='admin' and clicks>10 order by clicks desc limit 10 
+----+-------------+-------+-------+---------------+--------+---------+------+------+-------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 
+----+-------------+-------+-------+---------------+--------+---------+------+------+-------------+ 
| 1 | SIMPLE | imgs | range | clicks | clicks | 4 | NULL | 5455 | Using where | 
+----+-------------+-------+-------+---------------+--------+---------+------+------+-------------+ 
1 row in set (0.00 sec) 
這時mysql用到了clicks索引進行查詢,但是結果集比userid還要大!看來還要再進行限制: 
mysql> desc select * from imgs use index (clicks) where userid='admin' and clicks>1000 order by clicks desc limit 10 
+----+-------------+-------+-------+---------------+--------+---------+------+------+-------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 
+----+-------------+-------+-------+---------------+--------+---------+------+------+-------------+ 
| 1 | SIMPLE | imgs | range | clicks | clicks | 4 | NULL | 312 | Using where | 
+----+-------------+-------+-------+---------------+--------+---------+------+------+-------------+ 
1 row in set (0.00 sec) 
加到1000的時候結果集變成了312條,排序效率應該是可以接受。 
不過,采用換索引這種優化方式需要取一個采樣點,比如這個例子中的1000這個數字,這樣,對userid的每個數值,都要去找一個采樣點,這樣對程序來說是很難辦的。如果按1000取樣的話,那么userid='7mini'這個例子中,取到的結果將不會是8條,而是2條,給用戶造成了困惑。 
當然還有另一種辦法,加入雙索引: 
create index userid_clicks on imgs (userid, clicks) 
mysql> desc select * from imgs where userid="admin" order by clicks desc limit 10; 
+----+-------------+-------+------+----------------------+---------------+---------+-------+------+-------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 
+----+-------------+-------+------+----------------------+---------------+---------+-------+------+-------------+ 
| 1 | SIMPLE | imgs | ref | userid,userid_clicks | userid_clicks | 51 | const | 2944 | Using where | 
+----+-------------+-------+------+----------------------+---------------+---------+-------+------+-------------+ 
1 row in set (0.00 sec) 
這時可以看到,結果集還是2944條,但是Extra中的filesort不見了。這時mysql使用userid_clicks這個索引去查詢,這不但能快速查詢到userid="admin"的所有記錄,并且結果是根據clicks排好序的!所以不用再把這個結果集讀入內存一條一條排序了,效率上會高很多。 
但是用多字段索引這種方式有個問題,如果查詢的sql種類很多的話,就得好好規劃一下了,否則索引會建得非常多,不但會影響到數據insert和update的效率,而且數據表也容易損壞。 
以上是對索引優化的辦法,因為原因可能會比較復雜,所以寫得比較的長,一般好好優化了索引之后,mysql的效率會提升n個檔次,從而也不需要考慮增加機器來解決問題了。 
但是,mysql甚至所有數據庫,可能都不好解決limit的問題。在mysql中,limit 0,10只要索引合適,是沒有問題的,但是limit 100000,10就會很慢了,因為mysql會掃描排好序的結果,然后找到100000這個點,取出10條返回。要找到100000這個點,就要掃描100000條記錄,這個循環是比較耗時的。不知道會不會有什么好的算法可以優化這個掃描引擎,我冥思苦想也想不出有什么好辦法。對于limit,目前直至比較久遠的將來,我想只能通過業務、程序和數據表的規劃來優化,我想到的這些優化辦法也都還沒有一個是萬全之策,往后再討論。 
2、sql寫法過于復雜 
sql寫法假如用到一些特殊的功能,比如groupby、或者多表聯合查詢的話,mysql用到什么方式來查詢也可以用desc來分析,我這邊用復雜sql的情況還不算多,所以不常分析,暫時就沒有好的建議。 
3、配置錯誤 
配置里主要參數是key_buffer、sort_buffer_size/myisam_sort_buffer_size,這兩個參數意思是: 
key_buffer=128M:全部表的索引都會盡可能放在這塊內存區域內,索引比較大的話就開稍大點都可以,我一般設為128M,有個好的建議是把很少用到并且比較大的表想辦法移到別的地方去,這樣可以顯著減少mysql的內存占用。 
sort_buffer_size=1M:單個線程使用的用于排序的內存,查詢結果集都會放進這內存里,如果比較小,mysql會多放幾次,所以稍微開大一點就可以了,重要是優化好索引和查詢語句,讓他們不要生成太大的結果集。 
另外一些配置: 
thread_concurrency=8:這個配置標配=cpu數量x2 
interactive_timeout=30 
wait_timeout=30:這兩個配置使用10-30秒就可以了,這樣會盡快地釋放內存資源,注意:一直在使用的連接是不會斷掉的,這個配置只是斷掉了長時間不動的連接。 
query_cache:這個功能不要使用,現在很多人看到cache這幾個字母就像看到了寶貝,這是不唯物主義的。mysql的query_cache在每次表數據有變化的時候都會重新清理連至該表的所有緩存,如果更新比較頻繁,query_cache不但幫不上忙,而且還會對效率影響很大。這個參數只適合只讀型的數據庫,如果非要用,也只能用query_cache_type=2自行用SQL_CACHE指定一些sql進行緩存。 
max_connections:默認為100,一般情況下是足夠用的,但是一般要開大一點,開到400-600就可以了,能超過600的話一般就有效率問題,得另找對策,光靠增加這個數字不是辦法。 
其它配置可以按默認就可以了,個人覺得問題還不是那么的大,提醒一下:1、配置雖然很重要,但是在絕大部分情況下都不是效率問題的罪魁禍首。2、mysql是一個數據庫,對于數據庫最重要考究的不應是效率,而是穩定性和數據準確性。 
4、機器實在負荷不了 
如果做了以上調整,服務器還是不能承受,那就只能通過架構級調整來優化了。 
1、mysql同步。 
通過mysql同步功能將數據同步到數臺從數據庫,由主數據庫寫入,從數據庫提供讀取。 
我個人不是那么樂意使用mysql同步,因為這個辦法會增加程序的復雜性,并常常會引起數據方面的錯誤。在高負荷的服務中,死機了還可以快速重啟,但數據錯誤的話要恢復就比較麻煩。 
2、加入緩存 
加入緩存之后,就可以解決并發的問題,效果很明顯。如果是實時系統,可以考慮用刷新緩存方式使緩存保持最新。 
在前端加入squid的架構比較提倡使用,在命中率比較高的應用中,基本上可以解決問題。 
如果是在程序邏輯層里面進行緩存,會增加很多復雜性,問題會比較多而且難解決,不建議在這一層面進行調整。 
3、程序架構調整,支持同時連接多個數據庫 
如果web加入緩存后問題還是比較嚴重,只能通過程序架構調整,把應用拆散,用多臺的機器同時提供服務。 
如果拆散的話,對業務是有少許影響,如果業務當中有部分功能必須使用所有的數據,可以用一個完整庫+n個分散庫這樣的架構,每次修改都在完整庫和分散庫各操作一次,或定期整理完整庫。 
當然,還有一種最笨的,把數據庫整個完完整整的做拷貝,然后程序每次都把完整的sql在這些庫執行一遍,訪問時輪詢訪問,我認為這樣要比mysql同步的方式安全。 
4、使用 mysql proxy 代理 
mysql proxy 可以通過代理把數據庫中的各個表分散到數臺服務器,但是它的問題是沒有能解決熱門表的問題,如果熱門內容散在多個表中,用這個辦法是比較輕松就能解決問題。 
我沒有用過這個軟件也沒有認真查過,不過我對它的功能有一點點懷疑,就是它怎么實現多個表之間的聯合查詢?如果能實現,那么效率如何呢? 
5、使用memcachedb 
數據庫換用支持mysql的memcachedb,是可以一試的想法,從memcachedb的實現方式和層面來看對數據沒有什么影響,不會對用戶有什么困擾。 
為我現在因為數據庫方面問題不多,沒有試驗過這個玩意。不過,只要它支持mysql的大部分主要的語法,而且本身穩定,可用性是無需置疑的。
 

注:相關教程知識閱讀請移步到MYSQL教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品久久久久久中文字幕一区奶水| 久久人人爽亚洲精品天堂| 国产91精品久| 91沈先生作品| 狠狠色狠狠色综合日日五| 日韩在线观看免费全| 97在线观看免费高清| 国产精品美女视频网站| 精品成人乱色一区二区| 亚洲精品免费网站| 亚洲精品日韩av| 国产视频精品xxxx| 成人黄色免费看| 国产精品一区二区av影院萌芽| 国外色69视频在线观看| 国产成人精品免费视频| 日韩精品免费综合视频在线播放| 岛国av午夜精品| 亚洲精品v天堂中文字幕| 日韩欧美在线视频日韩欧美在线视频| 日韩中文字幕网| 久久色免费在线视频| 97国产suv精品一区二区62| 亚洲人成电影在线播放| 国内精品国产三级国产在线专| 国产精品91免费在线| 亚洲区中文字幕| 日韩在线视频观看正片免费网站| 最近2019中文字幕一页二页| 日本成人激情视频| 国产欧美精品一区二区三区介绍| 亚洲成人av片| 粗暴蹂躏中文一区二区三区| 亚洲电影免费观看高清完整版在线观看| 国产午夜精品视频免费不卡69堂| 亚洲精品视频免费在线观看| 欧美大片大片在线播放| 日本精品久久久| 欧美性极品xxxx做受| 亚洲自拍偷拍在线| 精品美女久久久久久免费| 国产日韩欧美电影在线观看| 亚洲精品自产拍| 亚洲丝袜在线视频| 中文字幕亚洲图片| 久久成年人免费电影| 伊人伊人伊人久久| 国产精品欧美久久久| 国产成+人+综合+亚洲欧美丁香花| 欧美老女人xx| 久久九九国产精品怡红院| 中文在线资源观看视频网站免费不卡| 欧美性精品220| 国产在线视频一区| 欧美精品在线网站| 日韩在线观看精品| 久久精品男人天堂| 日韩国产欧美精品在线| 日韩av电影手机在线| 亚洲第一网中文字幕| 亚洲第一中文字幕| 国产精品福利在线| 精品久久久久久久久久久久久| 欧美另类在线观看| 2023亚洲男人天堂| 久久久久久久久久久av| 国产成人一区二区| 久久久久久中文字幕| 国产在线精品成人一区二区三区| 91伊人影院在线播放| 亚洲色图av在线| 亚洲一区二区三区sesese| 国产丝袜一区二区三区| 51精品国产黑色丝袜高跟鞋| 日韩在线观看免费网站| 欧美野外猛男的大粗鳮| 日韩精品在线观| 亚洲欧美在线第一页| 国产精品18久久久久久首页狼| 久久99久国产精品黄毛片入口| 久热国产精品视频| 亚洲人成网7777777国产| 精品成人在线视频| 午夜伦理精品一区| 国语自产偷拍精品视频偷| 久久久精品欧美| 亚洲最大福利视频网站| 亚洲一区久久久| 亚洲最大成人免费视频| 日韩亚洲欧美成人| 精品女同一区二区三区在线播放| 狠狠躁18三区二区一区| 欧美视频裸体精品| 国产盗摄xxxx视频xxx69| 中文字幕在线看视频国产欧美| 91亚洲精品视频| 91精品国产91久久久久久久久| 久久久亚洲福利精品午夜| 性欧美长视频免费观看不卡| 黑人与娇小精品av专区| 亚洲精品久久久一区二区三区| 日韩精品中文字幕在线播放| 2021久久精品国产99国产精品| 亚洲人a成www在线影院| 蜜臀久久99精品久久久久久宅男| 成人国产精品日本在线| 国产精品吹潮在线观看| 色狠狠av一区二区三区香蕉蜜桃| 久久99视频精品| 精品久久久国产| 午夜精品久久久久久99热| 欧美综合激情网| 国产精品久久久av久久久| 久久国产天堂福利天堂| 91美女片黄在线观| 久久色免费在线视频| 亚洲va久久久噜噜噜久久天堂| 国产成人在线一区二区| 日韩最新av在线| 日韩极品精品视频免费观看| 国产日韩欧美黄色| 日韩欧美在线视频| 国产免费久久av| 欧美激情亚洲综合一区| 日韩在线观看免费av| 国产欧美va欧美va香蕉在| 最近2019中文字幕大全第二页| 国产精品美女免费视频| 成人免费看片视频| 亚洲www永久成人夜色| 91亚洲精品一区二区| 亚洲精品黄网在线观看| 成人亚洲激情网| 久久国产精品影片| 国产精品久久久久久久久久新婚| 一区三区二区视频| 91牛牛免费视频| 久热爱精品视频线路一| 成人午夜一级二级三级| 国产精品99久久久久久久久久久久| 日韩美女主播视频| 亚洲午夜女主播在线直播| 欧美日韩中文字幕| 欧美性猛交xxxx富婆弯腰| 亚洲精品福利免费在线观看| 亚洲激情成人网| 日本一区二区在线免费播放| 亚洲色图欧美制服丝袜另类第一页| 亚洲第一男人av| 亚洲精品美女视频| 久久6免费高清热精品| 国产一区二区三区四区福利| 中文字幕日韩精品在线| 6080yy精品一区二区三区| 午夜精品www| 国产精品久久久久久搜索| 成人免费高清完整版在线观看| 最新91在线视频| 久久99精品久久久久久噜噜| 成人精品网站在线观看| 欧美精品生活片| 日本久久中文字幕| 日韩视频亚洲视频| 97婷婷涩涩精品一区|