溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

MYSQL(四)查詢性能優(yōu)化

發(fā)布時(shí)間:2020-07-19 20:09:12 來源:網(wǎng)絡(luò) 閱讀:1490 作者:sun_tantan 欄目:MySQL數(shù)據(jù)庫

優(yōu)化數(shù)據(jù)訪問

1.是否向數(shù)據(jù)庫請求了不需要的數(shù)據(jù)

解決方式:

A. 查詢后加limit

B. Select后寫需要的列而不是*

2. 是否掃描了額外的數(shù)據(jù)

數(shù)據(jù)庫的訪問方式速度由慢到快:全表掃描,索引掃描,范圍掃描,唯一索引查詢,常數(shù)引用

MYSQL Explain命令 的type(數(shù)據(jù)庫引擎訪問表的方式):Const > ref > range > index > all

1. const 常數(shù)引用

如果是根據(jù)主鍵查詢,將會將查詢轉(zhuǎn)化為一個(gè)常數(shù),只取出確定的一行數(shù)據(jù)。是最快的一種。

2. Ref

查找條件列使用了索引而且不為主鍵和unique(值允許重復(fù)),只取出確定值的數(shù)據(jù),可能多行。

3. ref_eq 唯一索引查詢

ref_eq 與 ref相比,這種類型的查找結(jié)果集只有一個(gè)

4. range 范圍掃描

索引或主鍵,在某個(gè)范圍內(nèi)時(shí)

4. index 索引掃描

僅僅只有索引被掃描

5. all 全表掃描


一般mysql應(yīng)用where條件的方式由好到壞:

1. 在索引中使用where條件過濾,這是在存儲引擎層完成;

2. 使用索引覆蓋掃描,直接從索引中過濾不需要的數(shù)據(jù)并返回結(jié)果,這是在mysql服務(wù)器完成,無需再回表查詢(在extra中出現(xiàn)using index)

3. 從數(shù)據(jù)表中返回?cái)?shù)據(jù),然后過濾不滿足條件的數(shù)據(jù),在服務(wù)器層完成,mysql需要先從數(shù)據(jù)表讀出記錄然后過濾(在extra中出現(xiàn)using where)

好的索引可以讓查詢使用合適的訪問類型,減少掃描的數(shù)據(jù)行數(shù)。


執(zhí)行查詢的基礎(chǔ):

    1. 客戶端發(fā)送一條查詢給服務(wù)器

    2. 服務(wù)器先檢查緩存,如果命中緩存,立刻返回結(jié)果

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

    4. Mysql根據(jù)優(yōu)化器生成的執(zhí)行計(jì)劃,調(diào)用存儲引擎API執(zhí)行查詢計(jì)劃

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


第一步(客戶端發(fā)送一條查詢給服務(wù)器):

Mysql客戶端與服務(wù)器之間的通信是半雙工的,要么由服務(wù)器向客戶端發(fā)送數(shù)據(jù),要么由客戶端向服務(wù)器發(fā)送數(shù)據(jù),不能同時(shí)進(jìn)行;

所以為了進(jìn)行流量控制,客戶端發(fā)送查詢語句過長時(shí),超過max_allowed_packet參數(shù),服務(wù)器會拋出相應(yīng)錯(cuò)誤。

客戶端從服務(wù)器獲取數(shù)據(jù)時(shí),多數(shù)連接mysql的庫函數(shù)都可以獲得全部結(jié)果集并緩存到內(nèi)存里,mysql需要等所有數(shù)據(jù)都發(fā)給客戶端才能釋放這條查詢所占用的資源;

第三步(服務(wù)器進(jìn)行sql解析、預(yù)處理、查詢優(yōu)化):

首先,通過關(guān)鍵字將sql語句進(jìn)行解析,生成一顆“解析樹”;

解析器驗(yàn)證語法規(guī)則;

預(yù)處理器檢查解析樹是否合法,驗(yàn)證權(quán)限;

查詢優(yōu)化器使用優(yōu)化策略生成一個(gè)最優(yōu)的執(zhí)行計(jì)劃:

    1. 重新定義關(guān)聯(lián)表的順序

    2. 將外連接轉(zhuǎn)化為內(nèi)連接

    3. 優(yōu)化count(),min(),max()(根據(jù)b-tree只讀取第一條或最后一條數(shù)據(jù))

    4. 預(yù)估并轉(zhuǎn)化為常數(shù)表達(dá)式

    5. 提前終止查詢

    6. 列表in()的比較(將in列表的數(shù)據(jù)先排序,通過二分查找確定值是否滿足條件)

生成一個(gè)執(zhí)行計(jì)劃——指令樹:因?yàn)閙ysql的關(guān)聯(lián)從一張表開始嵌套,所以執(zhí)行計(jì)劃是一顆左側(cè)深度優(yōu)先的樹。

第四步(調(diào)用存儲引擎API執(zhí)行查詢計(jì)劃)

查詢優(yōu)化器在服務(wù)器層,而統(tǒng)計(jì)信息(每個(gè)表或索引有多少頁,每個(gè)表的每個(gè)索引的基數(shù)是多少,數(shù)據(jù)行和索引長度,索引的分布信息等)在存儲引擎層;

MYSQL執(zhí)行關(guān)聯(lián)查詢方式:

Mysql認(rèn)為任何一次查詢都是一次關(guān)聯(lián),并不僅僅一次查詢關(guān)系到兩張表時(shí)。

在MySQL 中,只有一種 Join 算法,就是 Nested Loop Join嵌套迭代。

 MYSQL(四)查詢性能優(yōu)化

Simple Nested-Loop Join簡單嵌套循環(huán):從驅(qū)動表中取出R1匹配S表所有列,然后R2,R3,直到將R表中的所有數(shù)據(jù)匹配完,然后合并數(shù)據(jù),可以看到這種算法要對S表進(jìn)行RN次訪問,雖然簡單,但是相對來說開銷還是太大了。

Index Nested-Loop Join索引嵌套循環(huán):由于非驅(qū)動表上有索引,所以比較的時(shí)候不再需要一條條記錄進(jìn)行比較,而可以通過索引來減少比較,從而加速查詢。

優(yōu)化:

選擇記錄數(shù)少的作為驅(qū)動表;

優(yōu)先優(yōu)化NestedLoop的內(nèi)層循環(huán);

保證被驅(qū)動表上Join條件字段已經(jīng)被索引


Mysql查詢優(yōu)化器的局限性

1.關(guān)聯(lián)子查詢

使用in加子查詢,性能非常糟糕

//未完

2. 最大值和最小值

對于max()和min()查詢,mysql的優(yōu)化并不好,如:

Select min(actor_id) from sakila.actor where first_name = “pene”;

因?yàn)閒irst_name字段上沒有索引,所以mysql會進(jìn)行一次全表掃描;

一個(gè)優(yōu)化辦法是:(使mysql進(jìn)行主鍵掃描)

select actor_id from sakila.actor use index(primary) where first_name = “pene” limit 1;

用主建索引查詢,因?yàn)閎-tree是按照主鍵順序排序,所以limit 1 = min(actor_id),查找索引直到復(fù)合where條件的第一條數(shù)據(jù)


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI