干貨系列——SQL語句的優(yōu)化

SQL語句的優(yōu)化

如何索取有性能問題SQL的渠道

通過用戶反饋獲取存在性能問題的SQL

通過慢查日志獲取存在性能問題的SQL

實(shí)時(shí)獲取存在性能問題的SQL

慢查詢?nèi)罩窘榻B

slow_quey_log=on 啟動(dòng)記錄慢查詢?nèi)罩?/p>

slow_query_log_file 指定慢查詢?nèi)罩镜拇鎯?chǔ)路徑及文件(默認(rèn)情況下保存在MySQL的數(shù)據(jù)目錄中)

long_query_time 指定記錄慢查詢?nèi)罩緎ql執(zhí)行的閾值(默認(rèn)為10秒,通常改為0.001秒比較合適)

log_queries_not_using_indexes 是否記錄未使用索引的SQL

set global sql_query_log=on;

sysbench --test=./oltp.lua --mysql-table-engine=innodb --oltp-table-size=10000 --mysql-db=tests --mysql-user=sbtest --mysql-password=123456 --oltp-tables-count=10 --mysql-socket=/usr/local/mysql/data/mysql.sock run

慢查詢?nèi)罩痉治龉ぞ?/p>

mysqldumpslow

匯總除查詢條件外其它完全相同的SQL并將分析結(jié)果按照參數(shù)中所指定的順序輸出

mysqldumpslow -s r -t 10 slow-mysql.log

-s order(c,t,l,r,at,al,ar)[指定按照哪種排序方式輸出結(jié)果]

t top[指定取前幾條作為結(jié)束輸出]

c按照查詢的次數(shù)排序

t按照查詢的總時(shí)間排序

l按照查詢中鎖的時(shí)間來排序

r按照查詢中返回總的數(shù)據(jù)行來排序

at绞呈、al艺智、ar平均數(shù)量來排序

pt-query-digest

pt-query-digest \

--explain h=127.0.0.1,u=root,p=p@ssWord \

slow-mysql.log

pt-query-digest --explain h=127.0.0.1 slow-mysql.log > slow.rep

實(shí)時(shí)獲取存在性能問題的SQL

select id,user,host,db,command,time,state,info

FROM information_schema.processlist

WHERE time>=60

查詢速度為什么會(huì)這麼慢志鹃?

客戶端發(fā)送SQL請(qǐng)求給服務(wù)器

服務(wù)器檢查是否可以在查詢緩存中命中該SQL

服務(wù)器端進(jìn)行SQL解析,預(yù)處理曹铃,再由優(yōu)化器生成對(duì)應(yīng)的執(zhí)行計(jì)劃

根據(jù)執(zhí)行計(jì)劃缰趋,調(diào)用存儲(chǔ)引擎API來查詢數(shù)據(jù)

將結(jié)果返回給客戶端

》 對(duì)于一個(gè)讀寫頻繁的系統(tǒng)使用查詢緩存很可能會(huì)降低查詢處理的效率,建議大家不要使用查詢緩存

2.其中涉及的參數(shù): query_cache_type 設(shè)置查詢緩存是否可用[ON,OFF,DEMAND] DEMAND表示只有在查詢語句中使用了SQL_CACHE和SQL_NO_CACHE來控制是否需要進(jìn)行緩存 query_cache_size 設(shè)置查詢緩存的內(nèi)存的大小 query_cache_limit 設(shè)置查詢緩存可用的存儲(chǔ)的最大值(加上SQL_NO_CACHE可以提高效率) query_cache_wlock_invalidate 設(shè)置數(shù)據(jù)表被鎖后是否返回緩存中的數(shù)據(jù) query_cache_min_res_unit 設(shè)置查詢緩存分配的內(nèi)存塊最小單位 3.MySQL依照這個(gè)執(zhí)行計(jì)劃和存儲(chǔ)引擎進(jìn)行交互 解析SQL陕见,預(yù)處理直撤。優(yōu)化SQL的查詢計(jì)劃 語法解析階段是通過關(guān)鍵字對(duì)MySQL語句進(jìn)行解析,并生成一顆對(duì)應(yīng)的解析樹 MySQL解析器將使用MySQL語法規(guī)則驗(yàn)證和解析查詢蜕着,包括檢查語法是否使用了正確的關(guān)鍵走谋竖;關(guān)鍵字的順序是否正確等等; 預(yù)處理階段是根據(jù)MySQL規(guī)則進(jìn)一步檢查解析樹是否合法 檢查查詢中所涉及的表和數(shù)據(jù)列是否存在及名字或別名是否存在歧義等等 語法檢查通過了承匣,查詢優(yōu)化器就可以生成查詢計(jì)劃了 優(yōu)化器SQL的查詢計(jì)劃階段對(duì)上一步所生成的執(zhí)行計(jì)劃進(jìn)行選擇基于成本模型的最優(yōu)的執(zhí)行計(jì)劃【下面是影響選擇最優(yōu)的查詢計(jì)劃的7因素】 1.統(tǒng)計(jì)信息不準(zhǔn)確 2.執(zhí)行計(jì)劃中的成本估算不等于實(shí)際的執(zhí)行計(jì)劃的成本 3.MySQL優(yōu)化器認(rèn)為的最優(yōu)的可能與你認(rèn)為最優(yōu)的不一樣【基于成本模型選擇最優(yōu)的執(zhí)行計(jì)劃】 4.MySQL從不考慮其他的并發(fā)的查詢蓖乘,這可能會(huì)影響當(dāng)前查詢的速度 5.MySQL有時(shí)候也會(huì)基于一些固定的規(guī)則來生成執(zhí)行計(jì)劃 6.MySQL不會(huì)考慮不受其控制的成本 查詢優(yōu)化器在目前的版本中可以進(jìn)行優(yōu)化的SQL的類型: 1.重新定義表的關(guān)聯(lián)順序 2.將外連接轉(zhuǎn)化為內(nèi)連接 3.使用等價(jià)變換規(guī)則 4.優(yōu)化count(),min()和max()[select tables optimozed away] 5.將一個(gè)表達(dá)式轉(zhuǎn)化為一個(gè)常數(shù)表達(dá)式 6.子查詢優(yōu)化 7.提前終止查詢 8.對(duì)in()條件進(jìn)行優(yōu)化

如何確定查詢處理各個(gè)階段所消耗的時(shí)間

使用profile[不建議使用,未來mysql中將被移除]

set profiling = 1;[啟動(dòng)profile,這是一個(gè)session級(jí)別的配置]

執(zhí)行查詢

show profiles;[查看每一個(gè)查詢所消耗的總的時(shí)間的信息]

show profile for query N;[查詢的每個(gè)階段所消耗的時(shí)間]

show profile cpu for query N;[查看每個(gè)階段所消耗的時(shí)間信息和所消耗的cpu的信息]

使用performance_schema

啟動(dòng)所需要的監(jiān)控和歷史記錄表的信息

update setup_instruments set enabled='yes',timed='yes' where name like 'stage%';

update setup_consumers set enabled='yes' where name like 'events%';

SELECT

a.thread_id,

sql_text,

c.event_name,

(c.timer_end - c.timer_start) / 1000000000 AS 'duration(ms)'

FROM

events_statements_history_long a

JOIN threads b on a.thread_id=b.thread_id

JOIN events_stages_history_long c ON c.thread_id=b.thread_id

AND c.event_id between a.event_id and a.end_event_id

WHERE b.processlist_id=CONNECTION_ID()

AND a.event_name='statement/sql/select'

ORDER BY a.thread_id,c.event_id

特定的SQL查詢優(yōu)化

大表的更新和刪除

delimiter $$ use 'imooc'$$ drop procedure if exists 'p_delete_rows'$$ create definer='root'@'127.0.0.1' procedure 'p_delete_rows'() begin declare v_rows int; set v_rows int, while v_rows=1, while v_rows>0 do delete from test where id>=9000 and id<=19000 limit 5000; select row_count() into v_rows; select sleep(5); end while; end $$ delimiter;

如何修改大表的表結(jié)構(gòu)

1.對(duì)表中的列的字段類型進(jìn)行修改改變字段的寬度時(shí)還是會(huì)進(jìn)行鎖表

2.無法解決主從數(shù)據(jù)庫延遲的問題

修改的方法:

pt-online-schema-change --alter="modify c varchar(150) not null default''" --user=root --password=PassWord D=testDataBaseName,t=tesTableName --charset=utf-8 --execute

如何優(yōu)化not in和<>查詢

#原始的SQL語句 SELECT customer_id, first_name, last_name, email FROM customer WHERE customer_id NOT IN ( SELECT customer_id FROM payment ) #優(yōu)化后的SQL語句 SELECT a.customer_id, a, first_name, a.last_name, a.email FROM customer a LEFT JOIN payment b ON a.customer_id = b.customer_id WHERE b.customer_id IS NULL

使用匯總表的方法進(jìn)行優(yōu)化

#統(tǒng)計(jì)商品的評(píng)論數(shù)[優(yōu)化前的SQL] select count(*) from product_comment where product_id=999; #匯總表就是提前以要統(tǒng)計(jì)的數(shù)據(jù)進(jìn)行匯總并記錄到數(shù)據(jù)庫中以備后續(xù)的查詢使用 create table product_comment_cnt(product_id int,cnt int); #統(tǒng)計(jì)商品的評(píng)論數(shù)[優(yōu)化后的SQL] select sum(cnt) from( select cnt from product_comment_cnt where product_id=999 union all select count(*) from product_comment where product_id=999 and timestr>DATE(NOW()) ) a

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末韧骗,一起剝皮案震驚了整個(gè)濱河市嘉抒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌袍暴,老刑警劉巖些侍,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件隶症,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡岗宣,警方通過查閱死者的電腦和手機(jī)蚂会,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來耗式,“玉大人胁住,你說我怎么就攤上這事】龋” “怎么了彪见?”我有些...
    開封第一講書人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)娱挨。 經(jīng)常有香客問我余指,道長(zhǎng),這世上最難降的妖魔是什么让蕾? 我笑而不...
    開封第一講書人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任浪规,我火速辦了婚禮,結(jié)果婚禮上探孝,老公的妹妹穿的比我還像新娘笋婿。我一直安慰自己,他們只是感情好顿颅,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開白布缸濒。 她就那樣靜靜地躺著,像睡著了一般粱腻。 火紅的嫁衣襯著肌膚如雪庇配。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,255評(píng)論 1 308
  • 那天绍些,我揣著相機(jī)與錄音捞慌,去河邊找鬼。 笑死柬批,一個(gè)胖子當(dāng)著我的面吹牛啸澡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播氮帐,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼嗅虏,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了上沐?” 一聲冷哼從身側(cè)響起皮服,我...
    開封第一講書人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后龄广,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體硫眯,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年择同,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了舟铜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡奠衔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出塘娶,到底是詐尸還是另有隱情归斤,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布刁岸,位于F島的核電站脏里,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏虹曙。R本人自食惡果不足惜迫横,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望酝碳。 院中可真熱鬧矾踱,春花似錦、人聲如沸疏哗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽返奉。三九已至贝搁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間芽偏,已是汗流浹背雷逆。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留污尉,地道東北人膀哲。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像十厢,于是被迫代替她去往敵國和親等太。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 一蛮放、SQL速成 結(jié)構(gòu)查詢語言(SQL)是用于查詢關(guān)系數(shù)據(jù)庫的標(biāo)準(zhǔn)語言缩抡,它包括若干關(guān)鍵字和一致的語法,便于數(shù)據(jù)庫元件...
    shadow雨軒閱讀 514評(píng)論 0 3
  • cc@cc-Inspiron-3542:~$ mysql -u root -p;Enter password:We...
    叫我老村長(zhǎng)閱讀 776評(píng)論 0 0
  • 有時(shí)候想想是不是自己真的太獨(dú)斷了?好像覺得自己也算是小有成績(jī)?nèi)缓缶陀X得自己已經(jīng)掌握了一套方法瞻想,就聽不進(jìn)去那些看似不...
    好大一只蟲閱讀 130評(píng)論 0 0
  • 所有的時(shí)光都是被辜負(fù)被浪費(fèi)的压真,也只有在辜負(fù)浪費(fèi)之后,才能從記憶里將某一段拎出蘑险,拍拍上面的沉積的灰塵滴肿,感嘆她是最好的...
    加了鹽的咖啡閱讀 184評(píng)論 0 0
  • 從2005年到至今、我一直在鄉(xiāng)村學(xué)校任教佃迄!在這12年里泼差、從懵懂到成熟的蛻變把最美好的青春奉獻(xiàn)在了這片我熱愛的鄉(xiāng)...
    啊秋老師閱讀 358評(píng)論 1 1