mysql -u root -p 回車輸入密碼進(jìn)入mysql
在隰縣等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都網(wǎng)站建設(shè)、網(wǎng)站建設(shè) 網(wǎng)站設(shè)計制作專業(yè)公司,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站制作,營銷型網(wǎng)站,外貿(mào)網(wǎng)站建設(shè),隰縣網(wǎng)站建設(shè)費用合理。
show processlist;
查看連接數(shù),可以發(fā)現(xiàn)有很多連接處于sleep狀態(tài),這些其實是暫時沒有用的,所以可以kill掉
show variables like "max_connections";
查看最大連接數(shù),應(yīng)該是與上面查詢到的連接數(shù)相同,才會出現(xiàn)too many connections的情況
set GLOBAL max_connections=1000;
修改最大連接數(shù),但是這不是一勞永逸的方法,應(yīng)該要讓它自動殺死那些sleep的進(jìn)程。
show global variables like 'wait_timeout';
這個數(shù)值指的是mysql在關(guān)閉一個非交互的連接之前要等待的秒數(shù),默認(rèn)是28800s
set global wait_timeout=300;
修改這個數(shù)值,這里可以隨意,最好控制在幾分鐘內(nèi)
set global interactive_timeout=500;
修改這個數(shù)值,表示mysql在關(guān)閉一個連接之前要等待的秒數(shù),至此可以讓mysql自動關(guān)閉那些沒用的連接,但要注意的是,正在使用的連接到了時間也會被關(guān)閉,因此這個時間值要合適
SHOW VARIABLES LIKE '%table_open_cache%';
查看
show global status like 'Open%tables';
在開始演示之前,我們先介紹下兩個概念。
概念一,數(shù)據(jù)的可選擇性基數(shù),也就是常說的cardinality值。
查詢優(yōu)化器在生成各種執(zhí)行計劃之前,得先從統(tǒng)計信息中取得相關(guān)數(shù)據(jù),這樣才能估算每步操作所涉及到的記錄數(shù),而這個相關(guān)數(shù)據(jù)就是cardinality。簡單來說,就是每個值在每個字段中的唯一值分布狀態(tài)。
比如表t1有100行記錄,其中一列為f1。f1中唯一值的個數(shù)可以是100個,也可以是1個,當(dāng)然也可以是1到100之間的任何一個數(shù)字。這里唯一值越的多少,就是這個列的可選擇基數(shù)。
那看到這里我們就明白了,為什么要在基數(shù)高的字段上建立索引,而基數(shù)低的的字段建立索引反而沒有全表掃描來的快。當(dāng)然這個只是一方面,至于更深入的探討就不在我這篇探討的范圍了。
概念二,關(guān)于HINT的使用。
這里我來說下HINT是什么,在什么時候用。
HINT簡單來說就是在某些特定的場景下人工協(xié)助MySQL優(yōu)化器的工作,使她生成最優(yōu)的執(zhí)行計劃。一般來說,優(yōu)化器的執(zhí)行計劃都是最優(yōu)化的,不過在某些特定場景下,執(zhí)行計劃可能不是最優(yōu)化。
比如:表t1經(jīng)過大量的頻繁更新操作,(UPDATE,DELETE,INSERT),cardinality已經(jīng)很不準(zhǔn)確了,這時候剛好執(zhí)行了一條SQL,那么有可能這條SQL的執(zhí)行計劃就不是最優(yōu)的。為什么說有可能呢?
來看下具體演示
譬如,以下兩條SQL,
A:
select * from t1 where f1 = 20;
B:
select * from t1 where f1 = 30;
如果f1的值剛好頻繁更新的值為30,并且沒有達(dá)到MySQL自動更新cardinality值的臨界值或者說用戶設(shè)置了手動更新又或者用戶減少了sample page等等,那么對這兩條語句來說,可能不準(zhǔn)確的就是B了。
這里順帶說下,MySQL提供了自動更新和手動更新表cardinality值的方法,因篇幅有限,需要的可以查閱手冊。
那回到正題上,MySQL 8.0 帶來了幾個HINT,我今天就舉個index_merge的例子。
示例表結(jié)構(gòu):
mysql desc t1;+------------+--------------+------+-----+---------+----------------+| Field ? ? ?| Type ? ? ? ? | Null | Key | Default | Extra ? ? ? ? ?|+------------+--------------+------+-----+---------+----------------+| id ? ? ? ? | int(11) ? ? ?| NO ? | PRI | NULL ? ?| auto_increment || rank1 ? ? ?| int(11) ? ? ?| YES ?| MUL | NULL ? ?| ? ? ? ? ? ? ? ?|| rank2 ? ? ?| int(11) ? ? ?| YES ?| MUL | NULL ? ?| ? ? ? ? ? ? ? ?|| log_time ? | datetime ? ? | YES ?| MUL | NULL ? ?| ? ? ? ? ? ? ? ?|| prefix_uid | varchar(100) | YES ?| ? ? | NULL ? ?| ? ? ? ? ? ? ? ?|| desc1 ? ? ?| text ? ? ? ? | YES ?| ? ? | NULL ? ?| ? ? ? ? ? ? ? ?|| rank3 ? ? ?| int(11) ? ? ?| YES ?| MUL | NULL ? ?| ? ? ? ? ? ? ? ?|+------------+--------------+------+-----+---------+----------------+7 rows in set (0.00 sec)
表記錄數(shù):
mysql select count(*) from t1;+----------+| count(*) |+----------+| ? ?32768 |+----------+1 row in set (0.01 sec)
這里我們兩條經(jīng)典的SQL:
SQL C:
select * from t1 where rank1 = 1 or rank2 = 2 or rank3 = 2;
SQL D:
select * from t1 where rank1 =100 ?and rank2 =100 ?and rank3 =100;
表t1實際上在rank1,rank2,rank3三列上分別有一個二級索引。
那我們來看SQL C的查詢計劃。
顯然,沒有用到任何索引,掃描的行數(shù)為32034,cost為3243.65。
mysql explain ?format=json select * from t1 ?where rank1 =1 or rank2 = 2 or rank3 = 2\G*************************** 1. row ***************************EXPLAIN: { ?"query_block": { ? ?"select_id": 1, ? ?"cost_info": { ? ? ?"query_cost": "3243.65" ? ?}, ? ?"table": { ? ? ?"table_name": "t1", ? ? ?"access_type": "ALL", ? ? ?"possible_keys": [ ? ? ? ?"idx_rank1", ? ? ? ?"idx_rank2", ? ? ? ?"idx_rank3" ? ? ?], ? ? ?"rows_examined_per_scan": 32034, ? ? ?"rows_produced_per_join": 115, ? ? ?"filtered": "0.36", ? ? ?"cost_info": { ? ? ? ?"read_cost": "3232.07", ? ? ? ?"eval_cost": "11.58", ? ? ? ?"prefix_cost": "3243.65", ? ? ? ?"data_read_per_join": "49K" ? ? ?}, ? ? ?"used_columns": [ ? ? ? ?"id", ? ? ? ?"rank1", ? ? ? ?"rank2", ? ? ? ?"log_time", ? ? ? ?"prefix_uid", ? ? ? ?"desc1", ? ? ? ?"rank3" ? ? ?], ? ? ?"attached_condition": "((`ytt`.`t1`.`rank1` = 1) or (`ytt`.`t1`.`rank2` = 2) or (`ytt`.`t1`.`rank3` = 2))" ? ?} ?}}1 row in set, 1 warning (0.00 sec)
我們加上hint給相同的查詢,再次看看查詢計劃。
這個時候用到了index_merge,union了三個列。掃描的行數(shù)為1103,cost為441.09,明顯比之前的快了好幾倍。
mysql explain ?format=json select /*+ index_merge(t1) */ * from t1 ?where rank1 =1 or rank2 = 2 or rank3 = 2\G*************************** 1. row ***************************EXPLAIN: { ?"query_block": { ? ?"select_id": 1, ? ?"cost_info": { ? ? ?"query_cost": "441.09" ? ?}, ? ?"table": { ? ? ?"table_name": "t1", ? ? ?"access_type": "index_merge", ? ? ?"possible_keys": [ ? ? ? ?"idx_rank1", ? ? ? ?"idx_rank2", ? ? ? ?"idx_rank3" ? ? ?], ? ? ?"key": "union(idx_rank1,idx_rank2,idx_rank3)", ? ? ?"key_length": "5,5,5", ? ? ?"rows_examined_per_scan": 1103, ? ? ?"rows_produced_per_join": 1103, ? ? ?"filtered": "100.00", ? ? ?"cost_info": { ? ? ? ?"read_cost": "330.79", ? ? ? ?"eval_cost": "110.30", ? ? ? ?"prefix_cost": "441.09", ? ? ? ?"data_read_per_join": "473K" ? ? ?}, ? ? ?"used_columns": [ ? ? ? ?"id", ? ? ? ?"rank1", ? ? ? ?"rank2", ? ? ? ?"log_time", ? ? ? ?"prefix_uid", ? ? ? ?"desc1", ? ? ? ?"rank3" ? ? ?], ? ? ?"attached_condition": "((`ytt`.`t1`.`rank1` = 1) or (`ytt`.`t1`.`rank2` = 2) or (`ytt`.`t1`.`rank3` = 2))" ? ?} ?}}1 row in set, 1 warning (0.00 sec)
我們再看下SQL D的計劃:
不加HINT,
mysql explain format=json select * from t1 where rank1 =100 and rank2 =100 and rank3 =100\G*************************** 1. row ***************************EXPLAIN: { ?"query_block": { ? ?"select_id": 1, ? ?"cost_info": { ? ? ?"query_cost": "534.34" ? ?}, ? ?"table": { ? ? ?"table_name": "t1", ? ? ?"access_type": "ref", ? ? ?"possible_keys": [ ? ? ? ?"idx_rank1", ? ? ? ?"idx_rank2", ? ? ? ?"idx_rank3" ? ? ?], ? ? ?"key": "idx_rank1", ? ? ?"used_key_parts": [ ? ? ? ?"rank1" ? ? ?], ? ? ?"key_length": "5", ? ? ?"ref": [ ? ? ? ?"const" ? ? ?], ? ? ?"rows_examined_per_scan": 555, ? ? ?"rows_produced_per_join": 0, ? ? ?"filtered": "0.07", ? ? ?"cost_info": { ? ? ? ?"read_cost": "478.84", ? ? ? ?"eval_cost": "0.04", ? ? ? ?"prefix_cost": "534.34", ? ? ? ?"data_read_per_join": "176" ? ? ?}, ? ? ?"used_columns": [ ? ? ? ?"id", ? ? ? ?"rank1", ? ? ? ?"rank2", ? ? ? ?"log_time", ? ? ? ?"prefix_uid", ? ? ? ?"desc1", ? ? ? ?"rank3" ? ? ?], ? ? ?"attached_condition": "((`ytt`.`t1`.`rank3` = 100) and (`ytt`.`t1`.`rank2` = 100))" ? ?} ?}}1 row in set, 1 warning (0.00 sec)
加了HINT,
mysql explain format=json select /*+ index_merge(t1)*/ * from t1 where rank1 =100 and rank2 =100 and rank3 =100\G*************************** 1. row ***************************EXPLAIN: { ?"query_block": { ? ?"select_id": 1, ? ?"cost_info": { ? ? ?"query_cost": "5.23" ? ?}, ? ?"table": { ? ? ?"table_name": "t1", ? ? ?"access_type": "index_merge", ? ? ?"possible_keys": [ ? ? ? ?"idx_rank1", ? ? ? ?"idx_rank2", ? ? ? ?"idx_rank3" ? ? ?], ? ? ?"key": "intersect(idx_rank1,idx_rank2,idx_rank3)", ? ? ?"key_length": "5,5,5", ? ? ?"rows_examined_per_scan": 1, ? ? ?"rows_produced_per_join": 1, ? ? ?"filtered": "100.00", ? ? ?"cost_info": { ? ? ? ?"read_cost": "5.13", ? ? ? ?"eval_cost": "0.10", ? ? ? ?"prefix_cost": "5.23", ? ? ? ?"data_read_per_join": "440" ? ? ?}, ? ? ?"used_columns": [ ? ? ? ?"id", ? ? ? ?"rank1", ? ? ? ?"rank2", ? ? ? ?"log_time", ? ? ? ?"prefix_uid", ? ? ? ?"desc1", ? ? ? ?"rank3" ? ? ?], ? ? ?"attached_condition": "((`ytt`.`t1`.`rank3` = 100) and (`ytt`.`t1`.`rank2` = 100) and (`ytt`.`t1`.`rank1` = 100))" ? ?} ?}}1 row in set, 1 warning (0.00 sec)
對比下以上兩個,加了HINT的比不加HINT的cost小了100倍。
總結(jié)下,就是說表的cardinality值影響這張的查詢計劃,如果這個值沒有正常更新的話,就需要手工加HINT了。相信MySQL未來的版本會帶來更多的HINT。
數(shù)據(jù)庫優(yōu)化一方面是找出系統(tǒng)的瓶頸,提高M(jìn)ySQL數(shù)據(jù)庫的整體性能,而另一方面需要合理的結(jié)構(gòu)設(shè)計和參數(shù)調(diào)整,以提高用戶的相應(yīng)速度,同時還要盡可能的節(jié)約系統(tǒng)資源,以便讓系統(tǒng)提供更大的負(fù)荷.
1. 優(yōu)化一覽圖
2. 優(yōu)化
筆者將優(yōu)化分為了兩大類,軟優(yōu)化和硬優(yōu)化,軟優(yōu)化一般是操作數(shù)據(jù)庫即可,而硬優(yōu)化則是操作服務(wù)器硬件及參數(shù)設(shè)置.
2.1 軟優(yōu)化
2.1.1 查詢語句優(yōu)化
1.首先我們可以用EXPLAIN或DESCRIBE(簡寫:DESC)命令分析一條查詢語句的執(zhí)行信息.
2.例:
顯示:
其中會顯示索引和查詢數(shù)據(jù)讀取數(shù)據(jù)條數(shù)等信息.
2.1.2 優(yōu)化子查詢
在MySQL中,盡量使用JOIN來代替子查詢.因為子查詢需要嵌套查詢,嵌套查詢時會建立一張臨時表,臨時表的建立和刪除都會有較大的系統(tǒng)開銷,而連接查詢不會創(chuàng)建臨時表,因此效率比嵌套子查詢高.
2.1.3 使用索引
索引是提高數(shù)據(jù)庫查詢速度最重要的方法之一,關(guān)于索引可以參高筆者M(jìn)ySQL數(shù)據(jù)庫索引一文,介紹比較詳細(xì),此處記錄使用索引的三大注意事項:
2.1.4 分解表
對于字段較多的表,如果某些字段使用頻率較低,此時應(yīng)當(dāng),將其分離出來從而形成新的表,
2.1.5 中間表
對于將大量連接查詢的表可以創(chuàng)建中間表,從而減少在查詢時造成的連接耗時.
2.1.6 增加冗余字段
類似于創(chuàng)建中間表,增加冗余也是為了減少連接查詢.
2.1.7 分析表,,檢查表,優(yōu)化表
分析表主要是分析表中關(guān)鍵字的分布,檢查表主要是檢查表中是否存在錯誤,優(yōu)化表主要是消除刪除或更新造成的表空間浪費.
1. 分析表: 使用 ANALYZE 關(guān)鍵字,如ANALYZE TABLE user;
2. 檢查表: 使用 CHECK關(guān)鍵字,如CHECK TABLE user [option]
option 只對MyISAM有效,共五個參數(shù)值:
3. 優(yōu)化表:使用OPTIMIZE關(guān)鍵字,如OPTIMIZE [LOCAL|NO_WRITE_TO_BINLOG] TABLE user;
LOCAL|NO_WRITE_TO_BINLOG都是表示不寫入日志.,優(yōu)化表只對VARCHAR,BLOB和TEXT有效,通過OPTIMIZE TABLE語句可以消除文件碎片,在執(zhí)行過程中會加上只讀鎖.
2.2 硬優(yōu)化
2.2.1 硬件三件套
1.配置多核心和頻率高的cpu,多核心可以執(zhí)行多個線程.
2.配置大內(nèi)存,提高內(nèi)存,即可提高緩存區(qū)容量,因此能減少磁盤I/O時間,從而提高響應(yīng)速度.
3.配置高速磁盤或合理分布磁盤:高速磁盤提高I/O,分布磁盤能提高并行操作的能力.
2.2.2 優(yōu)化數(shù)據(jù)庫參數(shù)
優(yōu)化數(shù)據(jù)庫參數(shù)可以提高資源利用率,從而提高M(jìn)ySQL服務(wù)器性能.MySQL服務(wù)的配置參數(shù)都在my.cnf或my.ini,下面列出性能影響較大的幾個參數(shù).
2.2.3 分庫分表
因為數(shù)據(jù)庫壓力過大,首先一個問題就是高峰期系統(tǒng)性能可能會降低,因為數(shù)據(jù)庫負(fù)載過高對性能會有影響。另外一個,壓力過大把你的數(shù)據(jù)庫給搞掛了怎么辦?所以此時你必須得對系統(tǒng)做分庫分表 + 讀寫分離,也就是把一個庫拆分為多個庫,部署在多個數(shù)據(jù)庫服務(wù)上,這時作為主庫承載寫入請求。然后每個主庫都掛載至少一個從庫,由從庫來承載讀請求。
2.2.4 緩存集群
如果用戶量越來越大,此時你可以不停的加機(jī)器,比如說系統(tǒng)層面不停加機(jī)器,就可以承載更高的并發(fā)請求。然后數(shù)據(jù)庫層面如果寫入并發(fā)越來越高,就擴(kuò)容加數(shù)據(jù)庫服務(wù)器,通過分庫分表是可以支持?jǐn)U容機(jī)器的,如果數(shù)據(jù)庫層面的讀并發(fā)越來越高,就擴(kuò)容加更多的從庫。但是這里有一個很大的問題:數(shù)據(jù)庫其實本身不是用來承載高并發(fā)請求的,所以通常來說,數(shù)據(jù)庫單機(jī)每秒承載的并發(fā)就在幾千的數(shù)量級,而且數(shù)據(jù)庫使用的機(jī)器都是比較高配置,比較昂貴的機(jī)器,成本很高。如果你就是簡單的不停的加機(jī)器,其實是不對的。所以在高并發(fā)架構(gòu)里通常都有緩存這個環(huán)節(jié),緩存系統(tǒng)的設(shè)計就是為了承載高并發(fā)而生。所以單機(jī)承載的并發(fā)量都在每秒幾萬,甚至每秒數(shù)十萬,對高并發(fā)的承載能力比數(shù)據(jù)庫系統(tǒng)要高出一到兩個數(shù)量級。所以你完全可以根據(jù)系統(tǒng)的業(yè)務(wù)特性,對那種寫少讀多的請求,引入緩存集群。具體來說,就是在寫數(shù)據(jù)庫的時候同時寫一份數(shù)據(jù)到緩存集群里,然后用緩存集群來承載大部分的讀請求。這樣的話,通過緩存集群,就可以用更少的機(jī)器資源承載更高的并發(fā)。
一個完整而復(fù)雜的高并發(fā)系統(tǒng)架構(gòu)中,一定會包含:各種復(fù)雜的自研基礎(chǔ)架構(gòu)系統(tǒng)。各種精妙的架構(gòu)設(shè)計.因此一篇小文頂多具有拋磚引玉的效果,但是數(shù)據(jù)庫優(yōu)化的思想差不多就這些了.
修改mysql配置文件,優(yōu)化緩存大小和連接數(shù)連接方式,優(yōu)化sql語句 ,記得mysql好像是有工具可以查看最占用資源的sql語句,找到他,優(yōu)化他。
安裝好mysql后,配制文件應(yīng)該在/usr/local/mysql/share/mysql目錄中,配制文件有幾個,有my-huge.cnf my-medium.cnf my-large.cnf my-small.cnf,不同的流量的網(wǎng)站和不同配制的服務(wù)器環(huán)境,當(dāng)然需要有不同的配制文件了。
一般的情況下,my-medium.cnf這個配制文件就能滿足我們的大多需要;一般我們會把配置文件拷貝到/etc/my.cnf 只需要修改這個配置文件就可以了,使用mysqladmin variables extended-status _u root _p 可以看到目前的參數(shù),有3個配置參數(shù)是最重要的,即key_buffer_size,query_cache_size,table_cache。
key_buffer_size只對MyISAM表起作用,
key_buffer_size指定索引緩沖區(qū)的大小,它決定索引處理的速度,尤其是索引讀的速度。一般我們設(shè)為16M,實際上稍微大一點的站點 這個數(shù)字是遠(yuǎn)遠(yuǎn)不夠的,通過檢查狀態(tài)值Key_read_requests和Key_reads,可以知道key_buffer_size設(shè)置是否合理。比例 key_reads / key_read_requests應(yīng)該盡可能的低,至少是1:100,1:1000更好(上述狀態(tài)值可以使用SHOW STATUS LIKE ‘key_read%’獲得)。 或者如果你裝了phpmyadmin 可以通過服務(wù)器運行狀態(tài)看到,筆者推薦用phpmyadmin管理mysql,以下的狀態(tài)值都是本人通過phpmyadmin獲得的實例分析:
這個服務(wù)器已經(jīng)運行了20天
key_buffer_size _ 128M
key_read_requests _ 650759289
key_reads - 79112
比例接近1:8000 健康狀況非常好