摘要:實現(xiàn)事務的原子性,要支持回滾操作,在某個操作失敗后,回滾到事務執(zhí)行之前的狀態(tài)。一致性事務使得系統(tǒng)從一個一致的狀態(tài)轉換到另一個一致狀態(tài)。
本文作者 TomorrowWu,原創(chuàng)文章,轉載注明出處,博客地址 https://segmentfault.com/u/to... 第一時間看后續(xù)精彩文章。覺得好的話,順手分享到朋友圈吧,感謝支持。
筆者最近在準備面試,覺得學習最好的方式就是把知道的東西通過博客寫出來,一方面考察自己對某個知識點的理解,一方面督促自己查閱更多資料深入學習
我會總結出我在網(wǎng)上看到的面試題以及相應的答案,并且盡可能的講原理,有錯誤的地方希望有大神基給予指正,讀者如果有好的題目,也可以評論中提出,我將后續(xù)更新上去,謝謝
當然學習MySQL不僅僅是看一些面試題,最好還是看一些相關的書籍,比如比較好的就是<<高性能MySQL>>中文版,很詳細,很厚,還未看完,還有簡朝陽先生的<
1.常用的方法是explainSQL查看執(zhí)行計劃,根據(jù)查詢計劃知道是否使用了索引,以及是否進行全表掃描,以及查詢的順序等等全過程,依次我們可以建立適當?shù)乃饕瓦B接查詢調優(yōu)、SQL語句拆分等
2.開啟慢查詢,記錄執(zhí)行時間長的SQL語句
SQL優(yōu)化通常會在where、join on、order by等使用到的字段上加上索引
避免查詢時判斷null,否則可能會導致全表掃描,無法使用索引;
解決方案:
在創(chuàng)建表時,字段盡量指定默認值,或者設置not null,不要給數(shù)據(jù)庫留null
避免使用or來連接查詢條件,如果一個字段有索引,一個字段沒有索引,將導致引擎放棄使用索引而進行全表掃描,可以改用union或union all
優(yōu)化案例
select id from t where num=10 or Name = "admin" //優(yōu)化后 select id from t where num = 10 union all select id from t where Name = "admin"
避免like查詢,否則可能導致全表掃描,可以考慮使用全文索引
前置模糊索引 like "%abc" 勢必會進行全表掃描; 2. like "abc%"依舊有可能進行全表掃描,當部分DBMD中返回結果超過該表的80%時,就失去使用索引的意義數(shù)據(jù)庫會自動改用全表掃描.(例如: where mobile like "1%")
應盡量避免在 where 子句中使用 != 或<>操作符,否則導致全表掃描
不使用select *,只查詢必須字段,避免加載無用數(shù)據(jù)
能用union all的時候就不用union,union過濾重復數(shù)據(jù)要耗費更多的CPU資源
where子句中使用變量參數(shù),導致全表掃描
原理:SQL只有在運行時才會解析局部變量,優(yōu)化程序必須在編譯時選擇訪問計劃,但是編譯時變量值還未知,因此無法作為索引選擇的輸入項
//全表掃描 select id from t where num = @num //強制使用索引 select id from t with(index(索引名)) where num = @num
避免在where子句中對字段進行表達式操作,導致放棄索引進行全表掃描
select id from t where num/2 = 100 //修改為 select id from t where num = 100*2
避免在where子句中對字段進行函數(shù)操作,導致放棄索引進行全表掃描
select id from t where substring(name,1,3) = ’abc’ //修改后 select id from t where name like "abc%"
索引并不是越多越好,索引可以提高查詢效率,但插入和修改時可能會重建索引;一個表的索引數(shù)量最好不要超過6個
字段類型盡量使用數(shù)字,不要設計成字符串,會降低性能,并增加存儲開銷
引擎在逐個比較字符串中每一個字符,對于數(shù)字只需要比較一次
避免使用游標,效率很差,如果游標操作的數(shù)據(jù)超過1萬行,就應該考慮改寫
盡量避免大事務操作,提高系統(tǒng)并發(fā)能力
拆分大的 DELETE 或 INSERT 語句。因為這兩個操作是會鎖表的,別的操作都進不來了,有時候用for循環(huán)來一個個執(zhí)行這些操作。
獲取唯一行時使用limit 1
引擎在找到第一個記錄后就停止掃描記錄,而不是遍歷整個表或索引
優(yōu)先使用enum
少量state使用enum,方便遷移數(shù)據(jù)庫以及維護,使用int和varchar
表字段設置為固定長度(靜態(tài))的表更快
使用procedure analyse()獲取建議,優(yōu)化表結構
使用orm
優(yōu)點:代碼量少,延遲加載,多個查詢批處理到事務中,操作速度比單個查詢快很多
缺點:級聯(lián)查詢
MySQL有哪些存儲引擎,區(qū)別InnoDB,MyISAM,Archive,Blackhole,CSV,Federated,Memory,Merge,NDB集群引擎等,還有一些第三方存儲引擎
引擎 | 存儲結構 | 存儲空間 | 可移植性、備份及恢復 | 事務支持 | AUTO_INCREMENT | 表鎖差異 | 全文索引 | 表主鍵 | 表的具體行數(shù) | CRUD操作 | 外鍵 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
InnoDB | 所有的表都保存在同一個數(shù)據(jù)文件中(也可能是多個文件,或者是獨立的表空間文件),InnoDB表的大小只受限于操作系統(tǒng)文件的大小,一般為2GB | 需要更多的內存和存儲,它會在主內存中建立其專用的緩沖池用于高速緩沖數(shù)據(jù)和索引 | 免費的方案可以是拷貝數(shù)據(jù)文件、備份binlog,或者用mysqldump,在數(shù)據(jù)量達到幾十G時就相對痛苦了 | 支持事務,外部鍵等高級數(shù)據(jù)庫功能;具有事務(commit)、回滾(rollback)和崩潰修復能力(crash recovery capabilities)的事務安全型表(transaction-safe ACID compliant) | 必須包含只有該字段的索引;自動增長列必須是索引;如果是組合索引也必須是組合索引的第一列 | 行級鎖;行鎖大幅度提高了多用戶并發(fā)操作性能;只有在where的主鍵時有效,非主鍵的where鎖全表 | 5.6.4以后開始支持fulltext類型的全文索引 | 如果沒有設定主鍵或者非空唯一索引,就會自動生成一個6字節(jié)的主鍵(用戶不可見),數(shù)據(jù)是主索引的一部分,附加索引保存的是主索引的值 | 沒有保存表的總行數(shù),如果使用select count() from table;就會遍歷整個表,消耗相當大,但是在加了wehre條件后,myisam和innodb處理的方式都一樣 | 適合大量insert或update;delete從性能上InnoDB更優(yōu),但DELETE FROM table時,InnoDB不會重新建立表,而是一行一行的刪除,在innodb上如果要清空保存有大量數(shù)據(jù)的表,最好使用truncate table這個命令 | 支持外鍵 | |
MyISAM | 在磁盤上存儲成三個文件,第一個文件的名字以表的名字開始,擴展名指出文件類型;.frm文件存儲表定義;數(shù)據(jù)文件的擴展名為.MYD(MYData);索引文件的擴展名是.MYI(MYIndex) | 可被壓縮,存儲空間較小;支持三種存儲格式:靜態(tài)表(默認,注意數(shù)據(jù)末尾不能有空格,會被去掉)、動態(tài)表、壓縮表 | 數(shù)據(jù)是以文件的形式存儲,跨平臺的數(shù)據(jù)轉移中很方便,在備份和恢復時可多帶帶針對某個表進行操作 | 不支持事務,不支持外鍵;強調性能,每次查詢具有原子性,執(zhí)行速度比InnoDB快 | 可以和其他字段一起建立聯(lián)合索引;自動增長列必須是索引,如果是組合索引,自動增長列可以不是第一列,它可以根據(jù)前面幾列進行排序后遞增 | 表級鎖;select,update,delete,insert語句都會給表自動加鎖,如果加鎖后,表滿足insert并發(fā)的情況下,可以在表尾部插入新數(shù)據(jù) | 支持fulltext類型的全文索引 | 允許沒有任何索引和主鍵的表存在,索引都是保存行的地址 | 保存有表的總行數(shù),select count() from table;會直接取出出該值 | 適合有大量select | 不支持外鍵 |
引擎 | 原則 |
---|---|
采用MyISAM引擎 | 1. R/W > 100:1,且update相對較少; 2,并發(fā)不高 3, 表數(shù)據(jù)量小 4, 硬件資源有限 |
采用InnoDB引擎 | 1, R/W比較小,頻繁update大字段 2, 表數(shù)據(jù)量超過1000萬,并發(fā)高 3,安全性和可用性要求高 |
采用Memory引擎 | 1,有足夠的內存 2,對數(shù)據(jù)一致性要求不高,如在線人數(shù)和session等應用3, 需要定期歸檔數(shù)據(jù) |
not null的字段不能插入null,只能插入"空值"
空值是不占用空間的,null其實不是空值,而是要占用空間
null會參與字段比較,對效率有一部分影響
對表的索引,不會存儲null值,如果索引的字段可以為null,索引的效率會下降很多
空值不一定等于空字符串例如電話號碼等字段,空值表示不知道對方的手機號碼,空字符表示后來取消了這個號碼,等等
分頁問題的優(yōu)化簡單來說,避免數(shù)據(jù)量大時掃描過多的記錄
解決方案:
方案 | 具體過程 | 原理 | 缺點 | |
---|---|---|---|---|
基于id分頁 | 帶上前一頁最后一條記錄的id去請求下一頁數(shù)據(jù),后端在去MySQL查詢時,where條件加上 id>last_id limit 10,order by id | 可以少去聚簇索引中拿很多數(shù)據(jù),只拿需要的10條 | 需要產品上做一些妥協(xié),無法進行指定頁的跳轉,加載數(shù)據(jù)時使用更多按鈕 | |
基于offset(偏移量)分頁 | 先去二級索引中找出滿足條件的offset+limit行記錄的id,然后根據(jù)id去聚簇索引中找到對應的行記錄,取出offset+limit行數(shù)據(jù),最后丟掉offset行,只保留limit行,效率很差 | 因為去聚簇索引中訪問了太多不必要的數(shù)據(jù) | 效率差 |
優(yōu)化案例:
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連續(xù)的系統(tǒng),速度極快 select * from news where id between 1000000 and 1000010 order by id desc延遲加載
類型 | 如何實現(xiàn) | 使用場景 | 優(yōu)點 | 缺點 | |
---|---|---|---|---|---|
延遲加載 | 分頁SQL拆成兩句,第一句先查詢符合條件的id(查詢的列都在二級索引中,不用訪問聚簇索引中的數(shù)據(jù)行,效率很高) 第二個sql根據(jù)id去聚簇索引拿數(shù)據(jù) | 解決offset過大導致的分頁性能問題 | 8s變50ms,避免加載多余數(shù)據(jù),浪費內存,網(wǎng)絡傳輸 | sql語句被多次發(fā)送執(zhí)行,對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(原子性,一致性,隔離性,持久性)原則原子性
一個事務包含多個操作,這些操作要么全部執(zhí)行,要么全都不執(zhí)行。實現(xiàn)事務的原子性,要支持回滾操作,在某個操作失敗后,回滾到事務執(zhí)行之前的狀態(tài)。
一致性
事務使得系統(tǒng)從一個一致的狀態(tài)轉換到另一個一致狀態(tài)。事務的一致性決定了一個系統(tǒng)設計和實現(xiàn)的復雜度
程度 | 詳解 |
---|---|
強一致性 | 讀操作可以立即讀到提交的更新操作 |
弱一致性 | 提交的更新操作,不一定立即會被讀操作讀到 |
最終一致性 | 是弱一致性的特例。事務更新一份數(shù)據(jù),最終一致性保證在沒有其他事務更新同樣的值的話,最終所有的事務都會讀到之前事務更新的最新值 |
單調一致性 | 如果一個進程已經讀到一個值,那么后續(xù)不會讀到更早的值 |
會話一致性 | 保證客戶端和服務器交互的會話過程中,讀操作可以讀到更新操作后的最新值 |
隔離性
并發(fā)事務之間互相影響的程度,比如一個事務會不會讀取到另一個未提交的事務修改的數(shù)據(jù)
持久性
事務提交后,對系統(tǒng)的影響是永久的
最常見的一個性能問題
舉個例子,我們數(shù)據(jù)庫中有兩張表,一個是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原則有什么區(qū)別?
前者的讀寫責任分離,責任是根據(jù)具體業(yè)務來的,讀不僅僅是指的數(shù)據(jù)庫意義上的讀操作,而是根據(jù)業(yè)務需求,為復雜業(yè)務時的讀操作,專門建立數(shù)據(jù)庫以供直接讀取去展示界面;后者讀寫分離是針對數(shù)據(jù)庫層次的,主數(shù)據(jù)庫寫,從數(shù)據(jù)庫讀
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/17627.html
摘要:結論把存入數(shù)據(jù)庫前必須做次處理中文處理包含中文的字符串時,會將中文字符轉換為的形式,而且通過是不能恢復的。處理特殊字符通過解決中文問題會帶來新問題,的特殊字符處理。 開發(fā)過程中經常碰到要把前端的json格式的數(shù)據(jù)傳遞到后端php,php做一些業(yè)務處理后把數(shù)據(jù)存到mysql,然后,php再從mysql中取出數(shù)據(jù)返回到前端。雖然這是一個再基礎不過的處理過程,但還是有不少問題需要認真研究。下...
摘要:結論把存入數(shù)據(jù)庫前必須做次處理中文處理包含中文的字符串時,會將中文字符轉換為的形式,而且通過是不能恢復的。處理特殊字符通過解決中文問題會帶來新問題,的特殊字符處理。 開發(fā)過程中經常碰到要把前端的json格式的數(shù)據(jù)傳遞到后端php,php做一些業(yè)務處理后把數(shù)據(jù)存到mysql,然后,php再從mysql中取出數(shù)據(jù)返回到前端。雖然這是一個再基礎不過的處理過程,但還是有不少問題需要認真研究。下...
摘要:常見錯誤分析與解決方法總結一翻譯不能連接到上的分析這說明計算機是存在的,但在這臺機器上卻沒提供服務。解決同樣對癥下藥,不同的原因不同的處理方法。九翻譯有一個語法錯誤在你的中分析論壇標準的程序是沒有語法錯誤的。表名,可以暫時解決問題。MySQL常見錯誤分析與解決方法總結 一、Cant connect to MySQL server on localhost (10061)翻譯:不能連接到 ...
閱讀 1414·2023-04-26 03:04
閱讀 2369·2019-08-30 15:44
閱讀 3737·2019-08-30 14:15
閱讀 3543·2019-08-27 10:56
閱讀 2763·2019-08-26 13:53
閱讀 2627·2019-08-26 13:26
閱讀 3090·2019-08-26 12:11
閱讀 3619·2019-08-23 18:21