1、數(shù)據(jù)庫(kù)存儲(chǔ)引擎
數(shù)據(jù)庫(kù)存儲(chǔ)引擎是數(shù)據(jù)庫(kù)底層軟件組織广凸,數(shù)據(jù)庫(kù)管理系統(tǒng)(DBMS)使用數(shù)據(jù)引擎進(jìn)行創(chuàng)建阅茶、查詢、更新和刪除數(shù)據(jù)谅海。不同的存儲(chǔ)引擎提供 不同的存儲(chǔ)機(jī)制脸哀、索引技巧、鎖定水平等功能扭吁,使用不同的存儲(chǔ)引擎撞蜂,還可以 獲得特定的功能∶は猓現(xiàn)在許多不同的數(shù)據(jù)庫(kù)管理系統(tǒng)都支持多種不同的數(shù)據(jù)引擎。存儲(chǔ)引擎主要有: 1. MyIsam , 2. InnoDB, 3. Memory, 4. Archive, 5. Federated 蝌诡。
InnoDB 底層存儲(chǔ)結(jié)構(gòu)為B+樹, B樹的每個(gè)節(jié)點(diǎn)對(duì)應(yīng)innodb的一個(gè)page浦旱, page大小是固定的宇色,一般設(shè)為 16k。其中非葉子節(jié)點(diǎn)只有鍵值颁湖, 葉子節(jié)點(diǎn)包含完成數(shù)據(jù)
適用場(chǎng)景:
經(jīng)常更新的表宣蠕,適合處理多重并發(fā)的更新請(qǐng)求。
支持事務(wù)爷狈。
可以從災(zāi)難中恢復(fù)(通過(guò) bin-log 日志等)植影。
外鍵約束。只有他支持外鍵涎永。
支持自動(dòng)增加列屬性 auto_increment思币。
2、TokuDB( Fractal Tree-節(jié)點(diǎn)帶數(shù)據(jù))
TokuDB 底層存儲(chǔ)結(jié)構(gòu)為 Fractal Tree,Fractal Tree 的結(jié)構(gòu)與 B+樹有些類似, 在 Fractal Tree中羡微, 每一個(gè) child 指針除了需要指向一個(gè) child
節(jié)點(diǎn)外谷饿,還會(huì)帶有一個(gè) Message Bu?er ,這個(gè)Message Bu?er 是一個(gè) FIFO 的隊(duì)列妈倔,用來(lái)緩存更新操作博投。
例如,一次插入操作只需要落在某節(jié)點(diǎn)的 Message Bu?er 就可以馬上返回了盯蝴,并不需要搜索到葉子節(jié)點(diǎn)毅哗。這些緩存的更新會(huì)在查詢時(shí)或后臺(tái)異步合并應(yīng)用到對(duì)應(yīng)的節(jié)點(diǎn)中。
TokuDB 在線添加索引捧挺,不影響讀寫操作, 非陈敲啵快的寫入性能, Fractal-tree 在事務(wù)實(shí)現(xiàn)上有優(yōu)勢(shì)闽烙。 他主要適用于訪問(wèn)頻率不高的數(shù)據(jù)或歷史數(shù)據(jù)歸檔
MyIASM是 MySQL默認(rèn)的引擎,但是它沒有提供對(duì)數(shù)據(jù)庫(kù)事務(wù)的支持黑竞,也不支持行級(jí)鎖和外鍵捕发,因此當(dāng) NSERT(插入)或 UPDATE(更新)數(shù)據(jù)時(shí)即寫操作需要鎖定整個(gè)表,效率便會(huì)低一些很魂。
ISAM 執(zhí)行讀取操作的速度很快扎酷,而且不占用大量的內(nèi)存和存儲(chǔ)資源。在設(shè)計(jì)之初就預(yù)想數(shù)據(jù)組織成有固定長(zhǎng)度的記錄遏匆,按順序存儲(chǔ)的霞玄。 —
ISAM 是一種靜態(tài)索引結(jié)構(gòu)骤铃。
缺點(diǎn)是它不 支持事務(wù)處理。
Memory(也叫 HEAP)堆內(nèi)存:使用存在內(nèi)存中的內(nèi)容來(lái)創(chuàng)建表。每個(gè) MEMORY 表只實(shí)際對(duì)應(yīng)一個(gè)磁盤文件喊暖。 MEMORY 類型的表訪問(wèn)非常得快惫企,因?yàn)樗臄?shù)據(jù)是放在內(nèi)存中的,并且默認(rèn)使用HASH 索引陵叽。但是一旦服務(wù)關(guān)閉狞尔,表中的數(shù)據(jù)就會(huì)丟失掉。 Memory 同時(shí)支持散列索引和 B 樹索引巩掺, B樹索引可以使用部分查詢和通配查詢偏序,也可以使用<,>和>=等操作符方便數(shù)據(jù)挖掘,散列索引相等的比較快但是對(duì)于范圍的比較慢很多
如何查看mysql提供的所有存儲(chǔ)引擎
mysql> show engines;
mysql常用引擎包括:MYISAM研儒、Innodb、Memory独令、MERGE
MYISAM:全表鎖端朵,擁有較高的執(zhí)行速度,不支持事務(wù)燃箭,不支持外鍵冲呢,并發(fā)性能差,占用空間相對(duì)較小招狸,對(duì)事務(wù)完整性沒有要求敬拓,以
select、insert為主的應(yīng)用基本上可以使用這引擎
Innodb:行級(jí)鎖裙戏,提供了具有提交乘凸、回滾和崩潰回復(fù)能力的事務(wù)安全,支持自動(dòng)增長(zhǎng)列挽懦,支持外鍵約束翰意,并發(fā)能力強(qiáng),占用空間是MYISAM的2.5倍信柿,處理效率相對(duì)會(huì)差一些
Memory:全表鎖冀偶,存儲(chǔ)在內(nèi)容中,速度快渔嚷,但會(huì)占用和數(shù)據(jù)量成正比的內(nèi)存空間且數(shù)據(jù)在mysql重啟時(shí)會(huì)丟失进鸠,默認(rèn)使用HASH索引, 檢索效率非常高形病,但不適用于精確查找客年,主要用于那些內(nèi)容變化不頻繁的代碼表
MERGE:是一組MYISAM表的組合
InnoDB支持事務(wù),MyISAM不支持量瓜,對(duì)于InnoDB每一條SQL語(yǔ)言都默認(rèn)封裝成事務(wù)司恳,自動(dòng)提交,這樣會(huì)影響速度绍傲,所以最好把多條
SQL語(yǔ)言放在begin和commit之間扔傅,組成一個(gè)事務(wù);
InnoDB支持外鍵烫饼,而MyISAM不支持猎塞。對(duì)一個(gè)包含外鍵的InnoDB表轉(zhuǎn)為MYISAM會(huì)失敗杠纵;
InnoDB是聚集索引荠耽,數(shù)據(jù)文件是和索引綁在一起的,必須要有主鍵比藻,通過(guò)主鍵索引效率很高铝量。但是輔助索引需要兩次查詢,先查詢到主鍵韩容,然后再通過(guò)主鍵查詢到數(shù)據(jù)款违。因此,主鍵不應(yīng)該過(guò)大群凶,因?yàn)橹麈I太大插爹,其他索引也都會(huì)很大。而MyISAM是非聚集索引请梢,數(shù)據(jù)文件是分離的赠尾,索引保存的是數(shù)據(jù)文件的指針。主鍵索引和輔助索引是獨(dú)立的毅弧。
InnoDB不保存表的具體行數(shù)气嫁,執(zhí)行select count(*) from table時(shí)需要全表掃描。而MyISAM用一個(gè)變量保存了整個(gè)表的行數(shù)够坐,執(zhí)行上述語(yǔ)句時(shí)只需要讀出該變量即可寸宵,速度很快;
Innodb不支持全文索引元咙,而MyISAM支持全文索引梯影,查詢效率上MyISAM要高
索引(Index)是幫助 MySQL 高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)庶香。 常見的查詢算法,順序查找,二分查找,二叉排序樹查找,哈希散列法,分塊查找,平衡多路搜索樹 B 樹(B-tree) 甲棍,索引是對(duì)數(shù)據(jù)庫(kù)表中一個(gè)或多個(gè)列的值進(jìn)行排序的結(jié)構(gòu),建立索引有助于快速獲取信息赶掖。
你也可以這樣理解:索引就是加快檢索表中數(shù)據(jù)的方法感猛。數(shù)據(jù)庫(kù)的索引類似于書籍的索引七扰。在書籍中,索引允許用戶不必翻閱完整個(gè)書就能迅速地找到所需要的信息陪白。在數(shù)據(jù)庫(kù)中颈走,索引也允許數(shù)據(jù)庫(kù)程序迅速地找到表中的數(shù)據(jù),而不必掃描整個(gè)數(shù)據(jù)庫(kù)
mysql 有4種不同的索引:
主鍵索引(PRIMARY)
唯一索引(UNIQUE)
普通索引(INDEX)
全文索引(FULLTEXT)
索引并非是越多越好咱士,創(chuàng)建索引也需要耗費(fèi)資源疫鹊,一是增加了數(shù)據(jù)庫(kù)的存儲(chǔ)空間,二是在插入和刪除時(shí)要花費(fèi)較多的時(shí)間維護(hù)索引
索引加快數(shù)據(jù)庫(kù)的檢索速度
索引降低了插入司致、刪除、修改等維護(hù)任務(wù)的速度唯一索引可以確保每一行數(shù)據(jù)的唯一性
通過(guò)使用索引聋迎,可以在查詢的過(guò)程中使用優(yōu)化隱藏器脂矫,提高系統(tǒng)的性能索引需要占物理和數(shù)據(jù)空間
選擇唯一性索引霉晕,唯一性索引的值是唯一的庭再,可以更快速的通過(guò)該索引來(lái)確定某條記錄。
為經(jīng)常需要排序牺堰、分組和聯(lián)合操作的字段建立索引拄轻。
為常用作為查詢條件的字段建立索引。
限制索引的數(shù)目:
越多的索引伟葫,會(huì)使更新表變得很浪費(fèi)時(shí)間恨搓。盡量使用數(shù)據(jù)量少的索引
如果索引的值很長(zhǎng),那么查詢的速度會(huì)受到影響筏养。盡量使用前綴來(lái)索引
如果索引字段的值很長(zhǎng)斧抱,最好使用值的前綴來(lái)索引。
刪除不再使用或者很少使用的索引
最左前綴匹配原則渐溶,非常重要的原則辉浦。
盡量選擇區(qū)分度高的列作為索引區(qū)分度的公式是表示字段不重復(fù)的比例
索引列不能參與計(jì)算,保持列“干凈”:帶函數(shù)的查詢不參與索引茎辐。
盡量的擴(kuò)展索引宪郊,不要新建索引
第一范式:列不可再分
第二范式:行可以唯一區(qū)分拖陆,主鍵約束
第三范式:表的非主屬性不能依賴與其他表的非主屬性 外鍵約束
且三大范式是一級(jí)一級(jí)依賴的弛槐,第二范式建立在第一范式上,第三范式建立第一第二范式上 慕蔚。
第一范式的目標(biāo)是確保每列的原子性:如果每列都是不可再分的最小數(shù)據(jù)單元(也稱為最小的原子單元),則滿足第一范式(1NF)
11孔飒、第二范式(2nd NF- 每個(gè)表只描述一件事情)
首先滿足第一范式灌闺,并且表中非主鍵列不存在對(duì)主鍵的部分依賴艰争。 第二范式要求每個(gè)表只描述一件事情。
12桂对、第三范式(3rd NF- 不存在對(duì)非主鍵列的傳遞依賴)
第三范式定義是甩卓,滿足第二范式,并且表中的列不存在對(duì)非主鍵列的傳遞依賴蕉斜。 除了主鍵訂單編號(hào)外逾柿,顧客姓名依賴于非主鍵顧客編號(hào)。
事務(wù)(TRANSACTION)是作為單個(gè)邏輯工作單元執(zhí)行的一系列操作机错, 這些操作作為一個(gè)整體一起向系統(tǒng)提交,要么都執(zhí)行父腕、要么都不執(zhí)行 弱匪。事務(wù)是一個(gè)不可分割的工作邏輯單元事務(wù)必須具備以下四個(gè)屬性,簡(jiǎn)稱 ACID 屬性:
原子性(Atomicity)
事務(wù)是一個(gè)完整的操作璧亮。事務(wù)的各步操作是不可分的(原子的)萧诫;要么都執(zhí)行,要么都不執(zhí)行枝嘶。
一致性(Consistency)
當(dāng)事務(wù)完成時(shí)帘饶,數(shù)據(jù)必須處于一致狀態(tài)。
隔離性(Isolation)
對(duì)數(shù)據(jù)進(jìn)行修改的所有并發(fā)事務(wù)是彼此隔離的群扶, 這表明事務(wù)必須是獨(dú)立的及刻,它不應(yīng)以任何方式依賴于或影響其他事務(wù)。
永久性(Durability)
事務(wù)完成后穷当,它對(duì)數(shù)據(jù)庫(kù)的修改被永久保持提茁,事務(wù)日志能夠保持事務(wù)的永久性
查詢語(yǔ)句中不要使用select *
盡量減少子查詢馁菜,使用關(guān)聯(lián)查詢(left join,right join,inner join)替代
減少使用IN或者NOT IN ,使用exists茴扁,not exists或者關(guān)聯(lián)查詢語(yǔ)句替代
or 的查詢盡量用 union或者union all 代替(在確認(rèn)沒有重復(fù)數(shù)據(jù)或者不用剔除重復(fù)數(shù)據(jù)時(shí),union all會(huì)更好)
應(yīng)盡量避免在 where 子句中使用!=或<>操作符汪疮,否則將引擎放棄使用索引而進(jìn)行全表掃描峭火。
應(yīng)盡量避免在 where 子句中對(duì)字段進(jìn)行 null 值判斷,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描智嚷,如: select id from t where num is null 可以在num上設(shè)置默認(rèn)值0卖丸,確保表中num列沒有null值,然后這樣查詢: select id from t where num=0
15盏道、簡(jiǎn)單說(shuō)一說(shuō)drop稍浆、delete與truncate的區(qū)別
SQL中的drop、delete、truncate都表示刪除衅枫,但是三者有一些差別
delete和truncate只刪除表的數(shù)據(jù)不刪除表的結(jié)構(gòu)速度,一般來(lái)說(shuō): drop> truncate >delete
delete語(yǔ)句是dml,這個(gè)操作會(huì)放到rollback segement中,事務(wù)提交之后才生效;
如果有相應(yīng)的trigger,執(zhí)行的時(shí)候?qū)⒈挥|發(fā). truncate,drop是ddl, 操作立即生效,原數(shù)據(jù)不放到rollbacksegment中,不能回滾. 操作不觸發(fā)
trigger
視圖是一種虛擬的表,具有和物理表相同的功能弦撩〔竭洌可以對(duì)視圖進(jìn)行增,改益楼,查猾漫,操作,試圖通常是有一個(gè)表或者多個(gè)表的行或列的子集感凤。對(duì)視圖的修改不影響基本表悯周。它使得我們獲取數(shù)據(jù)更容易,相比多表查詢
17陪竿、什么是內(nèi)聯(lián)接队橙、左外聯(lián)接、右外聯(lián)接萨惑?
內(nèi)聯(lián)接(Inner Join):匹配2張表中相關(guān)聯(lián)的記錄。
左外聯(lián)接(Left Outer Join):除了匹配2張表中相關(guān)聯(lián)的記錄外仇矾,還會(huì)匹配左表中剩余的記錄庸蔼,右表中未匹配到的字段用NULL表示。
右外聯(lián)接(Right Outer Join):除了匹配2張表中相關(guān)聯(lián)的記錄外贮匕,還會(huì)匹配右表中剩余的記錄姐仅,左表中未匹配到的字段用NULL表示。在判定左表和右表時(shí)刻盐,要根據(jù)表名出現(xiàn)在Outer Join的左右位置關(guān)系
18掏膏、并發(fā)事務(wù)帶來(lái)哪些問(wèn)題?
在典型的應(yīng)用程序中,多個(gè)事務(wù)并發(fā)運(yùn)行敦锌,經(jīng)常會(huì)操作相同的數(shù)據(jù)來(lái)完成各自的任務(wù)(多個(gè)用戶對(duì)同一數(shù)據(jù)進(jìn)行操作)馒疹。并發(fā)雖然是必須的,但可能會(huì)導(dǎo)致以下的問(wèn)題乙墙。
臟讀(Dirty read):?當(dāng)一個(gè)事務(wù)正在訪問(wèn)數(shù)據(jù)并且對(duì)數(shù)據(jù)進(jìn)行了修改颖变,而這種修改還沒有提交到數(shù)據(jù)庫(kù)中,這時(shí)另外一個(gè)事務(wù)也訪問(wèn)了這個(gè)數(shù)據(jù)听想,然后使用了這個(gè)數(shù)據(jù)腥刹。因?yàn)檫@個(gè)數(shù)據(jù)是還沒有提交的數(shù)據(jù),那么另外一個(gè)事務(wù)讀到的這個(gè)數(shù)據(jù)是“臟數(shù)據(jù)”汉买,依據(jù)“臟數(shù)據(jù)”所做的操作可能是不正確的衔峰。
丟失修改(Lost to modify):?指在一個(gè)事務(wù)讀取一個(gè)數(shù)據(jù)時(shí),另外一個(gè)事務(wù)也訪問(wèn)了該數(shù)據(jù),那么在第一個(gè)事務(wù)中修改了這個(gè)數(shù)據(jù)后垫卤,第二個(gè)事務(wù)也修改了這個(gè)數(shù)據(jù)威彰。這樣第一個(gè)事務(wù)內(nèi)的修改結(jié)果就被丟失,因此稱為丟失修葫男。 例如:事務(wù)1讀取某表中的數(shù)據(jù)A=20抱冷,事務(wù)2也讀取A=20,事務(wù)1修改A=A-1梢褐,事務(wù)2也修改A=A-1旺遮,最終結(jié)果A=19,事務(wù)1的修改被丟失盈咳。
不可重復(fù)讀(Unrepeatableread):?指在一個(gè)事務(wù)內(nèi)多次讀同一數(shù)據(jù)耿眉。在這個(gè)事務(wù)還沒有結(jié)束時(shí),另一個(gè)事務(wù)也訪問(wèn)該數(shù)據(jù)鱼响。那么鸣剪,在第一個(gè)事務(wù)中的兩次讀數(shù)據(jù)之間,由于第二個(gè)事務(wù)的修改導(dǎo)致第一個(gè)事務(wù)兩次讀取的數(shù)據(jù)可能不太一樣丈积。這就發(fā)生了在一個(gè)事務(wù)內(nèi)兩次讀到的數(shù)據(jù)是不一樣的情況筐骇,因此稱為不可重復(fù)讀。
幻讀(Phantom read):?幻讀與不可重復(fù)讀類似江滨。它發(fā)生在一個(gè)事務(wù)(T1)讀取了幾行數(shù)據(jù)铛纬,接著另一個(gè)并發(fā)事務(wù)(T2)插入了一些數(shù)據(jù)時(shí)。在隨后的查詢中唬滑,第一個(gè)事務(wù)(T1)就會(huì)發(fā)現(xiàn)多了一些原本不存在的記錄告唆,就好像發(fā)生了幻覺一樣,所以稱為幻讀晶密。
不可重復(fù)讀和幻讀區(qū)別:
不可重復(fù)讀的重點(diǎn)是修改比如多次讀取一條記錄發(fā)現(xiàn)其中某些列的值被修改擒悬,幻讀的重點(diǎn)在于新增或者刪除比如多次讀取一條記錄發(fā)現(xiàn)記錄增多或減少了
19、事務(wù)隔離級(jí)別有哪些?MySQL的默認(rèn)隔離級(jí)別是?
SQL 標(biāo)準(zhǔn)定義了四個(gè)隔離級(jí)別:
READ-UNCOMMITTED(讀取未提交):?最低的隔離級(jí)別稻艰,允許讀取尚未提交的數(shù)據(jù)變更懂牧,可能會(huì)導(dǎo)致臟讀、幻讀或不可重復(fù)讀尊勿。
READ-COMMITTED(讀取已提交):?允許讀取并發(fā)事務(wù)已經(jīng)提交的數(shù)據(jù)归苍,可以阻止臟讀,但是幻讀或不可重復(fù)讀仍有可能發(fā)生运怖。
REPEATABLE-READ(可重復(fù)讀):?對(duì)同一字段的多次讀取結(jié)果都是一致的拼弃,除非數(shù)據(jù)是被本身事務(wù)自己所修改,可以阻止臟讀和不可重復(fù)讀摇展,但幻讀仍有可能發(fā)生
SERIALIZABLE(可串行化):?最高的隔離級(jí)別吻氧,完全服從ACID的隔離級(jí)別。所有的事務(wù)依次逐個(gè)執(zhí)行,這樣事務(wù)之間就完全不可能產(chǎn)生干擾盯孙,也就是說(shuō)鲁森,該級(jí)別可以防止臟讀、不可重復(fù)讀以及幻讀
MySQL InnoDB 存儲(chǔ)引擎的默認(rèn)支持的隔離級(jí)別是 REPEATABLE-READ(可重讀)振惰。我們可以通過(guò)SELECT @@tx_isolation; 命令來(lái)查看
mysql>SELECT@@tx_isolation;+-----------------+|@@tx_isolation|+-----------------+|REPEATABLE-READ|+-----------------+
這里需要注意的是:與 SQL 標(biāo)準(zhǔn)不同的地方在于 InnoDB 存儲(chǔ)引擎在 REPEATABLE-READ(可重讀)事務(wù)隔離級(jí)別下使用的是Next-Key
Lock 鎖算法歌溉,因此可以避免幻讀的產(chǎn)生,這與其他數(shù)據(jù)庫(kù)系統(tǒng)(如SQL Server) 是不同的骑晶。所以說(shuō)InnoDB 存儲(chǔ)引擎的默認(rèn)支持的隔離級(jí)別是REPEATABLE-READ(可重讀) 已經(jīng)可以完全保證事務(wù)的隔離性要求痛垛,即達(dá)到了 SQL標(biāo)準(zhǔn)的 SERIALIZABLE(可串行化) 隔離級(jí)別。因?yàn)楦綦x級(jí)別越低桶蛔,事務(wù)請(qǐng)求的鎖越少匙头,所以大部分?jǐn)?shù)據(jù)庫(kù)系統(tǒng)的隔離級(jí)別都是 READCOMMITTED(讀取提交內(nèi)容) ,但是你要知道的是InnoDB 存儲(chǔ)引擎默認(rèn)使用 REPEAaTABLEREAD(可重讀) 并不會(huì)有任何性能損失
InnoDB 存儲(chǔ)引擎在 分布式事務(wù) 的情況下一般會(huì)用到 SERIALIZABLE(可串行化) 隔離級(jí)別仔雷。
當(dāng)MySQL單表記錄數(shù)過(guò)大時(shí)碟婆,數(shù)據(jù)庫(kù)的CRUD性能會(huì)明顯下降电抚,一些常見的優(yōu)化措施如下:
限定數(shù)據(jù)的范圍
務(wù)必禁止不帶任何限制數(shù)據(jù)范圍條件的查詢語(yǔ)句。比如:我們當(dāng)用戶在查詢訂單歷史的時(shí)候竖共,我們可以控制在一個(gè)月的范圍內(nèi)喻频;
讀/寫分離
經(jīng)典的數(shù)據(jù)庫(kù)拆分方案,主庫(kù)負(fù)責(zé)寫肘迎,從庫(kù)負(fù)責(zé)讀;
垂直分區(qū)
根據(jù)數(shù)據(jù)庫(kù)里面數(shù)據(jù)表的相關(guān)性進(jìn)行拆分锻煌。 例如妓布,用戶表中既有用戶的登錄信息又有用戶的基本信息,可以將用戶表拆分成兩個(gè)單獨(dú)的表宋梧,甚至放到單獨(dú)的庫(kù)做分庫(kù)匣沼。
簡(jiǎn)單來(lái)說(shuō)垂直拆分是指數(shù)據(jù)表列的拆分,把一張列比較多的表拆分為多張表捂龄。 如下圖所示释涛,這樣來(lái)說(shuō)大家應(yīng)該就更容易理解了
垂直拆分的優(yōu)點(diǎn):?可以使得列數(shù)據(jù)變小,在查詢時(shí)減少讀取的Block數(shù)倦沧,減少I/O次數(shù)唇撬。此外,垂直分區(qū)可以簡(jiǎn)化表的結(jié)構(gòu)展融,易于維護(hù)窖认。
垂直拆分的缺點(diǎn):?主鍵會(huì)出現(xiàn)冗余,需要管理冗余列,并會(huì)引起Join操作扑浸,可以通過(guò)在應(yīng)用層進(jìn)行
Join來(lái)解決烧给。此外,垂直分區(qū)會(huì)讓事務(wù)變得更加復(fù)雜喝噪;
保持?jǐn)?shù)據(jù)表結(jié)構(gòu)不變,通過(guò)某種策略存儲(chǔ)數(shù)據(jù)分片酝惧。這樣每一片數(shù)據(jù)分散到不同的表或者庫(kù)中榴鼎,達(dá)到了分布式的目的。 水平拆分可以支撐非常大的數(shù)據(jù)量系奉。
水平拆分是指數(shù)據(jù)表行的拆分檬贰,表的行數(shù)超過(guò)200萬(wàn)行時(shí),就會(huì)變慢缺亮,這時(shí)可以把一張的表的數(shù)據(jù)拆成多張表來(lái)存放翁涤。舉個(gè)例子:我們可以將用戶信息表拆分成多個(gè)用戶信息表,這樣就可以避免單一表數(shù)據(jù)量過(guò)大對(duì)性能造成影響萌踱。
水平拆分可以支持非常大的數(shù)據(jù)量葵礼。需要注意的一點(diǎn)是:分表僅僅是解決了單一表數(shù)據(jù)過(guò)大的問(wèn)題,但由于表的數(shù)據(jù)還是在同一臺(tái)機(jī)器上并鸵, 其實(shí)對(duì)于提升MySQL并發(fā)能力沒有什么意義鸳粉,所以 水平拆分最好分庫(kù) 。
水平拆分能夠 支持非常大的數(shù)據(jù)量存儲(chǔ)园担,應(yīng)用端改造也少届谈,但 分片事務(wù)難以解決 ,跨節(jié)點(diǎn)Join性能較差弯汰,邏輯復(fù)雜艰山。《Java工程師修煉之道》的作者推薦 盡量不要對(duì)數(shù)據(jù)進(jìn)行分片咏闪,因?yàn)椴鸱謺?huì)帶來(lái)邏輯曙搬、部署、運(yùn)維的各種復(fù)雜度 鸽嫂,一般的數(shù)據(jù)表在優(yōu)化得當(dāng)?shù)那闆r下支撐千萬(wàn)以下的數(shù)據(jù)量是沒有太大問(wèn)題的纵装。如果實(shí)在要分片,盡量選擇客戶端分片架構(gòu)据某,這樣可以減少一次和中間件的網(wǎng)絡(luò)I/O橡娄。
下面補(bǔ)充一下數(shù)據(jù)庫(kù)分片的兩種常見方案:
客戶端代理: 分片邏輯在應(yīng)用端,封裝在jar包中癣籽,通過(guò)修改或者封裝JDBC層來(lái)實(shí)現(xiàn)瀑踢。 當(dāng)當(dāng)網(wǎng)的Sharding-JDBC 扳还、阿里的TDDL是兩種比較常用的實(shí)現(xiàn)。
中間件代理: 在應(yīng)用和數(shù)據(jù)中間加了一個(gè)代理層橱夭。分片邏輯統(tǒng)一維護(hù)在中間件服務(wù)中氨距。 我們現(xiàn)在談的 Mycat 、360的Atlas棘劣、網(wǎng)易的DDB等等都是這種架構(gòu)的實(shí)現(xiàn)俏让。
詳細(xì)內(nèi)容可以參考: MySQL大表優(yōu)化方案: https://segmentfault.com/a/1190000006158186
因?yàn)橐欠殖啥鄠€(gè)表之后茬暇,每個(gè)表都是從 1 開始累加首昔,這樣是不對(duì)的,我們需要一個(gè)全局唯一的 id 來(lái)支持糙俗。
生成全局 id 有下面這幾種方式:
UUID:?不適合作為主鍵勒奇,因?yàn)樘L(zhǎng)了,并且無(wú)序不可讀巧骚,查詢效率低赊颠。比較適合用于生成唯一的名字的標(biāo)示比如文件的名字。
數(shù)據(jù)庫(kù)自增 id :?兩臺(tái)數(shù)據(jù)庫(kù)分別設(shè)置不同步長(zhǎng)劈彪,生成不重復(fù)ID的策略來(lái)實(shí)現(xiàn)高可用竣蹦。這種方式生成的 id 有序,但是需要獨(dú)立部署數(shù)據(jù)庫(kù)實(shí)例沧奴,成本高痘括,還會(huì)有性能瓶頸。
利用 redis 生成 id : 性能比較好滔吠,靈活方便纲菌,不依賴于數(shù)據(jù)庫(kù)。但是疮绷,引入了新的組件造成系統(tǒng)更加復(fù)雜翰舌,可用性降低,編碼更加復(fù)雜矗愧,增加了系統(tǒng)成本。
Twitter的snow?ake算法:?Github 地址:https://github.com/twitter-archive/snow?ake郑原。
美團(tuán)的Leaf分布式ID生成系統(tǒng) :Leaf 是美團(tuán)開源的分布式ID生成器唉韭,能保證全局唯一性、趨勢(shì)遞增犯犁、單調(diào)遞增属愤、信息安全,里面也提到了幾種分布式方案的對(duì)比酸役,但也需要依賴關(guān)系數(shù)據(jù)庫(kù)住诸、Zookeeper等中間件驾胆。感覺還不錯(cuò)。美團(tuán)技術(shù)團(tuán)隊(duì)的一篇文章:https://tech.meituan. com/2017/04/21/mt-leaf.html
23贱呐、存儲(chǔ)過(guò)程(特定功能的 SQL 語(yǔ)句集)
一組為了完成特定功能的 SQL 語(yǔ)句集丧诺,存儲(chǔ)在數(shù)據(jù)庫(kù)中,經(jīng)過(guò)第一次編譯后再次調(diào)用不需要再次編譯奄薇,用戶通過(guò)指定存儲(chǔ)過(guò)程的名字并給出參數(shù)(如果該存儲(chǔ)過(guò)程帶有參數(shù))來(lái)執(zhí)行它驳阎。存儲(chǔ)過(guò)程是數(shù)據(jù)庫(kù)中的一個(gè)重要對(duì)象。
盡量利用一些 sql 語(yǔ)句來(lái)替代一些小循環(huán)呵晚,例如聚合函數(shù),求平均函數(shù)等沫屡。
中間結(jié)果存放于臨時(shí)表饵隙,加索引。
少使用游標(biāo)沮脖。 sql 是個(gè)集合語(yǔ)言金矛,對(duì)于集合運(yùn)算具有較高性能。而 cursors 是過(guò)程運(yùn)算倘潜。比如對(duì)一個(gè) 100 萬(wàn)行的數(shù)據(jù)進(jìn)行查詢绷柒。游標(biāo)需要讀表 100 萬(wàn)次,而不使用游標(biāo)則只需要少量幾次讀取涮因。
事務(wù)越短越好废睦。 sqlserver 支持并發(fā)操作。如果事務(wù)過(guò)多過(guò)長(zhǎng)养泡,或者隔離級(jí)別過(guò)高嗜湃,都會(huì)造成并發(fā)操作的阻塞,死鎖澜掩。導(dǎo)致查詢極慢购披,cpu 占用率極地。
使用 try-catch 處理錯(cuò)誤異常肩榕。
查找語(yǔ)句盡量不要放在循環(huán)內(nèi)
25刚陡、觸發(fā)器(一段能自動(dòng)執(zhí)行的程序)
觸發(fā)器是一段能自動(dòng)執(zhí)行的程序,是一種特殊的存儲(chǔ)過(guò)程株汉, 觸發(fā)器和普通的存儲(chǔ)過(guò)程的區(qū)別是:觸發(fā)器是當(dāng)對(duì)某一個(gè)表進(jìn)行操作時(shí)觸發(fā)筐乳。諸如: update、 insert乔妈、 delete 這些操作的時(shí)候蝙云,系統(tǒng)會(huì)自動(dòng)調(diào)用執(zhí)行該表上對(duì)應(yīng)的觸發(fā)器。 SQL Server 2005 中觸發(fā)器可以分為兩類:
DML 觸發(fā)器和DDL 觸發(fā)器路召,其中 DDL 觸發(fā)器它們會(huì)影響多種數(shù)據(jù)定義語(yǔ)言語(yǔ)句而激發(fā)勃刨,這些語(yǔ)句有 create波材、alter、 drop 語(yǔ)句身隐。
并發(fā)控制一般采用三種方法,分別是樂(lè)觀鎖和悲觀鎖以及時(shí)間戳抡医。
表級(jí)鎖:開銷小忌傻,加鎖快大脉;不會(huì)出現(xiàn)死鎖;鎖定粒度大水孩,發(fā)生鎖沖突的概率最高镰矿,并發(fā)度最低。
行級(jí)鎖:開銷大俘种,加鎖慢秤标;會(huì)出現(xiàn)死鎖;鎖定粒度最小宙刘,發(fā)生鎖沖突的概率最低苍姜,并發(fā)度也最高。
頁(yè)面鎖:開銷和加鎖時(shí)間界于表鎖和行鎖之間悬包;會(huì)出現(xiàn)死鎖衙猪;鎖定粒度界于表鎖和行鎖之間,并發(fā)度一般
共有 5 種類型的表格:
MyISAM
Heap
Merge
INNODB
ISAM
29、簡(jiǎn)述在 MySQL 數(shù)據(jù)庫(kù)中 MyISAM 和 InnoDB 的區(qū)別
MyISAM:
不支持事務(wù)撑瞧,但是每次查詢都是原子的棵譬; 支持表級(jí)鎖,即每次操作是對(duì)整個(gè)表加鎖预伺; 存儲(chǔ)表的總行數(shù)订咸;
一個(gè) MYISAM 表有三個(gè)文件:索引文件、表結(jié)構(gòu)文件酬诀、數(shù)據(jù)文件脏嚷;
采用菲聚集索引,索引文件的數(shù)據(jù)域存儲(chǔ)指向數(shù)據(jù)文件的指針料滥。輔索引與主索引基本一致然眼,但是輔索引不用保證唯一性艾船。
InnoDb:
支持 ACID 的事務(wù)葵腹,支持事務(wù)的四種隔離級(jí)別高每; 支持行級(jí)鎖及外鍵約束:因此可以支持寫并發(fā);
不存儲(chǔ)總行數(shù):
一個(gè) InnoDb 引擎存儲(chǔ)在一個(gè)文件空間(共享表空間践宴,表大小不受操作系統(tǒng)控制鲸匿,一個(gè)表可能分布在多個(gè)文件里),也有可能為多個(gè)(設(shè)置為獨(dú)立表空阻肩,表大小受操作系統(tǒng)文件大小限制带欢,一般為 2G),受操作系統(tǒng)文件大小的限制瑰抵;
主鍵索引采用聚集索引(索引的數(shù)據(jù)域存儲(chǔ)數(shù)據(jù)文件本身)茎匠,輔索引的數(shù)據(jù)域存儲(chǔ)主鍵的值啸罢;因此從輔索引查找數(shù)據(jù),需要先通過(guò)輔索引找到主鍵值渡贾,再訪問(wèn)輔索引;最好使用自增主鍵雄右,防止插入數(shù)據(jù)時(shí)空骚,為維持 B+樹結(jié)構(gòu),文件的大調(diào)整擂仍。
30囤屹、MySQL 中 InnoDB 支持的四種事務(wù)隔離級(jí)別名稱,以及逐級(jí)之間的區(qū)別逢渔?
SQL 標(biāo)準(zhǔn)定義的四個(gè)隔離級(jí)別為:
read uncommited :讀到未提交數(shù)據(jù)
read committed:臟讀肋坚,不可重復(fù)讀
repeatable read: 可 重 讀
serializable :串行事物
CHAR 和 VARCHAR 類型在存儲(chǔ)和檢索方面有所不同
CHAR 列長(zhǎng)度固定為創(chuàng)建表時(shí)聲明的長(zhǎng)度冲簿,長(zhǎng)度值范圍是 1 到 255 當(dāng) CHAR值被存儲(chǔ)時(shí),它們被用空格填充到特定長(zhǎng)度亿昏,檢索 CHAR 值時(shí)需刪除尾隨空格峦剔。
表格的每一行都由主鍵唯一標(biāo)識(shí),一個(gè)表只有一個(gè)主鍵吝沫。
主鍵也是候選鍵。按照慣例递礼,候選鍵可以被指定為主鍵惨险,并且可以用于任何外鍵引用。
33脊髓、myisamchk 是用來(lái)做什么的辫愉?
它用來(lái)壓縮 MyISAM 表,這減少了磁盤或內(nèi)存使用将硝。
34恭朗、MyISAM Static 和 MyISAM Dynamic 有什么區(qū)別屏镊?
在 MyISAM Static 上的所有字段有固定寬度。動(dòng)態(tài) MyISAM 表將具有像 TEXT痰腮,BLOB 等字段而芥,以適應(yīng)不同長(zhǎng)度的數(shù)據(jù)類型。
MyISAM Static 在受損情況下更容易恢復(fù)膀值。
35棍丐、如果一個(gè)表有一列定義為 TIMESTAMP,將發(fā)生什么沧踏?
每當(dāng)行被更改時(shí)歌逢,時(shí)間戳字段將獲取當(dāng)前時(shí)間戳。
列設(shè)置為 AUTO INCREMENT 時(shí)翘狱,如果在表中達(dá)到最大值趋翻,會(huì)發(fā)生什么情況?
它會(huì)停止遞增盒蟆,任何進(jìn)一步的插入都將產(chǎn)生錯(cuò)誤踏烙,因?yàn)槊荑€已被使用。
怎樣才能找出最后一次插入時(shí)分配了哪個(gè)自動(dòng)增量历等?
LAST_INSERT_ID 將返回由 Auto_increment 分配的最后一個(gè)值讨惩,并且不需要指定表名稱
索引是通過(guò)以下方式為表格定義的:
SHOW INDEX FROM ;
%對(duì)應(yīng)于 0 個(gè)或更多字符寡夹,_只是 LIKE 語(yǔ)句中的一個(gè)字符
如何在 Unix 和 MySQL 時(shí)間戳之間進(jìn)行轉(zhuǎn)換处面?
UNIX_TIMESTAMP 是從 MySQL 時(shí)間戳轉(zhuǎn)換為 Unix 時(shí)間戳的命令
FROM_UNIXTIME 是從 Unix 時(shí)間戳轉(zhuǎn)換為 MySQL 時(shí)間戳的命令
在 SELECT 語(yǔ)句的列比較中使用=魂角,<>,<=智绸,<野揪,> =,>瞧栗,<<斯稳,>>,<=>迹恐,AND挣惰,OR 或 LIKE 運(yùn)算符。
BLOB 是一個(gè)二進(jìn)制對(duì)象唆涝,可以容納可變數(shù)量的數(shù)據(jù)。TEXT 是一個(gè)不區(qū)分大小寫的 BLOB唇辨。
BLOB 和 TEXT 類型之間的唯一區(qū)別在于對(duì) BLOB 值進(jìn)行排序和比較時(shí)區(qū)分大小寫,對(duì) TEXT 值不區(qū)分大小寫能耻。
40赏枚、MySQL_fetch_array 和 MySQL_fetch_object 的區(qū)別是什么?
以 下 是 MySQL_fetch_array 和 MySQL_fetch_object 的 區(qū) 別 : MySQL_fetch_array() – 將結(jié)果行作為關(guān)聯(lián)數(shù)組或來(lái)自數(shù)據(jù)庫(kù)的常規(guī)數(shù)組返回晓猛。MySQL_fetch_object – 從數(shù)據(jù)庫(kù)返回結(jié)果行作為對(duì)象饿幅。
41、MyISAM 表格將在哪里存儲(chǔ)戒职,并且還提供其存儲(chǔ)格式栗恩?
每個(gè) MyISAM 表格以三種格式存儲(chǔ)在磁盤上:
·“.frm”文件存儲(chǔ)表定義
·數(shù)據(jù)文件具有“.MYD”(MYData)擴(kuò)展名索引文件具有“.MYI”(MYIndex)擴(kuò)展名
42、MySQL 如何優(yōu)化 DISTINCT洪燥?
DISTINCT 在所有列上轉(zhuǎn)換為 GROUP BY磕秤,并與 ORDER BY 子句結(jié)合使用。
SELECT DISTINCT t1.a FROM t1,t2 where t1.a=t2.a;
在 MySQL 中,使用以下代碼查詢顯示前 50 行:
任何標(biāo)準(zhǔn)表最多可以創(chuàng)建 16 個(gè)索引列 。
45芒篷、NOW()和 CURRENT_DATE()有什么區(qū)別搜变?
NOW()命令用于顯示當(dāng)前年份,月份针炉,日期挠他,小時(shí),分鐘和秒篡帕。CURRENT_DATE()僅顯示當(dāng)前年份绩社,月份和日期。
46赂苗、什么是非標(biāo)準(zhǔn)字符串類型愉耙?
TINYTEXT
TEXT
MEDIUMTEXT
LONGTEXT
CONCAT(A, B) – 連接兩個(gè)字符串值以創(chuàng)建單個(gè)字符串輸出朴沿。通常用于將兩個(gè)或多個(gè)字段合并為一個(gè)字段。
FORMAT(X, D)- 格式化數(shù)字 X 到 D 有效數(shù)字。
CURRDATE(), CURRTIME()- 返回當(dāng)前日期或時(shí)間赌渣。
NOW() – 將當(dāng)前日期和時(shí)間作為一個(gè)值返回魏铅。
MONTH(),DAY()坚芜,YEAR()览芳,WEEK(),WEEKDAY() – 從日期值中提取給定數(shù)據(jù)鸿竖。
HOUR()沧竟,MINUTE(),SECOND() – 從時(shí)間值中提取給定數(shù)據(jù)缚忧。
DATEDIFF(A悟泵,B) – 確定兩個(gè)日期之間的差異,通常用于計(jì)算年齡
SUBTIMES(A闪水,B) – 確定兩次之間的差異糕非。
FROMDAYS(INT) – 將整數(shù)天數(shù)轉(zhuǎn)換為日期值
在缺省模式下朽肥,MySQL 是 autocommit 模式的,所有的數(shù)據(jù)庫(kù)更新操作都會(huì)即時(shí)提交持钉,所以在缺省情況下鞠呈,MySQL 是不支持事務(wù)的。
但是如果你的 MySQL 表類型是使用 InnoDB Tables 或 BDB tables 的話右钾,你的MySQL 就可以使用事務(wù)處理,使用 SET AUTOCOMMIT=0 就可以使 MySQL 允許在非 autocommit 模式蚁吝,在非autocommit 模式下,你必須使用 COMMIT 來(lái)提交你的更改舀射,或者用 ROLLBACK來(lái)回滾你的更改窘茁。
NUMERIC 和 DECIMAL 類型被 MySQL 實(shí)現(xiàn)為同樣的類型脆烟,這在 SQL92 標(biāo)準(zhǔn)允許山林。他們被用于保存值,該值的準(zhǔn)確精度是極其重要的值邢羔, 例如與金錢有關(guān)的數(shù)據(jù)驼抹。當(dāng)聲明一個(gè)類是這些類型之一時(shí),精度和規(guī)模的能被(并且通常是)指定拜鹤。
例如:
在這個(gè)例子中框冀,9(precision)代表將被用于存儲(chǔ)值的總的小數(shù)位數(shù),而 2(scale)代表將被用于存儲(chǔ)小數(shù)點(diǎn)后的位數(shù)敏簿。因此明也,在這種情況下宣虾,能被存儲(chǔ)在 salary 列中的值的范圍是從-9999999.99 到
9999999.99。
salary DECIMAL(9,2)
在這個(gè)例子中温数,9(precision)代表將被用于存儲(chǔ)值的總的小數(shù)位數(shù)绣硝,而 2(scale)代表將被用于存儲(chǔ)小數(shù)點(diǎn)后的位數(shù)。因此撑刺,在這種情況下鹉胖,能被存儲(chǔ)在 salary 列中的值的范圍是從-9999999.99 到
9999999.99。
50够傍、MySQL 有關(guān)權(quán)限的表都有哪幾個(gè)甫菠?
MySQL 服務(wù)器通過(guò)權(quán)限表來(lái)控制用戶對(duì)數(shù)據(jù)庫(kù)的訪問(wèn),權(quán)限表存放在 MySQL 數(shù)據(jù)庫(kù)里王带,由 MySQL_install_db 腳本初始化。這些權(quán)限表分別 user市殷,db愕撰,table_priv,columns_priv 和 host醋寝。
博主公眾號(hào)程序員小羊?只發(fā)面試相關(guān)推文