日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql如何explan优化sql_《MySQL数据库》MySQL 优化SQL(explain)

發(fā)布時(shí)間:2024/4/18 数据库 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql如何explan优化sql_《MySQL数据库》MySQL 优化SQL(explain) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

如果要寫出優(yōu)質(zhì)的SQL語句,就需要了解MySQL的存儲(chǔ)原理。MySQL是如何分析SQL,如何利用索引查詢。

Explain 關(guān)鍵字

explain select * from ic_base;? ? ? ? ? ? ? ? ? --查看SQL的執(zhí)行情況

id:執(zhí)行編號,標(biāo)識Select的執(zhí)行順序,存在子查詢等負(fù)責(zé)查詢的時(shí)候用來標(biāo)識執(zhí)行的優(yōu)先順序。

select_type:?select查詢語句的類型(simple,primary,subquery,derived,union,union result,dependent union,dependent subquery)。

>?simple : 簡單SQL

>?primary?: 包含union或者子查詢,最外層的部分標(biāo)記為primary

>?subquery?: 非相關(guān)子查詢(子查詢和主表之間有關(guān)聯(lián)關(guān)系)

>?derived?:?派生表——該臨時(shí)表是從子查詢派生出來的,位于form中的子查詢

>?union?: 包含union 或者 union all 的查詢

>?union result?: MySQL建立的臨時(shí)表需要去掉重復(fù)數(shù)據(jù)

>?dependent union?:?顧名思義,首先需要滿足UNION的條件,及UNION中第二個(gè)以及后面的SELECT語句,同時(shí)該語句依賴外部的查詢

>?dependent subquery?:?相關(guān)子查詢(子查詢和主表之間有關(guān)聯(lián)關(guān)系)

> materialized :當(dāng)查詢優(yōu)化器在執(zhí)行包含子查詢的語句時(shí),選擇將子查詢物化之后與外層查詢進(jìn)行連接查詢。

table:訪問的表名

partitions:分區(qū)信息

type:?訪問類型(system > const > eq_ref > ref > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL),innodb中不存在system.一般來說,得保證查詢至少達(dá)到range級別,最好能達(dá)到ref。

>?system?:?這是const連接類型的一種特例,表只有一行數(shù)據(jù)

> const?: 主鍵索引僅有一行滿足條件

> eq_ref?:?被驅(qū)動(dòng)表和驅(qū)動(dòng)表通過驅(qū)動(dòng)表的主鍵關(guān)聯(lián)。

> ref?: 輔助索引訪問,等值匹配或者常量匹配。

> ref_or_null?: 索引訪問,等值匹配或者常量匹配,存在null值。

> index_merge?:?合并索引,有多個(gè)索引可以選擇。

> unique_subquery?:?子查詢使用唯一索引

> index_subquery?:?子查詢使用索引

> range?:?范圍掃描,一個(gè)有限制的索引掃描。key列顯示使用了哪個(gè)索引。當(dāng)使用=、<>、>、>=、、BETWEEN 和IN 操作符,用常量比較關(guān)鍵字列時(shí)。

> index?:?和全表掃描一樣。只是掃描表的時(shí)候按照索引次序進(jìn)行而不是行。主要優(yōu)點(diǎn)就是避免了排序, 但是開銷仍然非常大。

> ALL :?全表掃描

possible_keys:顯示能夠使用的索引

key:使用的索引

key_len:使用的索引長度(使用的索引字段長度之和,字段沒有設(shè)置非空,需要加1,varchar 字段還要加2)

ref:關(guān)聯(lián)列或者常數(shù)

rows:數(shù)據(jù)行數(shù)(來自統(tǒng)計(jì)信息)

filtered:過濾百分比,可能滿足條數(shù)/總條數(shù)

Extra:MySQL的補(bǔ)充額外信息

> no tables used : 沒有額外信息

> Using where : 當(dāng)我們使用全表掃描來執(zhí)行對某個(gè)表的查詢,并且該語句的WHERE子句中有針對該表的搜索條件

> Using index: 當(dāng)我們的查詢列表以及搜索條件中只包含屬于某個(gè)索引的列,也就是在可以使用索引覆蓋的情況

> Impossible where: 查詢語句的WHERE子句永遠(yuǎn)為FALSE時(shí)將會(huì)提示該額外信息

> Using index condition:?有些搜索條件中雖然出現(xiàn)了索引列,但卻不能使用到索引

> no matching min/max row:?當(dāng)查詢列表處有MIN或者M(jìn)AX聚集函數(shù),但是并沒有符合WHERE子句中的搜索條件的記錄

> Using join buffer(block nested loop) : 在連接查詢執(zhí)行過程中,當(dāng)被驅(qū)動(dòng)表不能有效的利用索引加快訪問速度,MySQL一般會(huì)為其分配一塊名叫join

buffer的內(nèi)存塊來加快查詢速度

> Using filesort : 很多情況下排序操作無法使用到索引,只能在內(nèi)存中(記錄較少的時(shí)候)或者磁盤中(記錄較多的時(shí)候)進(jìn)行排序,這種在內(nèi)存中或者磁盤上進(jìn)行排序的方式統(tǒng)稱為文件排序(英文名:filesort)

> Using temporary : 在許多查詢的執(zhí)行過程中,MySQL可能會(huì)借助臨時(shí)表來完成一些功能,比如去重、排序之類的,比如我們在執(zhí)行許多包含DISTINCT、GROUP BY、UNION等子句的查詢過程中,如果不能有效利用索引來完成查詢,MySQL很有可能尋求通過建立內(nèi)部的臨時(shí)表來執(zhí)行查詢

> start temporary , end temporary: 查詢優(yōu)化器會(huì)優(yōu)先嘗試將IN子查詢轉(zhuǎn)換成semi-join,而semi-join又有好多種執(zhí)行策略,當(dāng)執(zhí)行策略為DuplicateWeedout時(shí),也就是通過建立臨時(shí)表來實(shí)現(xiàn)為外層查詢中的記錄進(jìn)行去重操作時(shí),驅(qū)動(dòng)表查詢執(zhí)行計(jì)劃的Extra列將顯示Start temporary提示,被驅(qū)動(dòng)表查詢執(zhí)行計(jì)劃的Extra列將顯示End temporary提示

> FirstMatch(表名) : 在將In子查詢轉(zhuǎn)為semi-join的去重的方式(找到一條就返回)

查詢優(yōu)化器

set optimizer_trace="enabled=on";? ? ? ?--打開查詢優(yōu)化器

---------------需要執(zhí)行的SQL(可以使用explain)-------------------------

select * from information_schema.OPTIMIZER_TRACE? ? ?--查詢優(yōu)化器的執(zhí)行結(jié)果

set optimizer_trace="enabled=off";? ? ? ?--關(guān)閉查詢優(yōu)化器

查詢優(yōu)化器查詢的結(jié)果

query: 對應(yīng)SQL.

trace :優(yōu)化過程(里面有行估算,走索引,最左前綴等一些計(jì)算成本的過程,然后MySQL自動(dòng)選擇一種最優(yōu)方式)。

成本計(jì)算公式:全表掃描的公式: 主鍵索引頁數(shù)*1 + 行數(shù)*0.2 = Data_length/16K + Rows*0.2 ;? ? 主鍵索引頁數(shù),行數(shù)來自統(tǒng)計(jì)信息, 其他數(shù)據(jù)為MySQL固定常量

由于MySQL的成本計(jì)算也是估算(99%是靠譜的),但是當(dāng)遇到很復(fù)雜的SQL,或者統(tǒng)計(jì)信息與實(shí)際情況差距太大的時(shí)候,會(huì)導(dǎo)致MySQL的優(yōu)化過程出現(xiàn)問題。

這個(gè)時(shí)候我們需要干擾MySQL的執(zhí)行計(jì)劃,強(qiáng)制走我們需要的索引或者更新統(tǒng)計(jì)信息。

索引失效

1. 隱式轉(zhuǎn)換,不走索引

表ic_website的url 創(chuàng)建了一個(gè)普通索引,并且該字段是varchar類型,會(huì)出現(xiàn)一下情況:

explain select * from ic_website where url = '123';? ? --? 索引有效

explain select * from ic_website where url = 123;? ? --? 索引失效

2. <>,not in 不走普通索引,主鍵索引還是可以走索引。

explain select * from ic_website where url <> '123';

3. 左邊有% 的不走索引

explain select * from ic_website where url like '%123';

實(shí)戰(zhàn)

一、ANALYZE TABLE? ic_base;? ?-- 重新收集ic_base 的統(tǒng)計(jì)信息,保證MySQL優(yōu)化器計(jì)算準(zhǔn)確。 查看統(tǒng)計(jì)信息是否被更新:select * from mysql.innodb_table_stats;

select * from mysql.innodb_index_stats;

二、hints

USE INDEX:限制索引的使用范圍,們在數(shù)據(jù)表里建立了很多索引,當(dāng)MySQL對索引進(jìn)行選擇 時(shí),這些索引都在考慮的范圍內(nèi)。但有時(shí)我們希望MySQL只考慮幾個(gè)索引,而不是全部的索引, 這就需要用到USE INDEX對查詢語句進(jìn)行設(shè)置。

IGNORE INDEX :限制不使用索引的范圍

FORCE INDEX:我們希望MySQL必須要使用某一個(gè)索引(由于 MySQL在查詢時(shí)只能使用一個(gè)索 引,因此只能強(qiáng)迫MySQL使用一個(gè)索引)。這就需要使用FORCE INDEX來完成這個(gè)功能。

hints 語法:

SELECT * FROM table1 USE|IGNORE|FORCE INDEX (col1_index,col2_index) WHERE col1=1 ANDcol2=2 AND col3=3;

三、straight_join? ?-- 強(qiáng)制改成左邊為驅(qū)動(dòng)表

select t1.* fromTable1 t1 STRAIGHT_JOIN Table2 t2on t1.CommonID = t2.CommonID where t1.FilterID = 1

總結(jié)

SQL優(yōu)化伴隨開發(fā)的全部過程,隨著時(shí)間和業(yè)務(wù)的推移,一些SQL的性能跟不上了,需要重新整理和優(yōu)化。

筆者遇到過好幾千行的SQL(union,子查詢,嵌套查詢,函數(shù),分組,排序)幾乎用了SQL的全部特性,優(yōu)化這類SQL第一要熟悉SQL的作用,第二點(diǎn)要將這類SQL拆小,先找到慢的地方,然后再考慮優(yōu)化。優(yōu)化SQL是一個(gè)需要耐心的活,平時(shí)一定要注意SQL寫法,盡量避免一些糟糕的寫法,減少后期的維護(hù)。

總結(jié)

以上是生活随笔為你收集整理的mysql如何explan优化sql_《MySQL数据库》MySQL 优化SQL(explain)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。