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