性能優化之mysql索引優化

 

sql及索引優化mysql

如何經過慢查詢日誌發現有問題的sql?sql

  1. 查詢次數多且每次查詢佔用時間長的sql
    一般爲pt-query-digest分析的前幾個查詢數據庫

  2. IO大的sql
    注意pt-query-digest分析中的rows examine項緩存

  3. 未命中索引的sql
    注意pt-query-digest分析中rows examine 和 rows send的對比數據結構

 

 

 

磁盤IO與預讀:磁盤讀取數據靠的是機械運動,每次讀取數據花費的時間能夠分爲尋道時間,旋轉時間,傳輸時間三個部分。雖然日常理論上來講沒什麼壓力,函數

可是數據庫若是動輒十萬百萬乃至千萬級數據,顯然是個災難。性能

 

瞭解下mysql的B+樹:一種爲了減小IO操做快速搜索到數據的數據結構,以下圖:優化

 


    說明:spa

        藍色部分磁盤塊指針

        黃色部分指針

        深藍色目標數據塊
    分析一下查找的過程:

    若是要查詢數據爲29的值:

    1.將磁盤一加入到內存中此時發生一次IO,在內存中用二分查找肯定29在17和35之間,鎖定磁盤塊1的P2指針

    2.經過磁盤塊1的P2指針的磁盤地址把磁盤塊3由磁盤加載到內存,發生第二次IO

    3. 29在26和30之間,鎖定磁盤塊3的P2指針,經過指針加載磁盤塊8到內存,發生第三次IO,同時內存中作二分查找找到29,結束查詢

    總結:總計三次IO,真實的狀況是,3層的b+樹能夠表示上百萬的數據,若是上百萬的數據查找只須要三次IO,性能提升將是巨大的,若是沒有索引,

每一個數據項都要發生一次IO,那麼總共須要百萬次的IO,顯然成本很是很是高。


解釋下什麼叫二分法:其實就是一種經過不斷排除不可能的東西,來最終找到須要的東西的一種方法,因此能夠理解成排除法。之因此叫二分,是由於

每次排除都把全部的狀況分爲「可能」和不可能兩種,而後拋棄全部「不可能」的狀況。

  

優化sql實際上主要目的是爲了減小IO操做:
1.若是想在mysql配置方面減小IO的操做:儘量使用緩存,減小讀寫對數據庫的隨機IO的請求,同時減小寫的隨機IO的隨時發生,利用各類buffer去緩存。

2.建立索引:合理的索引是爲了少許IO操做達到數據的獲取。

  

創建索引的幾大原則:
1.在where 從句,group by從句,on從句中出現的列

2.最左前綴匹配,很是重要的原則,mysql會一直向左匹配直到遇到範圍查詢(>,<,between,like)就中止匹配
eg:a=1 and b=2 and c=3 and d=4   索引  add index (a,b,c,d)  這樣建立d是用不到索引的
eg:a=1 and b=2 and c=3 and d=4   索引  add index(a,b,d,c) 這樣建立則均可以用到,a,b,d的順序能夠任意調整

3.離散度大的列放到聯合索引的前面 

    計算離散度的公式是count(distinct col)/count(*),表示字段不重複的比例,比例越大咱們掃描的記錄數越少。

    select * from payment where staff_id=2 and customer_id=584;

    是index(sftaff_id,customer_id)好?仍是index(customer_id,staff_id)?
    因爲customer_id的離散度更大,因此應該使用index(customer_id,staff_id)

4.索引列不能參與計算,保持列乾淨
    索引列不能參與計算,保持列乾淨,在where語句中索引字段不要使用函數,進行檢索的時候須要把全部元素都應用函數才能比較,先人成本太大。

5.索引字段越小越好
    使用短索引,若是對字符串列進行索引,應該指定一個前綴長度,可節省大量索引空間,提高查詢速度。

6.儘可能的擴展索引,不要新建索引。
    

說了這麼多索引的優勢可是索引也是有負面的:

  1. 每一個額外的索引都要佔用額外的磁盤空間,並下降寫操做的性能

   2.在修改表的內容時,索引必須進行更新,有時可能須要重構,所以,所花的時間越長。

什麼叫作好的索引:

  1. 查詢頻繁(業務邏輯決定)

  2. 區分度高

  3. 長度小(與區分度保持一個平衡就是一個最優的效果)

  4. 儘可能能覆蓋經常使用查詢字段(並不表示全部字段都創建索引)

  5.  

 

sql及索引優化

如何經過慢查詢日誌發現有問題的sql?

  1. 查詢次數多且每次查詢佔用時間長的sql
    一般爲pt-query-digest分析的前幾個查詢

  2. IO大的sql
    注意pt-query-digest分析中的rows examine項

  3. 未命中索引的sql
    注意pt-query-digest分析中rows examine 和 rows send的對比

 

 

 

磁盤IO與預讀:磁盤讀取數據靠的是機械運動,每次讀取數據花費的時間能夠分爲尋道時間,旋轉時間,傳輸時間三個部分。雖然日常理論上來講沒什麼壓力,

可是數據庫若是動輒十萬百萬乃至千萬級數據,顯然是個災難。

 

瞭解下mysql的B+樹:一種爲了減小IO操做快速搜索到數據的數據結構,以下圖:


    說明:

        藍色部分磁盤塊

        黃色部分指針

        深藍色目標數據塊
    分析一下查找的過程:

    若是要查詢數據爲29的值:

    1.將磁盤一加入到內存中此時發生一次IO,在內存中用二分查找肯定29在17和35之間,鎖定磁盤塊1的P2指針

    2.經過磁盤塊1的P2指針的磁盤地址把磁盤塊3由磁盤加載到內存,發生第二次IO

    3. 29在26和30之間,鎖定磁盤塊3的P2指針,經過指針加載磁盤塊8到內存,發生第三次IO,同時內存中作二分查找找到29,結束查詢

    總結:總計三次IO,真實的狀況是,3層的b+樹能夠表示上百萬的數據,若是上百萬的數據查找只須要三次IO,性能提升將是巨大的,若是沒有索引,

每一個數據項都要發生一次IO,那麼總共須要百萬次的IO,顯然成本很是很是高。


解釋下什麼叫二分法:其實就是一種經過不斷排除不可能的東西,來最終找到須要的東西的一種方法,因此能夠理解成排除法。之因此叫二分,是由於

每次排除都把全部的狀況分爲「可能」和不可能兩種,而後拋棄全部「不可能」的狀況。

  

優化sql實際上主要目的是爲了減小IO操做:
1.若是想在mysql配置方面減小IO的操做:儘量使用緩存,減小讀寫對數據庫的隨機IO的請求,同時減小寫的隨機IO的隨時發生,利用各類buffer去緩存。

2.建立索引:合理的索引是爲了少許IO操做達到數據的獲取。

  

創建索引的幾大原則:
1.在where 從句,group by從句,on從句中出現的列

2.最左前綴匹配,很是重要的原則,mysql會一直向左匹配直到遇到範圍查詢(>,<,between,like)就中止匹配
eg:a=1 and b=2 and c=3 and d=4   索引  add index (a,b,c,d)  這樣建立d是用不到索引的
eg:a=1 and b=2 and c=3 and d=4   索引  add index(a,b,d,c) 這樣建立則均可以用到,a,b,d的順序能夠任意調整

3.離散度大的列放到聯合索引的前面 

    計算離散度的公式是count(distinct col)/count(*),表示字段不重複的比例,比例越大咱們掃描的記錄數越少。

    select * from payment where staff_id=2 and customer_id=584;

    是index(sftaff_id,customer_id)好?仍是index(customer_id,staff_id)?
    因爲customer_id的離散度更大,因此應該使用index(customer_id,staff_id)

4.索引列不能參與計算,保持列乾淨
    索引列不能參與計算,保持列乾淨,在where語句中索引字段不要使用函數,進行檢索的時候須要把全部元素都應用函數才能比較,先人成本太大。

5.索引字段越小越好
    使用短索引,若是對字符串列進行索引,應該指定一個前綴長度,可節省大量索引空間,提高查詢速度。

6.儘可能的擴展索引,不要新建索引。
    

說了這麼多索引的優勢可是索引也是有負面的:

  1. 每一個額外的索引都要佔用額外的磁盤空間,並下降寫操做的性能

   2.在修改表的內容時,索引必須進行更新,有時可能須要重構,所以,所花的時間越長。

什麼叫作好的索引:

  1. 查詢頻繁(業務邏輯決定)

  2. 區分度高

  3. 長度小(與區分度保持一個平衡就是一個最優的效果)

  4. 儘可能能覆蓋經常使用查詢字段(並不表示全部字段都創建索引)

相關文章
相關標籤/搜索