mysql系列【mysql優化完結篇】(面試必問)

前言

hello,大家好!博主上篇內容【mysql索引優化】 也是mysql優化的一部分,因爲所以這一塊相對來說內容比較多,所以單獨抽取出來;大家都知道mysql優化是面試中的常客,也是重頭戲,希望這篇內容能給到大家幫助

1、查找慢查詢並定位慢查詢

其中mysql的慢查詢參數

  • slow_query_log 慢查詢開啓狀態
  • slow_query_log_file 慢查詢日誌存放的位置(這個目錄需要MySQL的運行帳號的可寫權限,一般設置爲MySQL的數據存放目錄)
  • long_query_time 查詢超過多少秒才記錄

1、查看慢查詢的相關參數

mysql> show variables like 'slow_query%';
+---------------------------+----------------------------------+
| Variable_name             | Value                            |
+---------------------------+----------------------------------+
| slow_query_log            | OFF                              |
| slow_query_log_file       | /mysql/data/localhost-slow.log   |
+---------------------------+----------------------------------+

mysql> show variables like 'long_query_time';
+-----------------+-----------+
| Variable_name   | Value     |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+

2、設置方法

方法一:全局變量設置


-- 將 slow_query_log 全局變量設置爲“ON”狀態
mysql> set global slow_query_log='ON'; 

--設置慢查詢日誌存放的位置
mysql> set global slow_query_log_file='/usr/local/mysql/data/slow.log';
--查詢超過1秒就記錄
mysql> set global long_query_time=1;

方法二:配置文件設置

修改配置文件my.cnf,在[mysqld]下的下方加入
[mysqld]
slow_query_log = ON
slow_query_log_file = /usr/local/mysql/data/slow.log
long_query_time = 1

3、然後使用explain詳細分析sql語句

2、選擇合適的存儲引擎

Mysql 中常用的兩個引擎 MyISAMInnoDB

MyISAM
默認表類型(5.5之前),它是基於傳統的ISAM(Indexed Sequential Access Method)類型(有索引的順序訪問方法),它是存儲記錄和文件的標準方法。不是事務安全的,而且不支持外鍵,如果表對事務要求不高,同時是以查詢和添加爲主的,我們考慮使用MyISAM,比如bbs中的發帖表,回覆表,

InnoDB:mysql5.5之後默認的存儲引擎,支持事務;支持外鍵;行鎖;事務是他的最大特點。如果有大量的update和insert,建議使用InnoDB,特別是針對多個併發和QPS較高的情況。比如訂單表,賬號表。

InnoDB和MyISAM的區別

  • 事務 :
    InnoDB支持事務,MyISAM不支持事務
  • 外鍵 :
    InnoDB支持外鍵,MyISAM不支持外鍵
  • 全文索引
    InnoDB不支持全文索引,MyISAM支持
  • 業務
    InnoDB適合高併發業務,MyISAM適合查詢比較多的業務

  • InnoDB支持行鎖,但是是基於索引有效的情況,如果索引失效,InnoDB會默認行鎖轉變成表鎖,MyISAM只支持表鎖

3、mysql分區分表

在此之前得有一些原則

基本原則
設計數據庫表的時候需要三大範式
是首先符合1N,才能滿足2NF,進一步滿是3NF

  • 1NF:即表的列的具有原子性,不可再分解,即列的信息,不燒分解.只要數據庫是關係型數據庫(mysql/oracle/db2/syshase/sql server),就自動的滿足1NF.關係型數據庫中是不允許分割列的。
  • 2NF:表中的記錄是唯一的通常我們設計一個主鍵來實現
  • 3NF:即表中不要有元餘數據,就是說,表的信息,如果能夠按推導出來,就不應該單獨的設計一個字段來存放.

優化
反3NF:沒有冗餘的數據庫未必是最好的數據庫,有時爲了提高運行效率,就必須降低範式標準,適當保留冗餘數據。具體做法是;在概念數據模型設計時遵守第三範式,降低範式標準的工作放到物理數據模型設計時考慮。降低範式就是增加字段,允許冗餘。

  • 分區就是把一張表的數據分成N多個區塊,這些區塊可以在同一個磁盤上,也可以在不同的磁盤上
  • 分表從表面意思上看呢,就是把一張表分成N多個小表
  • 分表和表分區的目的就是減少數據庫的負擔,提高數據庫的效率,通常點來講就是提高表的增刪改查效率。

mysql分區
partition,分區是將數據分段劃分在多個位置存放,可以是同一塊磁盤也可以在不同的機器。分區後,表面上還是一張表,但數據散列到多個位置了。程序讀寫的時候操作的還是大表名字,db自動去組織分區的數據。 下面看下語法👇

-- 創建表的時候添加分區
Create table table_name (定義)

Partition by 分區算法 (參數) 分區選項。

例如:Partition by key (id) partitions 5;
------------	
create table partition_1(
id int UNSIGNED not nul1 AUTO_INCREMENT, 
title varchar(255), PRIMARY KEY(id)
)engine=myisam
partition by key(id) partitions 5;

分區算法

MySQL提供4種分區算法: Key hash Listrange

參與分區的參數字段需要爲主鍵的一部分。

mysql的分表
這個是真正的分表,一張表分成很多表後,每一個小表都是完正的一張表,都對應三個文件,一個.MYD數據文件,.MYI索引文件,.frm表結構文件。

分表又分爲水平分表垂直分表

  • 水平分表
    mysql表數據一般達到百萬級別,查詢效率會很低,容易造成表鎖,甚至堆積很多連接,直接掛掉;水平分表能夠很大程度減少這些壓力。

在這裏插入圖片描述

  • 垂直分表
    如果一張表中某個字段值非常多(長文本、二進制等),而且只有在很少的情況下會查詢。這時候就可以把字段多個單獨放到一個表,通過外鍵關聯起來。

4、主從複製

  • 一臺數據庫支種的最大併發連接數是有限的,如果用戶併發訪問太多,一臺服務器滿足不要要求是就可以集羣處理。mysql的集羣處理技術最常用的就是讀寫分離,不過我們得先主從複製
  • 一個sql語句需要鎖表,導致暫時不能使用讀的服務,那麼就很影響運行中的業務,使用主從複製,讓主庫負責寫,從庫負責讀,這樣,即使主庫出現了鎖表的情景,通過讀從庫也可以保證業務的正常運作。

MySQL複製過程分成三步:

  • MySQL的主從複製是一個異步的複製過程,數據將從一個MySQL數據庫(Master)複製到另一個MySQL數據庫(Slave)
  • 在Master和Slave之間實現整個主從複製的過程是由三個線程參與完成的。其中兩個線程(SQL線程和IO線程)在Slave端,另一個線程(I/O線程)在Master端。
  • 要實現MySQL的主從複製,首先必須打開Master端的binlog記錄功能,否則就無法實現。binlog: binary log,是主庫中保存所有更新事件日誌的二進制文件。因爲整個複製過程實際上就是Slave從Master端獲取binlog日誌,然後在Slave上以相同順序執行獲取的binlog日誌中的記錄的各種SQL操作。

在這裏插入圖片描述

  1. master將改變記錄到二進制日誌(binary log)。這些記錄過程叫做二進制日誌事件,binary log events;
  2. slave將master的binary log events拷貝到它的中繼日誌(relay log);
  3. slave重做中繼日誌中的事件,將改變應用到自己的數據庫中。MySQL複製是異步的且串行化的

5、使用各種緩存

說到緩存,可能大家就比較熟悉了,redis呀,query_cache等等

但是mysql8.0已經取消了查詢緩存,相信也有一定的道理吧
包括mongodb這樣的nosql數據庫都可以爲mysql減輕一定的壓力,

6、你是怎樣優化分頁語句?

mysql中你的分頁是這樣寫的麼:
select column from table limit (page-1)*size,size;
其實如果數據量大這就必須要優化了

select column_name
from table as b inner join (
select id from table as a limit (page-1)*size 
) where a.id = b.id

上面就是簡單的優化,因爲這個limit 的第一個參數基數越大,查詢時間就越長,這裏靠主鍵索引能夠起不小的作用呢

結言:歐了,以上兩篇mysql優化內容算是告一段落了,希望我們能夠在求職道路上披荊斬棘,職業生涯越走越遠,也歡迎評論區留言 ,喜歡博文可以給個👍呦,也可以關注我【jar殼蟲】,後續會有更多分享🎈🎈

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