sql及索引優化
如何通過慢查詢日誌發現有問題的sql?
查詢次數多且每次查詢占用時間長的sql
通常為pt-query-digest分析的前幾個查詢
io大的sql
注意pt-query-digest分析中的rows examine項
未命中索引的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會一直向左匹配直到遇到範圍查詢(>,
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.盡量的擴充套件索引,不要新建索引。
說了這麼多索引的優點但是索引也是有負面的:
每個額外的索引都要占用額外的磁碟空間,並降低寫操作的效能
2.在修改表的內容時,索引必須進行更新,有時可能需要重構,因此,所花的時間越長。
什麼叫做好的索引:
查詢頻繁(業務邏輯決定)
區分度高
長度小(與區分度保持乙個平衡就是乙個最優的效果)
盡量能覆蓋常用查詢字段(並不表示所有欄位都建立索引)
sql及索引優化
如何通過慢查詢日誌發現有問題的sql?
查詢次數多且每次查詢占用時間長的sql
通常為pt-query-digest分析的前幾個查詢
io大的sql
注意pt-query-digest分析中的rows examine項
未命中索引的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會一直向左匹配直到遇到範圍查詢(>,
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.盡量的擴充套件索引,不要新建索引。
說了這麼多索引的優點但是索引也是有負面的:
每個額外的索引都要占用額外的磁碟空間,並降低寫操作的效能
2.在修改表的內容時,索引必須進行更新,有時可能需要重構,因此,所花的時間越長。
什麼叫做好的索引:
查詢頻繁(業務邏輯決定)
區分度高
長度小(與區分度保持乙個平衡就是乙個最優的效果)
盡量能覆蓋常用查詢字段(並不表示所有欄位都建立索引)
MySQL索引效能優化
紅黑樹 hash表,是現在可以選擇的索引資料結構 b tree b tree b tree變種 可以保證樹的高度,就算記錄數多的時候查詢的次數也比較少,效率高,所有是現在預設使用的索引資料結構 在聯合索引的情況下,都在遵循最左字首法制 這個也是因為節點的資料索引是由第乙個索引先通過索引最左字首原理 ...
MySQL 資料庫效能優化之索引優化
資料庫效能優化專題 系列的第三篇文章 mysql 資料庫效能優化之索引優化 大家都知道索引對於資料訪問的效能有非常關鍵的作用,都知道索引可以提高資料訪問效率。為什麼索引能提高資料訪問效能?他會不會有 是不是索引建立越多,效能就越好?到底該如何設計索引,才能最大限度的發揮其效能?這篇文章主要是帶著上面...
MySQL 資料庫效能優化之索引優化
大家都知道索引對於資料訪問的效能有非常關鍵的作用,都知道索引可以提高資料訪問效率。為什麼索引能提高資料訪問效能?他會不會有 是不是索引建立越多,效能就越好?到底該如何設計索引,才能最大限度的發揮其效能?這篇文章主要是帶著上面這幾個問題來做乙個簡要的分析,同時排除了業務場景所帶來的特殊性,請不要糾結業...