中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Mysql優化問題有哪些

發布時間:2022-06-14 09:34:26 來源:億速云 閱讀:164 作者:zzz 欄目:MySQL數據庫

這篇文章主要介紹了Mysql優化問題有哪些的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇Mysql優化問題有哪些文章都會有所收獲,下面我們一起來看看吧。

Mysql優化問題有哪些

開發過程如何排查SQL?

排查思路

對于大部分程序員來說,在開發過程中排查SQL基本是空白。但隨著行業的內卷,對一開發過程越來越重視和專業,其中一項就是開發過程中盡可能解決掉SQL問題,避免生產才暴露SQL問題。那么在開發過程中如何方便的進行程序的SQL排查呢?

其思路還是使用Mysql的慢日志來實現:

  • 首先在開發過程中也需要開啟數據庫Mysql的慢查詢

    SET GLOBAL slow_query_log='on';
  • 其次設置慢SQL的最小時間

    注意:這里時間單位是s秒但是有6位小數因此可以表示到微妙的時間力度,一般單表SQL執行時間在20ms之內為宜,反之理解就是在開發過程中,如果你執行的sql語句超過了20ms則你需要去關注它。

    SET GLOBAL long_query_time=0.02;
  • 為方便操作可以把慢SQL記錄到表中而不是文件中

    SET GLOBAL log_output='TABLE';
  • 最后通過mysql.slow_log表就可以查詢到記錄的慢SQL

Mysql優化問題有哪些

使用工具

在勇哥給大家開發的軟件中,也提供了圖形化的界面來一鍵幫助大家快速實現上述功能。

Mysql優化問題有哪些

生產環境SQL問題如何排查?

排查思路

生成SQL問題的排查就相對復雜一點點,但是整體的思路還是通過慢SQL來排查,具體思路如下:

  • 首先開啟數據庫Mysql的慢查詢

    SET GLOBAL slow_query_log='on';
  • 其次設置慢SQL的最小時間

    SET GLOBAL long_query_time=0.02;
  • 一般生成時把慢SQL放到文件

    SET GLOBAL log_output='FILE';
  • 下載慢SQL日志文件到本地

  • 最后關閉數據庫Mysql的慢查詢

    著重注意:生產的慢SQL最好在使用時,才去開啟,用完后關閉,避免日志記錄影響到業務性能

    SET GLOBAL slow_query_log='off';

SQL怎么調優?

SQL調優融合多方面的知識,總體來說常見從表結構、表索引、兩方面來優化。

表結構優化

1、合理的使用字段類及長度

舉個例子來理解:就一個性別字段,用tinyint(1)存儲占用1字節,用int(1)存儲占用4個字節,如果有100W條記錄,那么用int存儲的表就比tinyint存儲的表文件大小多2.8M左右,因此在讀取int類型存儲的表時文件大,讀速度相比讀tinyint的慢。這其實就是為什么說要合理使用字段類型長度的本質:就是減少存儲的文件大小,以提供讀性能

當然有的朋友就可能說2.8M并不影響大局,因此可以忽略。對于此想法勇哥要補充一嘴:一個表假設有10個字段,你的系統一共有30個表,那么再看一下多出的文件大小是多少?(2.8Mx10x30=840M,840M你用迅雷超級下載也要花好幾秒,這個時間在計算機里面算是很慢了...)

2、合理的使用冗余設計

2.1、冗余設計背景——臨時表

Mysql內部存在一種特殊且輕量級的臨時表,它是被Mysql自動創建和刪除的。主要在SQL的執行過程中使用臨時表來存儲某些操作的中間結果,該過程由 MySQL 自動完成,用戶無法手工干預,且這種內部表對用戶來說是不可見的。

內部臨時表在 SQL 語句的優化過程中非常重要,MySQL 中的很多操作都要依賴于內部臨時表來進行優化操作。但是使用內部臨時表需要創建表以及中間數據的存取代價,所以在寫 SQL 語句的時候應該盡量去避免使用臨時表

那么場景的那些場景Mysql內部會使用臨時表呢?

  • 多表關聯查詢(JOIN)中,order by 或group by使用的列不是第一個表的列

  • group by 的列不是索引列時

  • distinct和group by 聯合使用

  • order by 語句中使用了distinct關鍵字

  • group by 的列時索引列,但數據量過大時

2.2、如何查看是否使用內部臨時表?

通過Explain關鍵字或者工具的功能按鈕,查看SQL的執行過程,在結果中的Extra列中如果出現Using temporary關鍵字,則說明你的SQL語句在執行時使用了臨時表。

如下圖,角色Role表和角色組Role_Group是多對1的關系,在關聯查詢的時候,排序使用role_group的id排序則會使用臨時表(見下圖1),如果排序使用role的id則不會使用臨時表(見圖2)。

Mysql優化問題有哪些

Mysql優化問題有哪些

2.3、如何解決不使用內部臨時表?

這個問題解決有兩個方案,一是調整SQL語句避免使用臨時表,另外一個方案就是在表中冗余存儲。比如2.2中的圖一例子如果一定要按照role_group的id排序,則可以按照role表中的group_id排序,而這列正是冗余存儲的role_group表中id列值。

Mysql優化問題有哪些

3、合理的使用分庫分表

分庫分表不僅用于大數量情況下的優化,其中垂直分表還可以使用到SQL調優下。(這里我就不去解釋垂直和水平分表了,感興趣的私信我)

例如:一個文章表一般設計不會包括文章內容這個大字段。

Mysql優化問題有哪些

文章內容這個大字段是單獨放置到一張表中

Mysql優化問題有哪些

為什么文章表要采用以上設計而不把字段合并到一表中呢?

我們先來計算一道數學題,假設一篇文章總共1M大小,其中文章內容,824KB,其余字段200KB,這樣的文章一共有100W條,則:

  • 方案一,如果用一個表存儲,則這個表大小是100W*1M=100WM

  • 方案二,如果用垂直分表存儲,則基本表時200KBx100W,內容表824KBx100W

我們在前端有文章列表和文章詳情兩個頁面,分別要直接從數據庫中查詢相關內容,則:

  • 方案一,文章列表和文章詳情的查詢都會從100WM數據中查詢

  • 方案二,文章列表會從200KBx100W中查詢,文章詳情會從824KBx100W中查詢(當前也可能還需要從200KBx100W中查詢)

說到這里,相信大家心中應該有一個清晰的答案了吧!垂直拆表可以讓不同業務場景的查詢的數據量不同,常常這個數據量往往小于總表數據量,這就比從固定很大小的量中查詢更靈活和高效率。

表索引優化

1、合理的添加索引列

大多數人對應索引的理解層次都在“索引可以加快查詢的速度”,然而這句話勇哥要補充下半句“索引可以加快查詢的速度,也可以減慢數據插入或修改的速度”

如果一個表有5個索引,那么可以簡單的把一個索引當成一個表,則這就會有1張表+6張索引表=相當于有6張表,那么這6張表在什么時候會操作呢?我們來計算一下:

  • insert操作,數據插入后,需要去對5張索引表插入索引數據

  • delete操作,數據刪除后,需要去把5張索引表中的索引刪除

  • update操作

    • 如果修改了索引列的數據,則先修改數據,還需要修改索引表中的索引

    • 如果沒有修改索引列的數據,則只修改數據表

  • select操作

    • 如果命中查詢索引,則先查詢索引,再查數據表

    • 如果沒命中查詢索引,則直接查數據表

通過以上的計算,你會神奇的發現,索引個數越多,對于insert、delete、update操作是有影響的,而且是負影響。所以對于索引竟可能評估其帶來的影響小于查詢的收益,才去添加,而不是盲目的添加

2、合理的調配復合索引列個數和順序

復合索引指的是包括有多個列的索引,它能有效的減少表的索引個數,平衡了多個字段需要多個索引直接的性能平衡,但是再使用復合索引的時候,需要注意索引列個數和順序的問題。

先說列個數的問題,指的是一個復合索引中包括的列字段太多影響性能的問題,主要是對update操作的性能影響,如下紅字:

  • 如果修改了索引列的數據,則先修改數據,還需要修改索引表中的索引,如果索引列個數越多則修改該索引的概率越大

  • 如果沒有修改索引列的數據,則只修改數據表

再說復合索引中列順序的問題,是指索引的最左匹配原則,即最左優先,在檢索數據時從聯合索引的最左邊開始匹配,這個比較容易理解,就不多做闡述。

那些情況索引會失效?

  • 索引無法存儲null值,當使用is null或is not nulli時會全表掃描

  • like查詢以"%"開頭

  • 對于復合索引,查詢條件中沒有給出索引中第一列的值時

  • mysql內部評估全表掃描比索引快時

  • or、!=、<>、in、not in等查詢也可能引起索引失效

表設計有那些規范?

建表規約

  1. 表達是與否概念的字段,必須使用 is_xxx 的方式命名,數據類型為 unsigned tinyint說明:任何字段如果為非負數,則必須是 unsigned。

  2. 字段允許適當冗余,以提高查詢性能,但必須考慮數據一致。e.g. 商品類目名稱使用頻率高,字段長度短,名稱基本一成不變,可在相關聯的表中冗余存儲類目名稱,

    避免關聯查詢

    。冗余字段遵循:

    • 不是頻繁修改的字段;

    • 不是 varchar 超長字段,更不能是 text 字段。

索引規約

  1. 在 varchar 字段上建立索引時,必須指定索引長度,沒必要對全字段建立索引,根據實際文本區分度決定索引長度即可。

  2. 頁面搜索嚴禁左模糊或者全模糊,如果需要請通過搜索引擎來解決。 說明:索引文件具有 B-Tree 的最左前綴匹配特性,如果左邊的值未確定,那么無法使用此索引。

  3. 如果有 order by 的場景,請注意利用索引的有序性。order by 最后的字段是組合索引的一部分,并且放在索引組合順序的最后,避免出現 file_sort 的情況,影響查詢性能。

    • 正例:where a=? and b=? order by c; 索引: a_b_c。

    • 反例:索引中有范圍查找,那么索引有序性無法利用,如 WHERE a>10 ORDER BY b; 索引 a_b 無法排序。

  4. 利用延遲關聯或者子查詢優化超多分頁場景。 說明:MySQL 并不是跳過 offset 行,而是取 offset+N 行,然后返回放棄前 offset 的行,返回 N 行。當 offset 特別大的時候,效率會非常的低下,要么控制返回的總頁數,要么對超過閾值的頁數進行 SQL 改寫。

  5. 建組合索引的時候,區分度最高的在最左邊。

  6. SQL 性能優化的目標,至少要達到 range 級別,要求是 ref 級別,最好是 consts。

SQL 語句

  1. 不要使用 count(列名) 或 count(常量) 來替代 count(),count() 是 SQL92 定義的標準統計行數的語句,跟數據庫無關,跟 NULL 和非 NULL 無關。 說明:count(*) 會統計值為 NULL 的行,而 count(列名) 不會統計此列為 NULL 值的行。

  2. count(distinct column) 計算該列除 NULL 外的不重復行數。注意,count(distinct column1,column2) 如果其中一列全為 NULL,那么即使另一列用不同的值,也返回為 0。

  3. 當某一列的值全為 NULL 時,count(column) 的返回結果為 0,但 sum(column) 的返回結果為 NULL,因此使用 sum() 時需注意 NPE 問題。 可以使用如下方式來避免 sum 的 NPE 問題。

SELECT IF(ISNULL(SUM(g), 0, SUM(g))) FROM table;
  1. 使用 ISNULL() 來判斷是否為 NULL 值。 說明:NULL 與任何值的直接比較都為 NULL。

  2. 不得使用外鍵與級聯,一切外鍵概念必須在應用層解決。 說明:以學生和成績的關系為例,學生表的 student_id 是主鍵,成績表的 student_id 則為外鍵。如果更新學生表中的 student_id,同時觸發成績表中的 student_id 更新,即為級聯更新。外鍵與級聯更新適用于單機低并發,不適合分布式、高并發集群;級聯更新是強阻塞,存在數據庫更新風暴的風險;外鍵影響數據庫的插入速度。

  3. 禁止使用存儲過程。存儲過程難以調試和擴展,更沒有移植性。

  4. in 操作能避免則避免。若實在避免不了,需要仔細評估 in 后面的集合元素數量,控制在 1000 個之內。

ORM 映射

  1. POJO 類的布爾屬性不能加 is,而數據庫字段必須加 is_,要求在 resultMap 中進行字段與屬性的映射。

  2. sql.xml 配置參數使用:#{}, #param#,不要使用 ${},此種方式容易出現 SQL 注入。

  3. @Transactional 事務不要濫用。事務會影響數據庫的 QPS。另外,使用事務的地方需要考慮各方面的回滾方案,包括緩存回滾、搜索引擎回滾、消息補償、統計修正等。

關于“Mysql優化問題有哪些”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“Mysql優化問題有哪些”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

科技| 临沂市| 芦山县| 陆河县| 南漳县| 离岛区| 上栗县| 噶尔县| 遵化市| 石家庄市| 漯河市| 汕头市| 楚雄市| 洛扎县| 商南县| 大理市| 泸州市| 崇阳县| 双柏县| 临西县| 崇仁县| 碌曲县| 澄江县| 曲沃县| 得荣县| 宜兰县| 交城县| 安吉县| 石城县| 永福县| 青铜峡市| 汉阴县| 海口市| 无棣县| 黎川县| 洞口县| 乐平市| 崇阳县| 金平| 南涧| 大埔县|