MySQL常見問題總結

本文做者 TomorrowWu,原創文章,轉載註明出處,博客地址 https://segmentfault.com/u/to... 第一時間看後續精彩文章。以爲好的話,順手分享到朋友圈吧,感謝支持。mysql

筆者最近在準備面試,以爲學習最好的方式就是把知道的東西經過博客寫出來,一方面考察本身對某個知識點的理解,一方面督促本身查閱更多資料深刻學習面試

我會總結出我在網上看到的面試題以及相應的答案,而且儘量的講原理,有錯誤的地方但願有大神基給予指正,讀者若是有好的題目,也能夠評論中提出,我將後續更新上去,謝謝sql

固然學習MySQL不只僅是看一些面試題,最好仍是看一些相關的書籍,好比比較好的就是<<高性能MySQL>>中文版,很詳細,很厚,還未看完,還有簡朝陽先生的<<MySQL性能調優與架構設計>>一書,當初泛讀了一遍,等待深刻研究中數據庫

MySQL平時是怎麼分析效率?

1.經常使用的方法是explainSQL查看執行計劃,根據查詢計劃知道是否使用了索引,以及是否進行全表掃描,以及查詢的順序等等全過程,依次咱們能夠創建適當的索引和鏈接查詢調優、SQL語句拆分等segmentfault

2.開啓慢查詢,記錄執行時間長的SQL語句後端

SQL優化

  1. 一般會在where、join on、order by等使用到的字段上加上索引
  2. 避免查詢時判斷null,不然可能會致使全表掃描,沒法使用索引;

解決方案:
在建立表時,字段儘可能指定默認值,或者設置not null,不要給數據庫留null安全

  1. 避免使用or來鏈接查詢條件,若是一個字段有索引,一個字段沒有索引,將致使引擎放棄使用索引而進行全表掃描,能夠改用union或union all

優化案例服務器

select id from t where num=10 or Name = 'admin'
//優化後
select id from t where num = 10 union all select id from t where Name = 'admin'
  1. 避免like查詢,不然可能致使全表掃描,能夠考慮使用全文索引
  1. 前置模糊索引 like '%abc' 勢必會進行全表掃描; 2. like 'abc%'依舊有可能進行全表掃描,當部分DBMD中返回結果超過該表的80%時,就失去使用索引的意義數據庫會自動改用全表掃描.(例如: where mobile like '1%')
  1. 應儘可能避免在 where 子句中使用 != 或<>操做符,不然致使全表掃描
  2. 不使用select *,只查詢必須字段,避免加載無用數據
  3. 能用union all的時候就不用union,union過濾重複數據要耗費更多的CPU資源
  4. where子句中使用變量參數,致使全表掃描

原理:SQL只有在運行時纔會解析局部變量,優化程序必須在編譯時選擇訪問計劃,可是編譯時變量值還未知,所以沒法做爲索引選擇的輸入項網絡

//全表掃描
select id from t where num = @num
//強制使用索引
select id from t with(index(索引名)) where num = @num
  1. 避免在where子句中對字段進行表達式操做,致使放棄索引進行全表掃描
select id from t where num/2 = 100
//修改成
select id from t where num = 100*2
  1. 避免在where子句中對字段進行函數操做,致使放棄索引進行全表掃描
select id from t where substring(name,1,3) = ’abc’
//修改後
select id from t where name like 'abc%'
  1. 索引並非越多越好,索引能夠提升查詢效率,但插入和修改時可能會重建索引;一個表的索引數量最好不要超過6個
  2. 字段類型儘可能使用數字,不要設計成字符串,會下降性能,並增長存儲開銷

引擎在逐個比較字符串中每個字符,對於數字只須要比較一次session

  1. 避免使用遊標,效率不好,若是遊標操做的數據超過1萬行,就應該考慮改寫
  2. 儘可能避免大事務操做,提升系統併發能力
  3. 拆分大的 DELETE 或 INSERT 語句。由於這兩個操做是會鎖表的,別的操做都進不來了,有時候用for循環來一個個執行這些操做。
  4. 獲取惟一行時使用limit 1

引擎在找到第一個記錄後就中止掃描記錄,而不是遍歷整個表或索引

  1. 優先使用enum

少許state使用enum,方便遷移數據庫以及維護,使用int和varchar

  1. 表字段設置爲固定長度(靜態)的表更快
  2. 使用procedure analyse()獲取建議,優化表結構
  3. 使用orm
    優勢:代碼量少,延遲加載,多個查詢批處理到事務中,操做速度比單個查詢快不少

缺點:級聯查詢

MySQL有哪些存儲引擎,區別

InnoDB,MyISAM,Archive,Blackhole,CSV,Federated,Memory,Merge,NDB集羣引擎等,還有一些第三方存儲引擎

引擎 存儲結構 存儲空間 可移植性、備份及恢復 事務支持 AUTO_INCREMENT 表鎖差別 全文索引 表主鍵 表的具體行數 CRUD操做 外鍵
InnoDB 全部的表都保存在同一個數據文件中(也多是多個文件,或者是獨立的表空間文件),InnoDB表的大小隻受限於操做系統文件的大小,通常爲2GB 須要更多的內存和存儲,它會在主內存中創建其專用的緩衝池用於高速緩衝數據和索引 免費的方案能夠是拷貝數據文件、備份binlog,或者用mysqldump,在數據量達到幾十G時就相對痛苦了 支持事務,外部鍵等高級數據庫功能;具備事務(commit)、回滾(rollback)和崩潰修復能力(crash recovery capabilities)的事務安全型表(transaction-safe ACID compliant) 必須包含只有該字段的索引;自動增加列必須是索引;若是是組合索引也必須是組合索引的第一列 行級鎖;行鎖大幅度提升了多用戶併發操做性能;只有在where的主鍵時有效,非主鍵的where鎖全表 5.6.4之後開始支持fulltext類型的全文索引 若是沒有設定主鍵或者非空惟一索引,就會自動生成一個6字節的主鍵(用戶不可見),數據是主索引的一部分,附加索引保存的是主索引的值 沒有保存表的總行數,若是使用select count() from table;就會遍歷整個表,消耗至關大,可是在加了wehre條件後,myisam和innodb處理的方式都同樣 適合大量insert或update;delete從性能上InnoDB更優,但DELETE FROM table時,InnoDB不會從新創建表,而是一行一行的刪除,在innodb上若是要清空保存有大量數據的表,最好使用truncate table這個命令 支持外鍵
MyISAM 在磁盤上存儲成三個文件,第一個文件的名字以表的名字開始,擴展名指出文件類型;.frm文件存儲表定義;數據文件的擴展名爲.MYD(MYData);索引文件的擴展名是.MYI(MYIndex) 可被壓縮,存儲空間較小;支持三種存儲格式:靜態表(默認,注意數據末尾不能有空格,會被去掉)、動態表、壓縮表 數據是以文件的形式存儲,跨平臺的數據轉移中很方便,在備份和恢復時可單獨針對某個表進行操做 不支持事務,不支持外鍵;強調性能,每次查詢具備原子性,執行速度比InnoDB快 能夠和其餘字段一塊兒創建聯合索引;自動增加列必須是索引,若是是組合索引,自動增加列能夠不是第一列,它能夠根據前面幾列進行排序後遞增 表級鎖;select,update,delete,insert語句都會給表自動加鎖,若是加鎖後,表知足insert併發的狀況下,能夠在表尾部插入新數據 支持fulltext類型的全文索引 容許沒有任何索引和主鍵的表存在,索引都是保存行的地址 保存有表的總行數,select count() from table;會直接取出出該值 適合有大量select 不支持外鍵

存儲引擎選擇的基本原則

引擎 原則
採用MyISAM引擎 1. R/W > 100:1,且update相對較少; 2,併發不高 3, 表數據量小 4, 硬件資源有限
採用InnoDB引擎 1, R/W比較小,頻繁update大字段 2, 表數據量超過1000萬,併發高 3,安全性和可用性要求高
採用Memory引擎 1,有足夠的內存 2,對數據一致性要求不高,如在線人數和session等應用3, 須要按期歸檔數據

爲何select * from table where field = null 不能匹配空的字段

  • not null的字段不能插入null,只能插入"空值"
  • 空值是不佔用空間的,null其實不是空值,而是要佔用空間
  • null會參與字段比較,對效率有一部分影響
  • 對錶的索引,不會存儲null值,若是索引的字段能夠爲null,索引的效率會降低不少

空值不必定等於空字符串

例如電話號碼等字段,空值表示不知道對方的手機號碼,空字符表示後來取消了這個號碼,等等

分頁問題的優化

簡單來講,避免數據量大時掃描過多的記錄
解決方案:

方案 具體過程 原理 缺點
基於id分頁 帶上前一頁最後一條記錄的id去請求下一頁數據,後端在去MySQL查詢時,where條件加上 id>last_id limit 10,order by id 能夠少去聚簇索引中拿不少數據,只拿須要的10條 須要產品上作一些妥協,沒法進行指定頁的跳轉,加載數據時使用更多按鈕
基於offset(偏移量)分頁 先去二級索引中找出知足條件的offset+limit行記錄的id,而後根據id去聚簇索引中找到對應的行記錄,取出offset+limit行數據,最後丟掉offset行,只保留limit行,效率不好 由於去聚簇索引中訪問了太多沒必要要的數據 效率差

優化案例:

select * from news order by id desc limit 1000000,10
耗時7.28秒

//方案1 0.365秒
select * from news 
where id >  (select id from news order by id desc  limit 1000000, 1)
order by id desc 
limit 0,10

方案2 ,適合id連續的系統,速度極快
select * from news 
where id  between 1000000 and 1000010 
order by id desc

延遲加載

類型 如何實現 使用場景 優勢 缺點
延遲加載 分頁SQL拆成兩句,第一句先查詢符合條件的id(查詢的列都在二級索引中,不用訪問聚簇索引中的數據行,效率很高) 第二個sql根據id去聚簇索引拿數據 解決offset過大致使的分頁性能問題 8s變50ms,避免加載多餘數據,浪費內存,網絡傳輸 sql語句被屢次發送執行,對DB性能有影響

案例:

SELECT
  *
FROM
  table_A USE INDEX (index_A)
WHERE
  A = xxx
  AND B = xxx
  AND C IN (xxx)
ORDER BY
  D DESC
LIMIT
  33380, 11

KEY `index_A` (`A`,`B`,`D`,`C`)

// 延遲加載後:
1.
SELECT
  table_A.id
FROM
  table_A USE INDEX (index_A)
WHERE
  A = xxx
  AND B = xxx
  AND C IN (xxx)
ORDER BY
  D DESC
LIMIT
  33380, 11;

2.
Select * from table_A where id in (ids)

如何找出應用中開銷最大的查詢

慢查詢日誌

什麼是ACID(原子性,一致性,隔離性,持久性)原則

  • 原子性

一個事務包含多個操做,這些操做要麼所有執行,要麼全都不執行。實現事務的原子性,要支持回滾操做,在某個操做失敗後,回滾到事務執行以前的狀態。

  • 一致性

事務使得系統從一個一致的狀態轉換到另外一個一致狀態。事務的一致性決定了一個系統設計和實現的複雜度

程度 詳解
強一致性 讀操做能夠當即讀到提交的更新操做
弱一致性 提交的更新操做,不必定當即會被讀操做讀到
最終一致性 是弱一致性的特例。事務更新一份數據,最終一致性保證在沒有其餘事務更新一樣的值的話,最終全部的事務都會讀到以前事務更新的最新值
單調一致性 若是一個進程已經讀到一個值,那麼後續不會讀到更早的值
會話一致性 保證客戶端和服務器交互的會話過程當中,讀操做能夠讀到更新操做後的最新值
  • 隔離性

併發事務之間互相影響的程度,好比一個事務會不會讀取到另外一個未提交的事務修改的數據

  • 持久性
    事務提交後,對系統的影響是永久的

什麼是N+1問題

最多見的一個性能問題

舉個例子,咱們數據庫中有兩張表,一個是Customers,一個是Orders。Orders中含有一個外鍵customer_id,指向了Customers的主鍵id,想要獲得全部Customer以及其分別對應的Order

// N+1方式
SELECT * FROM Customers;
SELECT * FROM Orders WHERE Orders.customer_id = #{customer.id}

//left join
 SELECT * FROM Customers LEFT JOIN Orders on Customers.id = Orders.customer_id;

什麼是CQRS(Command Query Responsibility Segregation)?他和最先的Command-QuerySeparation原則有什麼區別?

前者的讀寫責任分離,責任是根據具體業務來的,讀不只僅是指的數據庫意義上的讀操做,而是根據業務需求,爲複雜業務時的讀操做,專門創建數據庫以供直接讀取去展現界面;後者讀寫分離是針對數據庫層次的,主數據庫寫,從數據庫讀

相關文章
相關標籤/搜索