mysql 整體優化

mysql優化,近期突擊了一下mysql數據庫優化,做自己的一個淺談和收集。有不足之處希望大家指正。


mysql數據庫該怎麼優化?

    我們會經常回答添加索引,查詢慢sql。添加緩存。這樣的回答,這樣的回答並不是錯誤的,太籠統不夠具體,沒有細節

下面我做了一個mysql的一個優化流程,要想去做數據庫的優化。需要宏觀的去觀察我們的程序數據庫的峯值瓶頸到底在那裏。

大概優化流程圖:http://on-img.com/chart_image/5a66ab56e4b0332f15428b7e.png


利用腳本去監控mysql的數據庫狀態,分析週期性卡頓、瓶頸。還是不規則性卡頓瓶頸

mysql 監控腳本 https://blog.csdn.net/qq_35809876/article/details/79782130

週期性:

    1、監控時間點,排查緩存失效時間,定時任務。

非週期性:

    1、開啓慢sql查詢(服務器端,也可以利用阿里druid),找出慢sql,並對語句進行explain 分析,索引是否命中。編寫是否合理

    2、查看錶關聯是否設計合理。

    3、合理使用緩存減輕數據庫壓力,把不常變動且不重要的 sql 加入緩存中。注意:緩存穿透問題

以上優化的優化思路

=========================================================================================

下面是主要的數據庫的規則。

索引生效原則

    B-tree索引 可以理解爲排好序的索引(詳情算法實現,請查詢其他貼子,這方面資料很多)

    MySQL官方對索引的定義爲:索引(Index)是幫助MySQL高效獲取數據的數據結構。我們可以簡單理解爲:快速查找排好序的一種數據結構。Mysql索引主要有兩種結構:B+Tree索引和Hash索引。我們平常所說的索引,如果沒有特別指明,一般都是指B樹結構組織的索引(B+Tree索引)。索引如圖所示  :


    最外層淺藍色磁盤塊1裏有數據17、35(深藍色)和指針P1、P2、P3(黃色)。P1指針表示小於17的磁盤塊,P2是在17-35之間,P3指向大於35的磁盤塊。真實數據存在於子葉節點也就是最底下的一層3、5、9、10、13......非葉子節點不存儲真實的數據,只存儲指引搜索方向的數據項,如17、35。

查找過程:例如搜索28數據項,首先加載磁盤塊1到內存中,發生一次I/O,用二分查找確定在P2指針。接着發現28在26和30之間,通過P2指針的地址加載磁盤塊3到內存,發生第二次I/O。用同樣的方式找到磁盤塊8,發生第三次I/O。

真實的情況是,上面3層的B+Tree可以表示上百萬的數據,上百萬的數據只發生了三次I/O而不是上百萬次I/O,時間提升是巨大的。


誤區:

    已index(a、b、c)爲例

where語句索引是否生效
where a = 3Y
where a=3 and b=2Y
where a=3 and b=2 and c=3Y
where a=3 and b>2 and c=3N(a\b 能利用索引C不能利用)
where b=2 and c=3N
where a=1 and b like '%xxxx%' and c=3N(a\b能利用索引,c不能)
where a =1 and c=23N(a能利用索引)




    總結:聯合索引 1、必須按照索引順序使用 2、範圍查詢,後面索引無法在生效    

hash索引   可以直接在表中快速找到單個結果

        特性:

               1、hash索引計算出的結果是隨機的,會在磁盤上隨機放置數據

                   2、無法進行範圍查詢

                   3、無法利用前綴索引

                   4、無法優化排序

                   5、必須回行(回到表中拿出對應行的數據),意思就是說通過索引拿到數據位置,必須回到表中去取數據 

重複索引:

    一個字段多個索引,數據庫允許這樣操作,但是這樣的索引無效。只會影響表的更新速度

冗餘索引:

    是被允許的,這種情況很常見

    例:1、index(x.y) index(y.x) 

          2、index(x) index(x,y)

索引碎片

    索引碎片的概念,經常改動數據內容,索引文件和數據文件會產生空洞。從而形成碎片,這樣會讓表的索引效率 和查詢效率降低

    解決方案:optimize table 表名     注意:修復表數據和索引碎片重新整理,如果表內容很大,這是一個非常耗資源的過程,請在夜間業務訪問量最低的時候進行或者停服務時進行。如果修改操作比較頻繁,安週期進行整理操作

索引總結:儘量讓查詢sql命中索引,也儘量讓我們查詢字段被索引覆蓋 避免或減少數據庫回行操作

in 子查詢陷阱

    create table student id、age   ;index(age)

    create table person id、name ;index( id)

    p.id = s.id

    select p.name form persion where id in (select id from student where age >13);

    我們正常理解先查詢出學生表年齡大於13的ID 在和person表中的 id 比較查詢出名字

    其實不然,可以用explain sql \G 去分析一下 sql 發現persion 表進行了一次全表掃描查詢,student表命中索引

    這個sql 執行過程應該是 person進行全表掃描去挨個匹配in 中的內容。    

    針對上述sql 優化用left join 表關聯查詢 

    select p.name form student s left  join  person p on s.id = p.id where s.age>13;

explain 分析 sql 語句

exists 和 group by 比較

   exists    要比表關聯 在group by 速度快一些,表關聯 在group by 需要創建一個臨時表在去分組。

而exists 並不需要創建臨時表


count 優化查詢小技巧

 select count(*) form table ;非常快因爲表的總數已經被數據庫緩存起來

 select count(*) from student  where age>9;相對會慢一些

 select count(*) from student where age <= 9; 先查詢出較少的數量

 select (select count(*) form table ) - (select count(*) from student where age <= 9) as count;


group by 儘量使用在統計 最大數 平均數上。不要使用group by 做數據篩選。

排序

    儘量按照某個索引規則執行,排序分爲倆種情況

        1、查出來的數據本身就是順序性的。直接在索引上查詢出來的結果就是一個有序的

        2、先查出來數據,在根據排序規則重新排序。

       知道這倆種情況,我們就知道該如何去做排序優化,爭取讓每次排序都是在索引上查詢出來的結果少一次在排序過程


大數據量分頁優化


select * from pro_order limit 100 ,10;

(等後續添加)


表設計字段類型數據庫查找最快排序 整型dataTimevarchar


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章