1.數(shù)據(jù)庫的三范式是什么?
?第一范式:強調(diào)的是列的原子性叠聋,即數(shù)據(jù)庫表的每一列都是不可分割的原子數(shù)據(jù)項讯私。
?第二范式:要求實體的屬性完全依賴于主關(guān)鍵字。所謂完全依賴是指不能存在僅依賴主關(guān)鍵字一部分的屬性准浴。
?第三范式:任何非主屬性不依賴于其它非主屬性事扭。
2.一張自增表里面總共有 7 條數(shù)據(jù),刪除了最后 2 條數(shù)據(jù)乐横,重啟 mysql 數(shù)據(jù)庫求橄,又插入了一條數(shù)據(jù),此時 id 是幾葡公?
?表類型如果是 MyISAM 罐农,那 id 就是 8。
表類型如果是 InnoDB匾南,那 id 就是 6啃匿。
3.如何獲取當(dāng)前數(shù)據(jù)庫版本?
使用 select version() 獲取當(dāng)前 MySQL 數(shù)據(jù)庫版本。
select version()
4.說一下 ACID 是什么溯乒?事務(wù)的特性
?Atomicity(原子性):一個事務(wù)(transaction)中的所有操作夹厌,或者全部完成,或者全部不完成裆悄,不會結(jié)束在中間某個環(huán)節(jié)矛纹。事務(wù)在執(zhí)行過程中發(fā)生錯誤,會被恢復(fù)(Rollback)到事務(wù)開始前的狀態(tài)光稼,就像這個事務(wù)從來沒有執(zhí)行過一樣或南。即,事務(wù)不可分割艾君、不可約簡采够。
?Consistency(一致性):在事務(wù)開始之前和事務(wù)結(jié)束以后,數(shù)據(jù)庫的完整性沒有被破壞冰垄。這表示寫入的資料必須完全符合所有的預(yù)設(shè)約束蹬癌、觸發(fā)器、級聯(lián)回滾等虹茶。
?Isolation(隔離性):數(shù)據(jù)庫允許多個并發(fā)事務(wù)同時對其數(shù)據(jù)進行讀寫和修改的能力逝薪,隔離性可以防止多個事務(wù)并發(fā)執(zhí)行時由于交叉執(zhí)行而導(dǎo)致數(shù)據(jù)的不一致。事務(wù)隔離分為不同級別蝴罪,包括讀未提交(Read uncommitted)董济、讀提交(read committed)、可重復(fù)讀(repeatable read)和串行化(Serializable)要门。
?Durability(持久性):事務(wù)處理結(jié)束后虏肾,對數(shù)據(jù)的修改就是永久的,即便系統(tǒng)故障也不會丟失暂衡。
5.char 和 varchar 的區(qū)別是什么询微?
?char(n) :固定長度類型,比如訂閱 char(10)狂巢,當(dāng)你輸入"abc"三個字符的時候撑毛,它們占的空間還是 10 個字節(jié),其他 7 個是空字節(jié)唧领。
?chat 優(yōu)點:效率高藻雌;缺點:占用空間;適用場景:存儲密碼的 md5 值斩个,固定長度的胯杭,使用 char 非常合適。
?varchar(n) :可變長度受啥,存儲的值是每個值占用的字節(jié)再加上一個用來記錄其長度的字節(jié)的長度做个。
?所以鸽心,從空間上考慮 varcahr 比較合適;從效率上考慮 char 比較合適居暖,二者使用需要權(quán)衡
6.float 和 double 的區(qū)別是什么顽频?
?float 最多可以存儲 8 位的十進制數(shù),并在內(nèi)存中占 4 字節(jié)太闺。
double 最可可以存儲 16 位的十進制數(shù)糯景,并在內(nèi)存中占 8 字節(jié)。
7.mysql 的內(nèi)連接省骂、左連接蟀淮、右連接有什么區(qū)別?
內(nèi)連接關(guān)鍵字:inner join钞澳;左連接:left join怠惶;右連接:right join。 內(nèi)連接是把匹配的關(guān)聯(lián)數(shù)據(jù)顯示出來略贮;左連接是左邊的表全部顯示出來甚疟,右邊的表顯示出符合條件的數(shù)據(jù)仗岖;右連接正好相反
8.mysql 索引是怎么實現(xiàn)的逃延?
索引是滿足某種特定查找算法的數(shù)據(jù)結(jié)構(gòu),而這些數(shù)據(jù)結(jié)構(gòu)會以某種方式指向數(shù)據(jù)轧拄,從而實現(xiàn)高效查找數(shù)據(jù)揽祥。 具體來說 MySQL 中的索引,不同的數(shù)據(jù)引擎實現(xiàn)有所不同檩电,但目前主流的數(shù)據(jù)庫引擎的索引都是 B+ 樹實現(xiàn)的拄丰,B+ 樹的搜索效率,可以到達(dá)二分法的性能俐末,找到數(shù)據(jù)區(qū)域之后就找到了完整的數(shù)據(jù)結(jié)構(gòu)了料按,所有索引的性能也是更好的
9.怎么驗證 mysql 的索引是否滿足需求?
使用 explain 查看 SQL 是如何執(zhí)行查詢語句的卓箫,從而分析你的索引是否滿足需求载矿。
explain 語法:
explain select * from table where type=1
10.說一下數(shù)據(jù)庫的事務(wù)隔離?
MySQL 的事務(wù)隔離是在 MySQL. ini 配置文件里添加的烹卒,在文件的最后添加:
transaction-isolation = REPEATABLE-READ
可用的配置值:READ-UNCOMMITTED闷盔、READ-COMMITTED、REPEATABLE-READ旅急、SERIALIZABLE逢勾。
?READ-UNCOMMITTED:未提交讀,最低隔離級別藐吮、事務(wù)未提交前溺拱,就可被其他事務(wù)讀忍颖础(會出現(xiàn)幻讀、臟讀迫摔、不可重復(fù)讀)秋泳。
?READ-COMMITTED:提交讀,一個事務(wù)提交后才能被其他事務(wù)讀取到(會造成幻讀攒菠、不可重復(fù)讀)迫皱。
?REPEATABLE-READ:可重復(fù)讀,默認(rèn)級別辖众,保證多次讀取同一個數(shù)據(jù)時卓起,其值都和事務(wù)開始時候的內(nèi)容是一致,禁止讀取到別的事務(wù)未提交的數(shù)據(jù)(會造成幻讀)凹炸。
?SERIALIZABLE:序列化戏阅,代價最高最可靠的隔離級別,該隔離級別能防止臟讀啤它、不可重復(fù)讀奕筐、幻讀。
臟讀 :表示一個事務(wù)能夠讀取另一個事務(wù)中還未提交的數(shù)據(jù)变骡。比如离赫,某個事務(wù)嘗試插入記錄 A,此時該事務(wù)還未提交塌碌,然后另一個事務(wù)嘗試讀取到了記錄 A渊胸。
不可重復(fù)讀 :是指在一個事務(wù)內(nèi),多次讀同一數(shù)據(jù)台妆。
幻讀 :指同一個事務(wù)內(nèi)多次查詢返回的結(jié)果集不一樣翎猛。比如同一個事務(wù) A 第一次查詢時候有 n 條記錄,但是第二次同等條件下查詢卻有 n+1 條記錄接剩,這就好像產(chǎn)生了幻覺切厘。發(fā)生幻讀的原因也是另外一個事務(wù)新增或者刪除或者修改了第一個事務(wù)結(jié)果集里面的數(shù)據(jù),同一個記錄的數(shù)據(jù)內(nèi)容被修改了懊缺,所有數(shù)據(jù)行的記錄就變多或者變少了
11.說一下 mysql 常用的引擎疫稿?
?InnoDB 引擎:InnoDB 引擎提供了對數(shù)據(jù)庫 acid 事務(wù)的支持,并且還提供了行級鎖和外鍵的約束桐汤,它的設(shè)計的目標(biāo)就是處理大數(shù)據(jù)容量的數(shù)據(jù)庫系統(tǒng)而克。MySQL 運行的時候,InnoDB 會在內(nèi)存中建立緩沖池怔毛,用于緩沖數(shù)據(jù)和索引员萍。但是該引擎是不支持全文搜索,同時啟動也比較的慢拣度,它是不會保存表的行數(shù)的碎绎,所以當(dāng)進行 select count(*) from table 指令的時候螃壤,需要進行掃描全表。由于鎖的粒度小筋帖,寫操作是不會鎖定全表的,所以在并發(fā)度較高的場景下使用會提升效率
?MyIASM 引擎:MySQL 的默認(rèn)引擎奸晴,但不提供事務(wù)的支持,也不支持行級鎖和外鍵日麸。因此當(dāng)執(zhí)行插入和更新語句時寄啼,即執(zhí)行寫操作的時候需要鎖定這個表,所以會導(dǎo)致效率會降低代箭。不過和 InnoDB 不同的是墩划,MyIASM 引擎是保存了表的行數(shù),于是當(dāng)進行 select count(*) from table 語句時嗡综,可以直接的讀取已經(jīng)保存的值而不需要進行掃描全表乙帮。所以,如果表的讀操作遠(yuǎn)遠(yuǎn)多于寫操作時极景,并且不需要事務(wù)的支持的察净,可以將 MyIASM 作為數(shù)據(jù)庫引擎的首選
12.說一下 mysql 的行鎖和表鎖?
MyISAM 只支持表鎖盼樟,InnoDB 支持表鎖和行鎖氢卡,默認(rèn)為行鎖
?表級鎖:開銷小,加鎖快恤批,不會出現(xiàn)死鎖异吻。鎖定粒度大,發(fā)生鎖沖突的概率最高,并發(fā)量最低
?行級鎖:開銷大暴拄,加鎖慢绿鸣,會出現(xiàn)死鎖。鎖力度小纤房,發(fā)生鎖沖突的概率小,并發(fā)度最高
13.說一下樂觀鎖和悲觀鎖?
?樂觀鎖:每次去拿數(shù)據(jù)的時候都認(rèn)為別人不會修改晰房,所以不會上鎖,但是在提交更新的時候會判斷一下在此期間別人有沒有去更新這個數(shù)據(jù)
?悲觀鎖:每次去拿數(shù)據(jù)的時候都認(rèn)為別人會修改射沟,所以每次在拿數(shù)據(jù)的時候都會上鎖殊者,這樣別人想拿這個數(shù)據(jù)就會阻止,直到這個鎖被釋放
數(shù)據(jù)庫的樂觀鎖需要自己實現(xiàn)验夯,在表里面添加一個 version 字段猖吴,每次修改成功值加 1,這樣每次修改的時候先對比一下挥转,自己擁有的 version 和數(shù)據(jù)庫現(xiàn)在的 version 是否一致海蔽,如果不一致就不修改共屈,這樣就實現(xiàn)了樂觀鎖
14.mysql 問題排查都有哪些手段?
?使用 show processlist 命令查看當(dāng)前所有連接信息
?使用 explain 命令查詢 SQL 語句執(zhí)行計劃
?開啟慢查詢?nèi)罩镜炒埽榭绰樵兊?SQL
15.如何做 mysql 的性能優(yōu)化拗引?
?為搜索字段創(chuàng)建索引
?避免使用 select *,列出需要查詢的字段
?垂直分割分表
?選擇正確的存儲引擎
16.Mysql怎么保證持久性的幌衣?
OK矾削,是利用Innodb的redo log。
正如之前說的豁护,Mysql是先把磁盤上的數(shù)據(jù)加載到內(nèi)存中怔软,在內(nèi)存中對數(shù)據(jù)進行修改,再刷回磁盤上择镇。如果此時突然宕機挡逼,內(nèi)存中的數(shù)據(jù)就會丟失。
怎么解決這個問題腻豌?
簡單啊家坎,事務(wù)提交前直接把數(shù)據(jù)寫入磁盤就行啊。
這么做有什么問題吝梅?
只修改一個頁面里的一個字節(jié)虱疏,就要將整個頁面刷入磁盤,太浪費資源了苏携。畢竟一個頁面16kb大小做瞪,你只改其中一點點東西,就要將16kb的內(nèi)容刷入磁盤右冻,聽著也不合理装蓬。
畢竟一個事務(wù)里的SQL可能牽涉到多個數(shù)據(jù)頁的修改,而這些數(shù)據(jù)頁可能不是相鄰的纱扭,也就是屬于隨機IO牍帚。顯然操作隨機IO,速度會比較慢乳蛾。
于是暗赶,決定采用redo log解決上面的問題。當(dāng)做數(shù)據(jù)修改的時候肃叶,不僅在內(nèi)存中操作蹂随,還會在redo log中記錄這次操作。當(dāng)事務(wù)提交的時候因惭,會將redo log日志進行刷盤(redo log一部分在內(nèi)存中岳锁,一部分在磁盤上)。當(dāng)數(shù)據(jù)庫宕機重啟的時候筛欢,會將redo log中的內(nèi)容恢復(fù)到數(shù)據(jù)庫中浸锨,再根據(jù)undo log和binlog內(nèi)容決定回滾數(shù)據(jù)還是提交數(shù)據(jù)唇聘。
采用redo log的好處?
其實好處就是將redo log進行刷盤比對數(shù)據(jù)頁刷盤效率高柱搜,具體表現(xiàn)如下
redo log體積小迟郎,畢竟只記錄了哪一頁修改了啥,因此體積小聪蘸,刷盤快宪肖。
redo log是一直往末尾進行追加,屬于順序IO健爬。效率顯然比隨機IO來的快控乾。
ps:不想具體去談redo log具體長什么樣,因為內(nèi)容太多了娜遵。
問題四: Mysql怎么保證隔離性的蜕衡?
OK,利用的是鎖和MVCC機制。還是拿轉(zhuǎn)賬例子來說明设拟,有一個賬戶表如下
表名t_balance
其中id是主鍵慨仿,user_id為賬戶名,balance為余額纳胧。還是以轉(zhuǎn)賬兩次為例镰吆,如下圖所示
至于MVCC,即多版本并發(fā)控制(Multi Version Concurrency Control),一個行記錄數(shù)據(jù)有多個版本對快照數(shù)據(jù),這些快照數(shù)據(jù)在undo log中跑慕。
如果一個事務(wù)讀取的行正在做DELELE或者UPDATE操作万皿,讀取操作不會等行上的鎖釋放,而是讀取該行的快照版本核行。
由于MVCC機制在可重復(fù)讀(Repeateable Read)和讀已提交(Read Commited)的MVCC表現(xiàn)形式不同牢硅,就不贅述了。
但是有一點說明一下钮科,在事務(wù)隔離級別為讀已提交(Read Commited)時唤衫,一個事務(wù)能夠讀到另一個事務(wù)已經(jīng)提交的數(shù)據(jù),是不滿足隔離性的绵脯。但是當(dāng)事務(wù)隔離級別為可重復(fù)讀(Repeateable Read)中,是滿足隔離性的休里。
17.Mysql怎么保證一致性的蛆挫?
OK,這個問題分為兩個層面來說妙黍。
從數(shù)據(jù)庫層面悴侵,數(shù)據(jù)庫通過原子性、隔離性拭嫁、持久性來保證一致性可免。也就是說ACID四大特性之中抓于,C(一致性)是目的,A(原子性)浇借、I(隔離性)捉撮、D(持久性)是手段,是為了保證一致性妇垢,數(shù)據(jù)庫提供的手段巾遭。數(shù)據(jù)庫必須要實現(xiàn)AID三大特性,才有可能實現(xiàn)一致性闯估。例如灼舍,原子性無法保證,顯然一致性也無法保證涨薪。
但是骑素,如果你在事務(wù)里故意寫出違反約束的代碼,一致性還是無法保證的刚夺。例如献丑,你在轉(zhuǎn)賬的例子中,你的代碼里故意不給B賬戶加錢光督,那一致性還是無法保證阳距。因此,還必須從應(yīng)用層角度考慮结借。
從應(yīng)用層面筐摘,通過代碼判斷數(shù)據(jù)庫數(shù)據(jù)是否有效,然后決定回滾還是提交數(shù)據(jù)船老!
18.Mysql怎么保證原子性的咖熟?
OK,是利用Innodb的undo log柳畔。
undo log名為回滾日志馍管,是實現(xiàn)原子性的關(guān)鍵,當(dāng)事務(wù)回滾時能夠撤銷所有已經(jīng)成功執(zhí)行的sql語句薪韩,他需要記錄你要回滾的相應(yīng)日志信息确沸。
例如
(1)當(dāng)你delete一條數(shù)據(jù)的時候,就需要記錄這條數(shù)據(jù)的信息俘陷,回滾的時候罗捎,insert這條舊數(shù)據(jù)
(2)當(dāng)你update一條數(shù)據(jù)的時候,就需要記錄之前的舊值拉盾,回滾的時候桨菜,根據(jù)舊值執(zhí)行update操作
(3)當(dāng)年insert一條數(shù)據(jù)的時候,就需要這條記錄的主鍵,回滾的時候倒得,根據(jù)主鍵執(zhí)行delete操作
undo log記錄了這些回滾需要的信息泻红,當(dāng)事務(wù)執(zhí)行失敗或調(diào)用了rollback,導(dǎo)致事務(wù)需要回滾霞掺,便可以利用undo log中的信息將數(shù)據(jù)回滾到修改之前的樣子谊路。
ps:具體的undo log日志長啥樣,這個可以寫一篇文章了根悼。而且寫出來凶异,看的人也不多,姑且先這么簡單的理解吧挤巡。
19.MySQL剩彬、Redis、 MongoDB對比
MySQL
1.使用c和c++編寫矿卑,并使用了多種編譯器進行測試喉恋,保證源代碼的可移植性2.支持多種操作系統(tǒng)3.為多種編程語言提供可API4.支持多線程,充分利用CPU資源優(yōu)化的SQL查詢算法母廷,有效的提高查詢速度5.提供多語言支持轻黑,常見的編碼如: GB2312、 BIG5琴昆、 UTF8.提供TCP/IP氓鄙、ODBC和JDBC等多種數(shù)據(jù)庫連接途徑提供用于管理、檢查业舍、優(yōu)化數(shù)據(jù)庫操作的管理工具7.大型的數(shù)據(jù)庫抖拦。可以處理擁有上千萬條記錄的大型數(shù)據(jù)庫8.支持多種存儲引擎9. MySQL軟件采用了雙授權(quán)政策舷暮,分為社區(qū)版和商業(yè)版态罪,由于其體積小、速度快下面、總體擁有成本低复颈,尤其是開放源碼這一特點,一 般中小型網(wǎng)站的開發(fā) 都選擇MySQL作為網(wǎng)站數(shù)據(jù)庫10. MySQL使 用標(biāo)準(zhǔn)的SQL數(shù)據(jù)語言形式11. Mysql是 可以定制的沥割,采用GPL協(xié)議耗啦,你可以修改源碼來開發(fā)自己的MySQL系統(tǒng)12.在線DDL 更改功能13.復(fù)制全局事務(wù)標(biāo)識14.復(fù)制無崩潰從機15.復(fù)制多線程從機
Redis
1. Redis支持?jǐn)?shù)據(jù)的持久化,可以將內(nèi)存中的數(shù)據(jù)保存在磁盤中机杜,重啟的時候可以再次加載進行使用芹彬。2. Redis不僅僅支 持簡單的key-va lue類型的數(shù)據(jù),同時還提供list,set,在set,hash等數(shù)據(jù)結(jié)構(gòu)的存儲叉庐。3.Redis支 持?jǐn)?shù)據(jù)的備份,即mas ter-s lave模式的數(shù)據(jù)備份4.性能極高- Redis能讀的速度是10000次/s,寫的速度是81000次/s5.豐富的數(shù)據(jù)類型-Redis支持二進制案例的Strings, Lists, Hashes , Setes及OrderedSets數(shù)據(jù)類型操作会喝。6.原子一Redis的所有操作都是原子性的陡叠,同時Redis還支持對幾個操作全并后的原子性執(zhí)行玩郊。7.豐富的特性- Redis還 支持publish/subscribe,通知,key過 期等等特性枉阵。
MongoDB
1.模式自由:可以把不同結(jié)構(gòu)的文檔存儲在同-個數(shù)據(jù)庫里2.面向集合的存儲:適合存儲JSON風(fēng)格文件的形式3.完整的索引支持译红,對任何屬性可索引4.復(fù)制和高可用性:支持服務(wù)器之間的數(shù)據(jù)復(fù)制,支持主-從模式及服務(wù)器之間的相互復(fù)制兴溜。復(fù)制的主要目的是提供冗余及自動故障轉(zhuǎn)移5.自動分片:支持水平的數(shù)據(jù)庫集群侦厚,可動態(tài)添加額外的機器6.豐富的查詢:支持豐富的查詢表達(dá)方式,查詢指令使用JSON形式額標(biāo)記拙徽,可輕易查詢文檔中的內(nèi)嵌的對象及數(shù)組7.快速就地更新:查詢優(yōu)化器會分析查詢表達(dá)式刨沦,并生成一個高效的查詢計劃8.高效的傳統(tǒng)存儲方式:支持二進制數(shù)據(jù)及大型對象
MongoDB適用于
①網(wǎng)站數(shù)據(jù):適合實時的插入,更新與查詢膘怕,并具備網(wǎng)站實時數(shù)據(jù)存儲所需對的復(fù)制及高度伸縮性;②緩存:由于性能很高想诅,也適合作為信息基礎(chǔ)設(shè)施的緩存層,在系統(tǒng)重啟之后岛心,搭建的持久化緩存可以避免下層的數(shù)據(jù)源過載;③大尺寸来破、低價值的數(shù)據(jù)也是MongoDB的最佳選擇,使用傳統(tǒng)的關(guān)系數(shù)據(jù)庫存儲一些數(shù)據(jù)時 可能會比較貴忘古,再次之前很多程序員往往會選擇傳統(tǒng)的文件進行存儲④高伸縮的場景徘禁,非常是個由數(shù)十或者數(shù)百臺服務(wù)器組成的數(shù)據(jù)庫⑤用于對象及j son數(shù)據(jù)的存儲,MongoDB的bson數(shù)據(jù)格式非常適合文檔格式化的存儲及查詢髓堪。
而mysql還是更加適用于##
①高度事務(wù)性的系統(tǒng)送朱。例如銀行或者會計系統(tǒng),傳統(tǒng)的關(guān)系型數(shù)據(jù)庫目前還是更實用于需要大量原子性復(fù)雜事務(wù)的應(yīng)用程序
②傳統(tǒng)的商業(yè)智能應(yīng)用旦袋,針對特定問題的BI數(shù)據(jù)庫會對產(chǎn)生高度優(yōu)化的查詢方式骤菠,對于此類應(yīng)用,數(shù)據(jù)倉庫可能是更合適的選擇
Red is應(yīng)用場景:
1.用來做緩存-redis 的所有數(shù)據(jù)時放在內(nèi)存中的2.可以在某些特定應(yīng)用場景下替代傳統(tǒng)數(shù)據(jù)庫-比如社交類的應(yīng)用3.在一些大型系統(tǒng)中疤孕,巧妙的實現(xiàn)一些特定的功能: session共享商乎、購物車4. MongoDB不支持SQL語句
20.主鍵和唯一索引的區(qū)別?
? ? ? ? 在創(chuàng)建主鍵的同時會生成對應(yīng)的唯一索引祭阀,主鍵在保證數(shù)據(jù)唯一性的同時不允許為? ? ? ? 空鹉戚,而唯一可以有一個為空數(shù)據(jù)項,一個表中只能有一個主鍵专控,但是一個主鍵可以有多個字段抹凳,一個表中可以有多個唯一索引。
21.Preparedstatement和statement的區(qū)別?
? ? 用Prepared statement進行開發(fā)伦腐。Prepared statement是預(yù)編譯的赢底,而statement不是,在每次執(zhí)行sql語句的增刪改時,如果是一條數(shù)據(jù)兩者沒差距幸冻,但如果數(shù)據(jù)量大于1粹庞,那么每次執(zhí)行sql語句statement都要重新編譯一次,而Prepared statement不用洽损,Prepared statement的運行效率大于statement庞溜;從代碼的可維護性和可讀性來說,雖然用Prepared statement來代替statement會使代碼多出幾行碑定,但這樣的代碼無論從可讀性還是可維護性來說流码,都比直接使用statement的代碼高很多檔次;最重要的一點延刘,從安全角度來說漫试,使用Prepared statement可以大大提高程序的安全性,因為Prepared statement是用‘访娶?’傳參,可以防止sql注入商虐,具有安全性,而statement用的是‘+’字符串拼接崖疤,安全性較低秘车。
22.視圖概述
? ? ? 視圖可以視為“虛擬表”或“存儲的查詢”
? ? ? 創(chuàng)建視圖所依據(jù)的表稱為“基表”
? ? ? 視圖的優(yōu)點:
? ? ? 提供了另外一種級別的表安全性:隱藏了一些關(guān)鍵的字段
? ? ? 簡化的用戶的SQL命令
? ? ? 隔離基表結(jié)構(gòu)的改變
23.存儲過程概述
存儲過程(Stored Procedure)
可以包含邏輯判斷的sql語句集合。
是經(jīng)過預(yù)編譯劫哼,存在于數(shù)據(jù)庫中叮趴。
通過調(diào)用指定存儲過程的名字(可有參,可無參)來執(zhí)行权烧。
優(yōu)點:
簡化了復(fù)雜的業(yè)務(wù)邏輯眯亦,根據(jù)需要可重復(fù)使用
屏蔽了底層細(xì)節(jié),不暴露表信息即可完成操作
降低網(wǎng)絡(luò)的通信量般码,多條語句可以封裝成一個存儲過程來執(zhí)行
設(shè)置訪問權(quán)限來提高安全性
提高執(zhí)行效率妻率,因為它是預(yù)編譯以及存儲在數(shù)據(jù)庫中
缺點:
可移植性差,相同的存儲過程并不能跨多個數(shù)據(jù)庫進行操作
大量使用存儲過程后板祝,首先會使服務(wù)器壓力增大宫静,而且維護難度逐漸增加
存儲過程的語法:
--下面是在oracle數(shù)據(jù)庫下最基本的語法
--僅創(chuàng)建一個名為testProcedure 的無參的存儲過程
--IS也可以是AS
--如果已經(jīng)存在名為 testProcedure 的存儲過程,下面的語法會出現(xiàn) 名稱已被使用的錯誤
--解決辦法:
--第一句可以寫成 create or replace procedure testProcedure
--這樣會替換原有的存儲過程
--NULL表示任何可以正確執(zhí)行的sql 語句券时,但至少一句
create procedure testProcedure
IS
BEGIN
NULL
END;
存儲過程的參數(shù)的分類:
IN
OUT
INOUT
注意:
存儲過程之間可相互調(diào)用
存儲過程一般修改后孤里,立即生效。
24.索引概述
1.索引的概念
?索引就是為了提高數(shù)據(jù)的檢索速度橘洞。
數(shù)據(jù)庫的索引類似于書籍的索引捌袜。
在書籍中,索引允許用戶不必翻閱完整個書就能迅速地找到所需要的信息炸枣。
在數(shù)據(jù)庫中虏等,索引也允許數(shù)據(jù)庫程序迅速地找到表中的數(shù)據(jù)弄唧,而不必掃描整個數(shù)據(jù)庫.
2、索引的優(yōu)點
1.創(chuàng)建唯一性索引博其,保證數(shù)據(jù)庫表中每一行數(shù)據(jù)的唯一性
2.大大加快數(shù)據(jù)的檢索速度套才,這也是創(chuàng)建索引的最主要的原因
3.減少磁盤IO(向字典一樣可以直接定位)
3、索引的缺點
1.創(chuàng)建索引和維護索引要耗費時間慕淡,這種時間隨著數(shù)據(jù)量的增加而增加
2.索引需要占用額外的物理空間
3.當(dāng)對表中的數(shù)據(jù)進行增加、刪除和修改的時候沸毁,索引也要動態(tài)的維護峰髓,降低了數(shù)據(jù)的維護速度
4、索引的分類
1.普通索引和唯一性索引
? ? 普通索引:CREATE? INDEX mycolumn_index ON mytable (myclumn)
? ? 唯一性索引:保證在索引列中的全部數(shù)據(jù)是唯一的
? ? CREATE unique INDEX mycolumn_index ON mytable (myclumn)
? ? 2. 單個索引和復(fù)合索引
? ? 單個索引:對單個字段建立索引
? ? 復(fù)合索引:又叫組合索引息尺,在索引建立語句中同時包含多個字段名携兵,
? ? 最多16個字段
? ? CREATE INDEX name_index ON userInfo(firstname,lastname)
? ? 3.順序索引,散列索引,位圖索引
25.左連接,右連接搂誉,內(nèi)連接徐紧,外連接的區(qū)別?
內(nèi)連接也叫連接,是最早的一種連接炭懊。還可以被稱為普通連接或者自然連接并级,內(nèi)連接是從結(jié)果表中刪除與其他被連接表中沒有匹配行的所有行,所以內(nèi)連接可能會丟失信息侮腹。外連接分為三種:左外連接嘲碧,右外連接,全外連接父阻。其中左外連接:left join是以左表的記錄為基礎(chǔ)的,例如A可以看成左表,B可以看成右表,它的結(jié)果集是A表中的數(shù)據(jù)愈涩,再加上A表和B表匹配的數(shù)據(jù)。其中A表的記錄將會全部表示出來,而右表B只會顯示符合搜索條件的記錄加矛。B表記錄不足的地方均為NULL履婉。右外連接與左外連接正好相反。全連接則是左表和右表都不做限制斟览,所有的記錄都顯示毁腿,兩表不足的地方用null 填充
26.MySQL中in 和exsit區(qū)別?
exists()后面的子查詢被稱做相關(guān)子查詢??,他是不返回列表的值的.只是返回一個ture或false的結(jié)果(所以一般exists中的子查詢里寫成"select?? 1 "?? 當(dāng)然也可以select任何東西)?
其運行方式是先運行主查詢一次?趣惠,再去子查詢里查詢與其對應(yīng)的結(jié)果狸棍,如果是ture則輸出,反之則不輸出.再根據(jù)主查詢中的每一行去子查詢里去查詢.?in()后面的子查詢?? 是返回結(jié)果集的,換句話說執(zhí)行次序和exists()不一樣.子查詢先產(chǎn)生結(jié)果集,然后主查詢再去結(jié)果集里去找符合要求的字段列表去.符合要求的輸出,反之則不輸出.
27.數(shù)據(jù)庫查詢緩慢的常見原因以及優(yōu)化方法?
查詢速度慢的原因很多味悄,常見如下幾種:
(1)沒有索引或者沒有用到索引(這是查詢慢最常見的問題草戈,是程序設(shè)計的缺陷)
(2)I/O吞吐量小,形成了瓶頸效應(yīng)侍瑟。
(3)沒有創(chuàng)建計算列導(dǎo)致查詢不優(yōu)化唐片。
(4)內(nèi)存不足,網(wǎng)絡(luò)速度慢
(5)查詢出的數(shù)據(jù)量過大(可以采用多次查詢丙猬,其他的方法降低數(shù)據(jù)量)
(6)鎖或者死鎖(這也是查詢慢最常見的問題,是程序設(shè)計的缺陷)
(7)返回了不必要的行和列(8)查詢語句不好费韭,沒有優(yōu)化茧球。
可以通過如下方法來優(yōu)化查詢 :
(1)把數(shù)據(jù)、日志星持、索引放到不同的I/O設(shè)備上抢埋,增加讀取速度(
2)縱向、橫向分割表督暂,減少表的尺寸
(3)升級硬件
(4)根據(jù)查詢條件,建立索引,優(yōu)化索引揪垄、優(yōu)化訪問方式,限制結(jié)果集的數(shù)據(jù)量逻翁。
(5)DB Server 和APPLication Server 分離
(6)優(yōu)化SQL語句:1饥努、SELECT子句中避免使用 ‘ * ‘:? 2、用TRUNCATE替代DELETE:當(dāng)刪除表中的記錄時,在通常情況下, 回滾段(ROLLBACK SEGMENTS ) 用來存放可以被恢復(fù)的信息. 假如你沒有COMMIT事務(wù),ORACLE會將數(shù)據(jù)恢復(fù)到刪除之前的狀態(tài)(準(zhǔn)確地說是恢復(fù)到執(zhí)行刪除命令之前的狀況) 而當(dāng)運用TRUNCATE時, 回滾段不再存放任何可被恢復(fù)的信息.當(dāng)命令運行后,數(shù)據(jù)不能被恢復(fù).因此很少的資源被調(diào)用,執(zhí)行時間也會很短. (注意: TRUNCATE只在刪除全表適用,TRUNCATE是DDL不是DML)? 3八回、盡量多使用COMMIT:只要有可能,在程序中盡量多使用COMMIT, 這樣程序的性能得到提高,需求也會因為COMMIT所釋放的資源而減少 4酷愧、用Where子句替換HAVING子句 5、使用表的別名(Alias):? 當(dāng)在SQL語句中連接多個表時, 使用表的別名并把別名前綴于每個Column上.這樣一來,就可以減少解析的時間并減少那些由Column歧義引起的語法錯誤. 6缠诅、用EXISTS替代IN溶浴、用NOT EXISTS替代NOT IN:? 在許多基于基礎(chǔ)表的查詢中,為了滿足一個條件,往往需要對另一個表進行聯(lián)接.在這種情況下, 使用EXISTS(或NOT EXISTS)通常將提高查詢的效率. 在子查詢中,NOT IN子句將執(zhí)行一個內(nèi)部的排序和合并. 無論在哪種情況下,NOT IN都是最低效的 。 7滴铅、用EXISTS替換DISTINCT:? 8戳葵、SQL語句用大寫的? 因為Orale總是先解析SQL語句,把小寫的字母轉(zhuǎn)換成大寫的再執(zhí)行 9汉匙、避免在索引列上使用NOT: 10拱烁、用>=替代>? 11、用IN來替換OR? 12噩翠、避免在索引列上使用IS NULL和IS NOT NULL? 13戏自、總是使用索引的第一個列等
28.SQLServer和Oracle的區(qū)別是什么??
(1)數(shù)據(jù)類型不同伤锚。sql server 的數(shù)據(jù)類型:int ,smallint ,char,varchar,nchar,nvarchar,ntext,datetime,smalldatetime,money,decima,float,bit擅笔;oracle 的數(shù)據(jù)類型:number(p,s),char,varchar2,Date,LOB(2)獲得當(dāng)前系統(tǒng)時間的函數(shù)不同。(3)在oracle中沒有默認(rèn)約束的說法(4)連接變量和字符串的方式不一樣(5)oracle沒有identity自動增長列屯援,而是使用序列實現(xiàn)增長(6)條件語句if……else……的語法不同(7)case語句的語法不同(8)觸發(fā)器創(chuàng)建語法不同
29.Oracle數(shù)據(jù)庫怎樣刪除重復(fù)行,怎樣根據(jù)條件篩選數(shù)據(jù)?
? ? 1猛们、查找表中多余的重復(fù)記錄,重復(fù)記錄是根據(jù)單個字段(Id)來判斷 狞洋;
select * from 表 where Id in (select Id from 表 group byId having count(Id) > 1)
2弯淘、刪除表中多余的重復(fù)記錄,重復(fù)記錄是根據(jù)單個字段(Id)來判斷吉懊,只留有rowid最小的記錄庐橙;
DELETE from 表 WHERE (id) IN ( SELECT id FROM 表 GROUP BY id HAVING COUNT(id) > 1) AND ROWID NOT IN (SELECT MIN(ROWID) FROM 表 GROUP BY id HAVING COUNT(*) > 1);
3假勿、查找表中多余的重復(fù)記錄(多個字段);
select * from 表 a where (a.Id,a.seq) in(select Id,seq from 表 group by Id,seq having count(*) > 1)
4态鳖、刪除表中多余的重復(fù)記錄(多個字段)转培,只留有rowid最小的記錄;
delete from 表 a where (a.Id,a.seq) in (select Id,seq from 表 group by Id,seq having count(*) > 1) and rowid not in (select min(rowid) from 表 group by Id,seq having count(*)>1)
5浆竭、查找表中多余的重復(fù)記錄(多個字段)浸须,不包含rowid最小的記錄;
select * from 表 a where (a.Id,a.seq) in (select Id,seq from 表 group by Id,seq having count(*) > 1) and rowid not in (select min(rowid) from 表 group by Id,seq having count(*)>1)
30.數(shù)據(jù)庫中用什么關(guān)鍵字進行排序,升降序兆蕉,分組羽戒,分組后查詢?
Order by排序,order by 列 desc|asc降升序虎韵,group by分組,having分組后查詢
31.數(shù)據(jù)庫中常用術(shù)語:
ddl:數(shù)據(jù)定義語言 Create Drop Alter
dml:數(shù)據(jù)操縱語言 insert update delete select
dcl:數(shù)據(jù)控制語言 grant revoke
tcl:事務(wù)控制語言 commit rollback
32.Sql語句優(yōu)化部分:
1.我們項目組是不提倡使用存儲過程的缸废,因為我們之前的的后臺管理是.net 包蓝,之后數(shù)據(jù)量大的時候發(fā)現(xiàn)速度很慢,就打算改成java企量,而且數(shù)據(jù)庫的結(jié)構(gòu)也有一些變化测萎,看到.net那邊有很多的存儲過程,由于數(shù)據(jù)結(jié)構(gòu)的改變届巩,我們放棄了之前的存儲過程硅瞧,修改為代碼里sql去完成,因為存儲過程的移植性差恕汇,而且不易于維護腕唧。-->對于互聯(lián)網(wǎng)項目模型變更頻繁,用存儲過程局限性太強瘾英。而且分布式項目大量使用存儲過程后枣接,首先會使服務(wù)器壓力增大,數(shù)據(jù)庫多的話缺谴,只要有一個地方發(fā)生了修改但惶,那么其他的地方都要進行修改,這樣開發(fā)的效率反而低了湿蛔,而且容易出錯膀曾。
舉例:如果表中有個字段用的是clob或者是blob這種大數(shù)據(jù)字段的話,他們的查詢應(yīng)該根據(jù)需要來進行指定字段的查詢阳啥,切記勿直接用*
2.(重點) 刪除重復(fù)記錄(mysql):
3. 用 >= 替換>
? ? 如一個表有100萬記錄添谊,一個數(shù)值型字段A,
? ? ? A=0時苫纤,有30萬條碉钠;
? ? ? A=1時纲缓,有30萬條;
? ? ? A=2時喊废,有39萬條祝高;
? ? ? A=3時,有1萬記錄污筷。
? ? ? 那么執(zhí)行 A>2 與 A>=3 的效果就有很大的區(qū)別了工闺,因為 A>2 時,
? ? ? ORACLE會先找出為2的記錄索引再進行比較瓣蛀,
? ? ? 而A>=3時ORACLE則直接找到=3的記錄索引陆蟆。
4.(重點)盡量多使用COMMIT
如對大數(shù)據(jù)量的分段批量提交
5. (重點)用NOT EXISTS 或(外連接+判斷為空)方案 替換 NOT IN操作符
? ? 此操作是強列推薦不使用的,因為它不能應(yīng)用表的索引惋增。
? ? 推薦方案:用NOT EXISTS 或(外連接+判斷為空)方案代替
6.(重點 必須說)LIKE操作符(大數(shù)據(jù)的全文檢索使用luncene)(solr)
? ? 因為使用like不當(dāng)叠殷,會導(dǎo)致性能問題,原因是like在左右兩邊都有
? ? %的時候诈皿,不會使用索引林束。
? ? 如LIKE '%5400%' 這種查詢不會引用索引,
? ? 而LIKE 'X5400%' 則會引用范圍索引稽亏。
? ? 一個實際例子:
? ? 查詢營業(yè)編號 YY_BH LIKE '%5400%' 這個條件會產(chǎn)生全表掃描壶冒,
? ? 如果改成? ? ? ? YY_BH LIKE 'X5400%' OR YY_BH LIKE 'B5400%'
? ? 則會利用? ? YY_BH? 的索引進行兩個范圍的查詢,性能肯定大大提高截歉。
7.(重點,必須說)避免在索引列上使用計算和函數(shù),這樣索引就不能使用
? 舉例:
低效:SELECT … FROM? DEPT? WHERE SAL * 12 > 25000;
高效: SELECT … FROM DEPT WHERE SAL > 25000/12;
8.(重點 必須說)用UNION-ALL 替換UNION胖腾,
因為UNION-ALL不會過濾重復(fù)數(shù)據(jù)而且不會自動排序,所執(zhí)行效率要快于UNION瘪松。
9. (優(yōu)化,重點,3個方面 a.緩存 b.分段批量 c.存儲過程)減少訪問數(shù)據(jù)庫的次數(shù)
舉例:如果批量刪除多條數(shù)據(jù)咸作,可以用? delete? from tableName where id in (1,2,3)
?而不要用多條delete語句進行刪除
10.(重點 必須說)用 TRUNCATE 替代DELETE
TRUNCATE不記錄日志,DELETE記錄日志凉逛,所以TRUNCATE要快于DELETE
但是一旦用TRUNCATE進行刪除就不能進行恢復(fù),TRUNCATE是刪除整張表的數(shù)據(jù)不能加where條件性宏。
mysql,sqlserver中如果id為自增類型,那么如果用TRUNCATE刪除状飞,則id字段再插入數(shù)據(jù)時從1開始毫胜,如果delete刪除的話,則從刪除之前的id的值繼續(xù)增長诬辈。
33.防sql注入
? ? ? 針對防sql注入酵使,我們通常是這樣做的:
? ? ? ? ? 首先在前臺頁面對用戶輸入信息進行js驗證,對一些特殊字符進行屏蔽焙糟,
? 比如:or ,單引號口渔,--,= 穿撮,還有就是限制用戶名輸入的長度缺脉,我們一般將其限制在6---13位痪欲。另外,對于用戶的敏感信息我們進行Md5加密攻礼,還有 业踢,為了增加用戶體驗度和用戶友好度,為了不使用戶看到一些詳細(xì)的異常信息礁扮,我們會進行錯誤信息頁面的定制知举,像404,500錯誤。另一個我層面講太伊,這樣也是為了保護我們的一些重要信息雇锡。此外,我們會給特定的人分配定定的權(quán)限 僚焦,而不是給其分配管理員權(quán)限锰提!
33.存儲過程的優(yōu)缺點:
優(yōu)點:
簡化了復(fù)雜的業(yè)務(wù)邏輯,根據(jù)需要可重復(fù)使用
屏蔽了底層細(xì)節(jié)芳悲,不暴露表信息即可完成操作
降低網(wǎng)絡(luò)的通信量欲账,多條語句可以封裝成一個存儲過程來執(zhí)行
設(shè)置訪問權(quán)限來提高安全性
提高執(zhí)行效率,因為它是預(yù)編譯以及存儲在數(shù)據(jù)庫中
缺點:
可移植性差芭概,相同的存儲過程并不能跨多個數(shù)據(jù)庫進行操作
大量使用存儲過程后,首先會使服務(wù)器壓力增大惩嘉,而且維護難度逐漸增加
34.如何定位到有問題的sql?
當(dāng)程序運行慢的時候罢洲,我們會根據(jù)接口訪問的時間(這個我們是通過Aop實現(xiàn)的),定位到超時時間的接口文黎,然后分析接口的業(yè)務(wù)惹苗,如果接口的業(yè)務(wù)中有sql的話,在拿出相應(yīng)的sql做分析耸峭。若不是sql的問題桩蓉,而是數(shù)據(jù)的并發(fā)量導(dǎo)致數(shù)據(jù)庫慢的話,可以采用mysql的讀寫分離來解決劳闹,因為大多數(shù)的場景都是讀多院究,寫少的場景,這樣主庫的寫的壓力就會減輕很多本涕。如果是調(diào)用其他服務(wù)導(dǎo)致查詢變慢业汰,那么我們就通知他們調(diào)式接口。
35.MySQL 主從復(fù)制(讀寫分離)的原理和配置
1)主從復(fù)制解決了什么問題菩颖?
? ? 優(yōu)點:
? ? ????1.減輕主庫的壓力(因為一般的業(yè)務(wù)都是讀多寫少的样漆。讓寫的任務(wù)都落到主庫,讀的任務(wù)都落到從晦闰,這樣主庫的壓力就會減輕放祟,從而提高網(wǎng)站的吞吐量)
? ? ????2.數(shù)據(jù)備份
????缺點:
????????1.【異步復(fù)制】不一致時間窗口(會導(dǎo)致從庫查不到鳍怨,變更的數(shù)據(jù))
????????2.【同步復(fù)制】犧牲性能
2)注意點
? 1.master寫二進制日志,也是有事物跪妥,(和持久化到數(shù)據(jù)庫是同一個事物)
????主從復(fù)制的原理:
????????主從復(fù)制有三種類型:
????????????分為
?????????1.同步復(fù)制 【保證了數(shù)據(jù)的強一致性鞋喇,但是犧牲了性能,高并發(fā)不建議采用】
? ? ? ????????????master接受一個變更數(shù)據(jù)的請求(增骗奖,刪确徙,改),將變更的信息sql保存到自己的二進制日志中执桌,因為是同步復(fù)制鄙皇,所以要等到從庫同步過這條sql才給用戶返回成功
? ? ????2.異步復(fù)制(提高了性能,但是有可能看不到新變更的數(shù)據(jù))
? ? ? ? ? ? ? ? ? ?master接受一個變更數(shù)據(jù)的請求(增仰挣,刪伴逸,改),將變更的信息sql保存到自己的二進制日志中膘壶,就給用戶返回成功错蝴,之后從庫一個監(jiān)聽主庫二進制日志的線程,讀取到改變的sql,同步到從庫中繼日志中颓芭,然后由執(zhí)行sql的一個線程顷锰,執(zhí)行這個sql這樣從庫就有了這條數(shù)據(jù)。(但是有一個不一致時間段)
? ????? 3.半同步復(fù)制 (可以將同步復(fù)制的機器作為備機)
master接受一個變更數(shù)據(jù)的請求(增亡问,刪官紫,改),將變更的信息sql保存到自己的二進制日志中州藕,因為是半同步復(fù)制束世,所以要等到其中一個從庫同步過這條sql才給用戶返回成功,其他都是異步的同步的從庫中
36.你們項目sql是如何優(yōu)化的床玻?
? 我們?yōu)榱硕ㄎ坏接袉栴}的sql,我們的controller方法執(zhí)行時都回通過時間攔截器記錄方法執(zhí)行的時間毁涉。而且我們在安裝mysql服務(wù)器的時候都會開啟慢查詢,我們可以查看慢查詢的日志锈死,找到運行慢的sql, 然后可以利用mysql的執(zhí)行計劃Explain+sql 根據(jù)顯示的參數(shù)贫堰,來定位這條sql是否用到了全表掃描,在數(shù)據(jù)量大的情況下馅精,全表掃描會嚴(yán)重影響sql的效率严嗜。然后分析一下這個sql是否可以簡化(把* 修改為需要查詢的字段)窿克,或者是建立相關(guān)的索引扮叨,如果sql采用的是子查詢,我們盡量把他修改為連接查詢瞳遍,因為子查詢要創(chuàng)建臨時表和刪除臨時表,這樣的話會影響效率睦优。
如果在并發(fā)量大的時候渗常,只通過sql優(yōu)化是解決不了數(shù)據(jù)庫的壓力,因為大部分的場景都是讀多寫少的汗盘,這樣就可以采用mysql的讀寫分離皱碘。
在使用索引的過程中
?(1)在使用LIKE關(guān)鍵字進行查詢的查詢語句中,如果匹配字符串的第一個字符為“%”隐孽,索引不起作用癌椿。只有“%”不在第一個位置,索引才會生效菱阵,
? (2)OR前后的兩個條件中的列都是索引時踢俄,索引才會生效,否則晴及,索引不生效
(EXPLAIN SELECT * from t_product WHERE PRODUCT_CODE='PN201610120023';? # 0.012s --> 0.003)
(3)WHERE字句的查詢條件里有不等于號(WHERE column!=…)都办,MYSQL將無法使用索引
(4)如果WHERE字句的查詢條件里使用了函數(shù)(如:WHERE DAY(column)=…),MYSQL將無法使用索引
2.使用子查詢進行SELECT語句嵌套查詢虑稼,可以一次完成很多邏輯上需要多個步驟才能完成的SQL操作琳钉。
子查詢雖然很靈活,但是執(zhí)行效率并不高蛛倦。
執(zhí)行子查詢時歌懒,MYSQL需要創(chuàng)建臨時表,查詢完畢后再刪除這些臨時表溯壶,所以歼培,子查詢的速度會受到一定的影響。
EXPLAIN SELECT id,name,age from
(SELECT id,name,age from t_user WHERE age=19) b
WHERE b.age=19;
優(yōu)化:
可以使用連接查詢(JOIN)代替子查詢茸塞,連接查詢時不需要建立臨時表,其速度比子查詢快查剖。
未完待續(xù)钾虐。。笋庄。效扫。將不定時更新