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

歡迎訪問 生活随笔!

生活随笔

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

数据库

MySQL基础总结(三)

發(fā)布時間:2024/4/11 数据库 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL基础总结(三) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

MySQL基礎(chǔ)總結(jié)(三)

文章目錄

  • MySQL基礎(chǔ)總結(jié)(三)
    • 七、鎖機(jī)制
      • 1.鎖的分類
        • 從對數(shù)據(jù)操作的類型分類:
        • 從對數(shù)據(jù)操作的粒度分類:
      • 2.MyISAM 表鎖
      • 3.InnoDB 行鎖
      • 4.加鎖機(jī)制
      • 5.鎖模式(InnoDB有三種行鎖的算法)
      • 6.select for update有什么含義,會鎖表還是鎖行還是其他
      • 7.死鎖
        • 死鎖產(chǎn)生:
        • 檢測死鎖:
        • 死鎖恢復(fù):
        • 外部鎖的死鎖檢測:
        • 死鎖影響性能:
        • MyISAM避免死鎖:
        • InnoDB避免死鎖:
        • 改變事務(wù)隔離級別
    • 八、性能優(yōu)化
      • 1.影響mysql的性能因素
      • 2.性能分析
        • MySQL Query Optimizer
        • MySQL常見瓶頸
        • 性能下降SQL慢 執(zhí)行時間長 等待時間長 原因分析
        • MySQL常見性能分析手段
      • 3.性能優(yōu)化
        • 索引優(yōu)化
        • 一般性建議
        • 查詢優(yōu)化
        • order by關(guān)鍵字優(yōu)化
        • GROUP BY關(guān)鍵字優(yōu)化
        • 數(shù)據(jù)類型優(yōu)化

七、鎖機(jī)制

鎖是計算機(jī)協(xié)調(diào)多個進(jìn)程或線程并發(fā)訪問某一資源的機(jī)制。

在數(shù)據(jù)庫中,除傳統(tǒng)的計算資源(如CPU、RAM、I/O等)的爭用以外,數(shù)據(jù)也是一種供許多用戶共享的資源。

數(shù)據(jù)庫鎖定機(jī)制簡單來說,就是數(shù)據(jù)庫為了保證數(shù)據(jù)的一致性,而使各種共享資源在被并發(fā)訪問變得有序所設(shè)計的一種規(guī)則。

  • 打個比方,我們到淘寶上買一件商品,商品只有一件庫存,這個時候如果還有另一個人買,那么如何解決是你買到還是另一個人買到的問題?
  • 這里肯定要用到事物,我們先從庫存表中取出物品數(shù)量,然后插入訂單,付款后插入付款表信息,然后更新商品數(shù)量。
  • 在這個過程中,使用鎖可以對有限的資源進(jìn)行保護(hù),解決隔離和并發(fā)的矛盾。

1.鎖的分類

從對數(shù)據(jù)操作的類型分類:

  • 讀鎖(共享鎖):針對同一份數(shù)據(jù),多個讀操作可以同時進(jìn)行,不會互相影響
  • 寫鎖(排他鎖):當(dāng)前寫操作沒有完成前,它會阻斷其他寫鎖和讀鎖

從對數(shù)據(jù)操作的粒度分類:

為了盡可能提高數(shù)據(jù)庫的并發(fā)度,每次鎖定的數(shù)據(jù)范圍越小越好,理論上每次只鎖定當(dāng)前操作的數(shù)據(jù)的方案會得到最大的并發(fā)度,但是管理鎖是很耗資源的事情(涉及獲取,檢查,釋放鎖等動作),因此數(shù)據(jù)庫系統(tǒng)需要在高并發(fā)響應(yīng)和系統(tǒng)性能兩方面進(jìn)行平衡,這樣就產(chǎn)生了“鎖粒度(Lock granularity)”的概念。

  • 表級鎖:開銷小,加鎖快;不會出現(xiàn)死鎖;鎖定粒度大,發(fā)生鎖沖突的概率最高,并發(fā)度最低(MyISAM 和 MEMORY 存儲引擎采用的是表級鎖);
  • 行級鎖:開銷大,加鎖慢;會出現(xiàn)死鎖;鎖定粒度最小,發(fā)生鎖沖突的概率最低,并發(fā)度也最高(InnoDB 存儲引擎既支持行級鎖也支持表級鎖,但默認(rèn)情況下是采用行級鎖);
  • 頁面鎖:開銷和加鎖時間界于表鎖和行鎖之間;會出現(xiàn)死鎖;鎖定粒度界于表鎖和行鎖之間,并發(fā)度一般。

適用:從鎖的角度來說,表級鎖更適合于以查詢?yōu)橹?#xff0c;只有少量按索引條件更新數(shù)據(jù)的應(yīng)用,如Web應(yīng)用;而行級鎖則更適合于有大量按索引條件并發(fā)更新少量不同數(shù)據(jù),同時又有并發(fā)查詢的應(yīng)用,如一些在線事務(wù)處理(OLTP)系統(tǒng)。

2.MyISAM 表鎖

  • MyISAM 的表鎖有兩種模式:
  • 表共享讀鎖 (Table Read Lock):不會阻塞其他用戶對同一表的讀請求,但會阻塞對同一表的寫請求;
  • 表獨占寫鎖 (Table Write Lock):會阻塞其他用戶對同一表的讀和寫操作;

MyISAM 表的讀操作與寫操作之間,以及寫操作之間是串行的。當(dāng)一個線程獲得對一個表的寫鎖后, 只有持有鎖的線程可以對表進(jìn)行更新操作。其他線程的讀、 寫操作都會等待,直到鎖被釋放為止。

默認(rèn)情況下,寫鎖比讀鎖具有更高的優(yōu)先級:當(dāng)一個鎖釋放時,這個鎖會優(yōu)先給寫鎖隊列中等候的獲取鎖請求,然后再給讀鎖隊列中等候的獲取鎖請求

3.InnoDB 行鎖

  • InnoDB 實現(xiàn)了以下兩種類型的行鎖:
  • 共享鎖(S):允許一個事務(wù)去讀一行,阻止其他事務(wù)獲得相同數(shù)據(jù)集的排他鎖。
  • 排他鎖(X):允許獲得排他鎖的事務(wù)更新數(shù)據(jù),阻止其他事務(wù)取得相同數(shù)據(jù)集的共享讀鎖和排他寫鎖。

為了允許行鎖和表鎖共存,實現(xiàn)多粒度鎖機(jī)制,InnoDB 還有兩種內(nèi)部使用的意向鎖(Intention Locks),這兩種意向鎖都是表鎖:

  • 意向共享鎖(IS):事務(wù)打算給數(shù)據(jù)行加行共享鎖,事務(wù)在給一個數(shù)據(jù)行加共享鎖前必須先取得該表的 IS 鎖。
  • 意向排他鎖(IX):事務(wù)打算給數(shù)據(jù)行加行排他鎖,事務(wù)在給一個數(shù)據(jù)行加排他鎖前必須先取得該表的 IX 鎖。

索引失效會導(dǎo)致行鎖變表鎖。比如 vchar 查詢不寫單引號的情況。

4.加鎖機(jī)制

樂觀鎖與悲觀鎖是兩種并發(fā)控制的思想,可用于解決丟失更新問題

樂觀鎖會“樂觀地”假定大概率不會發(fā)生并發(fā)更新沖突,訪問、處理數(shù)據(jù)過程中不加鎖,只在更新數(shù)據(jù)時再根據(jù)版本號或時間戳判斷是否有沖突,有則處理,無則提交事務(wù)。用數(shù)據(jù)版本(Version)記錄機(jī)制實現(xiàn),這是樂觀鎖最常用的一種實現(xiàn)方式

悲觀鎖會“悲觀地”假定大概率會發(fā)生并發(fā)更新沖突,訪問、處理數(shù)據(jù)前就加排他鎖,在整個數(shù)據(jù)處理過程中鎖定數(shù)據(jù),事務(wù)提交或回滾后才釋放鎖。另外與樂觀鎖相對應(yīng)的,悲觀鎖是由數(shù)據(jù)庫自己實現(xiàn)了的,要用的時候,我們直接調(diào)用數(shù)據(jù)庫的相關(guān)語句就可以了。

5.鎖模式(InnoDB有三種行鎖的算法)

  • 記錄鎖(Record Locks):單個行記錄上的鎖。對索引項加鎖,鎖定符合條件的行。其他事務(wù)不能修改和刪除加鎖項;
SELECT * FROM table WHERE id = 1 FOR UPDATE;

- 它會在 id=1 的記錄上加上記錄鎖,以阻止其他事務(wù)插入,更新,刪除 id=1 這一行在通過 主鍵索引 與 唯一索引 對數(shù)據(jù)行進(jìn)行 UPDATE 操作時,也會對該行數(shù)據(jù)加記錄鎖:

-- id 列為主鍵列或唯一索引列 UPDATE SET age = 50 WHERE id = 1;
  • 間隙鎖(Gap Locks):當(dāng)我們使用范圍條件而不是相等條件檢索數(shù)據(jù),并請求共享或排他鎖時,InnoDB會給符合條件的已有數(shù)據(jù)記錄的索引項加鎖。對于鍵值在條件范圍內(nèi)但并不存在的記錄,叫做“間隙”。
  • InnoDB 也會對這個“間隙”加鎖,這種鎖機(jī)制就是所謂的間隙鎖。
  • 對索引項之間的“間隙”加鎖,鎖定記錄的范圍(對第一條記錄前的間隙或最后一條將記錄后的間隙加鎖),不包含索引項本身。其他事務(wù)不能在鎖范圍內(nèi)插入數(shù)據(jù),這樣就防止了別的事務(wù)新增幻影行。
  • 間隙鎖基于非唯一索引,它鎖定一段范圍內(nèi)的索引記錄。間隙鎖基于下面將會提到的Next-Key Locking 算法,請務(wù)必牢記:使用間隙鎖鎖住的是一個區(qū)間,而不僅僅是這個區(qū)間中的每一條數(shù)據(jù)。
SELECT * FROM table WHERE id BETWEN 1 AND 10 FOR UPDATE;
  • 即所有在(1,10)區(qū)間內(nèi)的記錄行都會被鎖住,所有id 為 2、3、4、5、6、7、8、9 的數(shù)據(jù)行的插入會被阻塞,但是 1 和 10 兩條記錄行并不會被鎖住。
  • GAP鎖的目的,是為了防止同一事務(wù)的兩次當(dāng)前讀,出現(xiàn)幻讀的情況
  • 臨鍵鎖(Next-key Locks):臨鍵鎖,是記錄鎖與間隙鎖的組合,它的封鎖范圍,既包含索引記錄,又包含索引區(qū)間。(臨鍵鎖的主要目的,也是為了避免幻讀(Phantom Read)。如果把事務(wù)的隔離級別降級為RC,臨鍵鎖則也會失效。)
  • Next-Key 可以理解為一種特殊的間隙鎖,也可以理解為一種特殊的算法。通過臨建鎖可以解決幻讀的問題。
  • 個數(shù)據(jù)行上的非唯一索引列上都會存在一把臨鍵鎖,當(dāng)某個事務(wù)持有該數(shù)據(jù)行的臨鍵鎖時,會鎖住一段左開右閉區(qū)間的數(shù)據(jù)。
  • 需要強(qiáng)調(diào)的一點是,InnoDB 中行級鎖是基于索引實現(xiàn)的,臨鍵鎖只與非唯一索引列有關(guān),在唯一索引列(包括主鍵列)上不存在臨鍵鎖。

對于行的查詢,都是采用該方法,主要目的是解決幻讀的問題

6.select for update有什么含義,會鎖表還是鎖行還是其他

  • for update 僅適用于InnoDB,且必須在事務(wù)塊(BEGIN/COMMIT)中才能生效。

  • 在進(jìn)行事務(wù)操作時,通過“for update”語句,MySQL會對查詢結(jié)果集中每行數(shù)據(jù)都添加排他鎖,其他線程對該記錄的更新與刪除操作都會阻塞。排他鎖包含行鎖、表鎖。

  • InnoDB這種行鎖實現(xiàn)特點意味著:只有通過索引條件檢索數(shù)據(jù),InnoDB才使用行級鎖,否則,InnoDB將使用表鎖!假設(shè)有個表單 products ,里面有id跟name二個欄位,id是主鍵。

  • 明確指定主鍵,并且有此筆資料,row lock

SELECT * FROM products WHERE id='3' FOR UPDATE; SELECT * FROM products WHERE id='3' and type=1 FOR UPDATE;
  • 明確指定主鍵,若查無此筆資料,無lock
SELECT * FROM products WHERE id='-1' FOR UPDATE;
  • 無主鍵,table lock
SELECT * FROM products WHERE name='Mouse' FOR UPDATE;
  • 主鍵不明確,table lock
SELECT * FROM products WHERE id<>'3' FOR UPDATE;
  • 主鍵不明確,table lock
SELECT * FROM products WHERE id LIKE '3' FOR UPDATE;

注1: FOR UPDATE僅適用于InnoDB,且必須在交易區(qū)塊(BEGIN/COMMIT)中才能生效。

注2: 要測試鎖定的狀況,可以利用MySQL的Command Mode ,開二個視窗來做測試。

7.死鎖

死鎖產(chǎn)生:

  • 死鎖是指兩個或多個事務(wù)在同一資源上相互占用,并請求鎖定對方占用的資源,從而導(dǎo)致惡性循環(huán)
  • 當(dāng)事務(wù)試圖以不同的順序鎖定資源時,就可能產(chǎn)生死鎖。多個事務(wù)同時鎖定同一個資源時也可能會產(chǎn)生死鎖
  • 鎖的行為和順序和存儲引擎相關(guān)。以同樣的順序執(zhí)行語句,有些存儲引擎會產(chǎn)生死鎖有些不會——死鎖有雙重原因:真正的數(shù)據(jù)沖突;存儲引擎的實現(xiàn)方式。

檢測死鎖:

數(shù)據(jù)庫系統(tǒng)實現(xiàn)了各種死鎖檢測和死鎖超時的機(jī)制。InnoDB存儲引擎能檢測到死鎖的循環(huán)依賴并立即返回一個錯誤。

死鎖恢復(fù):

死鎖發(fā)生以后,只有部分或完全回滾其中一個事務(wù),才能打破死鎖,InnoDB目前處理死鎖的方法是,將持有最少行級排他鎖的事務(wù)進(jìn)行回滾。

所以事務(wù)型應(yīng)用程序在設(shè)計時必須考慮如何處理死鎖,多數(shù)情況下只需要重新執(zhí)行因死鎖回滾的事務(wù)即可。

外部鎖的死鎖檢測:

發(fā)生死鎖后,InnoDB 一般都能自動檢測到,并使一個事務(wù)釋放鎖并回退,另一個事務(wù)獲得鎖,繼續(xù)完成事務(wù)。

但在涉及外部鎖,或涉及表鎖的情況下,InnoDB 并不能完全自動檢測到死鎖, 這需要通過設(shè)置鎖等待超時參數(shù) innodb_lock_wait_timeout 來解決

死鎖影響性能:

死鎖會影響性能而不是會產(chǎn)生嚴(yán)重錯誤,因為InnoDB會自動檢測死鎖狀況并回滾其中一個受影響的事務(wù)。

在高并發(fā)系統(tǒng)上,當(dāng)許多線程等待同一個鎖時,死鎖檢測可能導(dǎo)致速度變慢。

有時當(dāng)發(fā)生死鎖時,禁用死鎖檢測(使用innodb_deadlock_detect配置選項)可能會更有效,這時可以依賴innodb_lock_wait_timeout設(shè)置進(jìn)行事務(wù)回滾。

MyISAM避免死鎖:

在自動加鎖的情況下,MyISAM 總是一次獲得 SQL 語句所需要的全部鎖,所以 MyISAM 表不會出現(xiàn)死鎖。

InnoDB避免死鎖:

為了在單個InnoDB表上執(zhí)行多個并發(fā)寫入操作時避免死鎖,可以在事務(wù)開始時通過為預(yù)期要修改的每個元祖(行)使用SELECT … FOR UPDATE語句來獲取必要的鎖,即使這些行的更改語句是在之后才執(zhí)行的。

在事務(wù)中,如果要更新記錄,應(yīng)該直接申請足夠級別的鎖,即排他鎖,而不應(yīng)先申請共享鎖、更新時再申請排他鎖,因為這時候當(dāng)用戶再申請排他鎖時,其他事務(wù)可能又已經(jīng)獲得了相同記錄的共享鎖,從而造成鎖沖突,甚至死鎖

如果事務(wù)需要修改或鎖定多個表,則應(yīng)在每個事務(wù)中以相同的順序使用加鎖語句。在應(yīng)用中,如果不同的程序會并發(fā)存取多個表,應(yīng)盡量約定以相同的順序來訪問表,這樣可以大大降低產(chǎn)生死鎖的機(jī)會

通過SELECT … LOCK IN SHARE MODE獲取行的讀鎖后,如果當(dāng)前事務(wù)再需要對該記錄進(jìn)行更新操作,則很有可能造成死鎖。

改變事務(wù)隔離級別

如果出現(xiàn)死鎖,可以用 show engine innodb status;命令來確定最后一個死鎖產(chǎn)生的原因。

返回結(jié)果中包括死鎖相關(guān)事務(wù)的詳細(xì)信息,如引發(fā)死鎖的 SQL 語句,事務(wù)已經(jīng)獲得的鎖,正在等待什么鎖,以及被回滾的事務(wù)等。據(jù)此可以分析死鎖產(chǎn)生的原因和改進(jìn)措施。

八、性能優(yōu)化

1.影響mysql的性能因素

  • 業(yè)務(wù)需求對MySQL的影響(合適合度)
  • 存儲定位對MySQL的影響
  • 系統(tǒng)各種配置及規(guī)則數(shù)據(jù)
  • 活躍用戶的基本信息數(shù)據(jù)
  • 活躍用戶的個性化定制信息數(shù)據(jù)
  • 準(zhǔn)實時的統(tǒng)計信息數(shù)據(jù)
  • 其他一些訪問頻繁但變更較少的數(shù)據(jù)
  • 二進(jìn)制多媒體數(shù)據(jù)
  • 流水隊列數(shù)據(jù)
  • 超大文本數(shù)據(jù)
  • 不適合放進(jìn)MySQL的數(shù)據(jù)
  • 需要放進(jìn)緩存的數(shù)據(jù)
  • Schema設(shè)計對系統(tǒng)的性能影響
  • 盡量減少對數(shù)據(jù)庫訪問的請求
  • 盡量減少無用數(shù)據(jù)的查詢請求
  • 硬件環(huán)境對系統(tǒng)性能的影響

2.性能分析

MySQL Query Optimizer

  • MySQL 中有專門負(fù)責(zé)優(yōu)化 SELECT 語句的優(yōu)化器模塊,主要功能:通過計算分析系統(tǒng)中收集到的統(tǒng)計信息,為客戶端請求的 Query 提供他認(rèn)為最優(yōu)的執(zhí)行計劃(他認(rèn)為最優(yōu)的數(shù)據(jù)檢索方式,但不見得是 DBA 認(rèn)為是最優(yōu)的,這部分最耗費時間)
  • 當(dāng)客戶端向 MySQL 請求一條 Query,命令解析器模塊完成請求分類,區(qū)別出是 SELECT 并轉(zhuǎn)發(fā)給 MySQL Query Optimize r時,MySQL Query Optimizer 首先會對整條 Query 進(jìn)行優(yōu)化,處理掉一些常量表達(dá)式的預(yù)算,直接換算成常量值。
  • 并對 Query 中的查詢條件進(jìn)行簡化和轉(zhuǎn)換,如去掉一些無用或顯而易見的條件、結(jié)構(gòu)調(diào)整等。
  • 然后分析 Query 中的 Hint 信息(如果有),看顯示 Hint 信息是否可以完全確定該 Query 的執(zhí)行計劃。
  • 如果沒有 Hint 或 Hint 信息還不足以完全確定執(zhí)行計劃,則會讀取所涉及對象的統(tǒng)計信息,根據(jù) Query 進(jìn)行寫相應(yīng)的計算分析,然后再得出最后的執(zhí)行計劃。

MySQL常見瓶頸

  • CPU:CPU在飽和的時候一般發(fā)生在數(shù)據(jù)裝入內(nèi)存或從磁盤上讀取數(shù)據(jù)時候
  • IO:磁盤I/O瓶頸發(fā)生在裝入數(shù)據(jù)遠(yuǎn)大于內(nèi)存容量的時候
  • 服務(wù)器硬件的性能瓶頸:top,free,iostat 和 vmstat來查看系統(tǒng)的性能狀態(tài)

性能下降SQL慢 執(zhí)行時間長 等待時間長 原因分析

  • 查詢語句寫的爛
  • 索引失效(單值、復(fù)合)
  • 關(guān)聯(lián)查詢太多join(設(shè)計缺陷或不得已的需求)
  • 服務(wù)器調(diào)優(yōu)及各個參數(shù)設(shè)置(緩沖、線程數(shù)等)

MySQL常見性能分析手段

在優(yōu)化MySQL時,通常需要對數(shù)據(jù)庫進(jìn)行分析,常見的分析手段有慢查詢?nèi)罩?#xff0c;EXPLAIN 分析查詢,profiling分析以及show命令查詢系統(tǒng)狀態(tài)及系統(tǒng)變量,通過定位分析性能的瓶頸,才能更好的優(yōu)化數(shù)據(jù)庫系統(tǒng)的性能。

  • 性能瓶頸定位

我們可以通過 show 命令查看 MySQL 狀態(tài)及變量,找到系統(tǒng)的瓶頸:

Mysql> show status ——顯示狀態(tài)信息(擴(kuò)展show status like ‘XXX’)Mysql> show variables ——顯示系統(tǒng)變量(擴(kuò)展show variables like ‘XXX’)Mysql> show innodb status ——顯示InnoDB存儲引擎的狀態(tài)Mysql> show processlist ——查看當(dāng)前SQL執(zhí)行,包括執(zhí)行狀態(tài)、是否鎖表等Shell> mysqladmin variables -u username -p password——顯示系統(tǒng)變量Shell> mysqladmin extended-status -u username -p password——顯示狀態(tài)信息
  • Explain(執(zhí)行計劃)

  • 慢查詢?nèi)罩?/p>

MySQL 的慢查詢?nèi)罩臼?MySQL 提供的一種日志記錄,它用來記錄在 MySQL 中響應(yīng)時間超過閾值的語句,具體指運行時間超過 long_query_time 值的 SQL,則會被記錄到慢查詢?nèi)罩局小?/strong>

  • long_query_time 的默認(rèn)值為10,意思是運行10秒以上的語句
  • 默認(rèn)情況下,MySQL數(shù)據(jù)庫沒有開啟慢查詢?nèi)罩?#xff0c;需要手動設(shè)置參數(shù)開啟
  • 查看開啟狀態(tài)
SHOW VARIABLES LIKE '%slow_query_log%'
  • 開啟慢查詢?nèi)罩?/p>

  • 臨時配置:

mysql> set global slow_query_log='ON'; mysql> set global slow_query_log_file='/var/lib/mysql/hostname-slow.log'; mysql> set global long_query_time=2;

也可set文件位置,系統(tǒng)會默認(rèn)給一個缺省文件host_name-slow.log
使用set操作開啟慢查詢?nèi)罩局粚Ξ?dāng)前數(shù)據(jù)庫生效,如果MySQL重啟則會失效。

  • 永久配置

修改配置文件my.cnf或my.ini,在[mysqld]一行下面加入兩個配置參數(shù)

[mysqld] slow_query_log = ON slow_query_log_file = /var/lib/mysql/hostname-slow.log long_query_time = 3

3.性能優(yōu)化

索引優(yōu)化

  • 全值匹配我最愛
  • 最佳左前綴法則,比如建立了一個聯(lián)合索引(a,b,c),那么其實我們可利用的索引就有(a), (a,b), (a,b,c)
  • 不在索引列上做任何操作(計算、函數(shù)、(自動or手動)類型轉(zhuǎn)換),會導(dǎo)致索引失效而轉(zhuǎn)向全表掃描
  • 存儲引擎不能使用索引中范圍條件右邊的列
  • 盡量使用覆蓋索引(只訪問索引的查詢(索引列和查詢列一致)),減少select
  • is null ,is not null 也無法使用索引
  • like “xxxx%” 是可以用到索引的,like “%xxxx” 則不行(like “%xxx%” 同理)。like以通配符開頭(’%abc…’)索引失效會變成全表掃描的操作,
  • 字符串不加單引號索引失效
  • 少用or,用它來連接時會索引失效
  • <,<=,=,>,>=,BETWEEN,IN 可用到索引,<>,not in ,!= 則不行,會導(dǎo)致全表掃描

一般性建議

  • 對于單鍵索引,盡量選擇針對當(dāng)前query過濾性更好的索引
  • 在選擇組合索引的時候,當(dāng)前Query中過濾性最好的字段在索引字段順序中,位置越靠前越好。
  • 在選擇組合索引的時候,盡量選擇可以能夠包含當(dāng)前query中的where字句中更多字段的索引
  • 盡可能通過分析統(tǒng)計信息和調(diào)整query的寫法來達(dá)到選擇合適索引的目的
  • 少用Hint強(qiáng)制索引

查詢優(yōu)化

  • 永遠(yuǎn)小標(biāo)驅(qū)動大表(小的數(shù)據(jù)集驅(qū)動大的數(shù)據(jù)集)
slect * from A where id in (select id from B)`等價于 #等價于 select id from B select * from A where A.id=B.id

當(dāng) B 表的數(shù)據(jù)集必須小于 A 表的數(shù)據(jù)集時,用 in 優(yōu)于 exists

select * from A where exists (select 1 from B where B.id=A.id) #等價于 select * from A select * from B where B.id = A.id`

order by關(guān)鍵字優(yōu)化

  • order by子句,盡量使用 Index 方式排序,避免使用 FileSort 方式排序
  • MySQL 支持兩種方式的排序,FileSort 和 Index,Index效率高,它指 MySQL 掃描索引本身完成排序,FileSort 效率較低;
  • ORDER BY 滿足兩種情況,會使用Index方式排序;①ORDER BY語句使用索引最左前列 ②使用where子句與ORDER BY子句條件列組合滿足索引最左前列
  • 盡可能在索引列上完成排序操作,遵照索引建的最佳最前綴
  • 如果不在索引列上,filesort 有兩種算法,mysql就要啟動雙路排序和單路排序
    • 雙路排序:MySQL 4.1之前是使用雙路排序,字面意思就是兩次掃描磁盤,最終得到數(shù)據(jù)
    • 單路排序:從磁盤讀取查詢需要的所有列,按照order by 列在 buffer對它們進(jìn)行排序,然后掃描排序后的列表進(jìn)行輸出,效率高于雙路排序
  • 優(yōu)化策略
    • 增大sort_buffer_size參數(shù)的設(shè)置
    • 增大max_lencth_for_sort_data參數(shù)的設(shè)置

GROUP BY關(guān)鍵字優(yōu)化

  • group by實質(zhì)是先排序后進(jìn)行分組,遵照索引建的最佳左前綴
  • 當(dāng)無法使用索引列,增大 max_length_for_sort_data 參數(shù)的設(shè)置,增大sort_buffer_size參數(shù)的設(shè)置
  • where高于having,能寫在where限定的條件就不要去having限定了

數(shù)據(jù)類型優(yōu)化

MySQL 支持的數(shù)據(jù)類型非常多,選擇正確的數(shù)據(jù)類型對于獲取高性能至關(guān)重要。不管存儲哪種類型的數(shù)據(jù),下面幾個簡單的原則都有助于做出更好的選擇。

  • 更小的通常更好:一般情況下,應(yīng)該盡量使用可以正確存儲數(shù)據(jù)的最小數(shù)據(jù)類型。簡單就好:簡單的數(shù)據(jù)類型通常需要更少的CPU周期。例如,整數(shù)比字符操作代價更低,因為字符集和校對規(guī)則(排序規(guī)則)使字符比較比整型比較復(fù)雜。
  • 盡量避免NULL:通常情況下最好指定列為NOT NULL

總結(jié)

以上是生活随笔為你收集整理的MySQL基础总结(三)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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