sql及索引優化mysql
如何經過慢查詢日誌發現有問題的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操做快速搜索到數據的數據結構,以下圖:優化
說明: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.儘可能的擴展索引,不要新建索引。
說了這麼多索引的優勢可是索引也是有負面的:
每一個額外的索引都要佔用額外的磁盤空間,並下降寫操做的性能
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會一直向左匹配直到遇到範圍查詢(>,<,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.儘可能的擴展索引,不要新建索引。
說了這麼多索引的優勢可是索引也是有負面的:
每一個額外的索引都要佔用額外的磁盤空間,並下降寫操做的性能
2.在修改表的內容時,索引必須進行更新,有時可能須要重構,所以,所花的時間越長。
什麼叫作好的索引:
查詢頻繁(業務邏輯決定)
區分度高
長度小(與區分度保持一個平衡就是一個最優的效果)
儘可能能覆蓋經常使用查詢字段(並不表示全部字段都創建索引)