摘要:并發(fā)雖然是必須的,但可能會導致以下的問題。事務隔離級別有哪些的默認隔離級別是標準定義了四個隔離級別讀取未提交最低的隔離級別,允許讀取尚未提交的數(shù)據(jù)變更,可能會導致臟讀幻讀或不可重復讀??纱谢罡叩母綦x級別,完全服從的隔離級別。
標題有點標題黨的意思,看了文章之后希望大家不會有這個想法,絕對干貨?。。∵@篇花文章是我花了幾天時間對之前總結的MySQL知識點做了完善后的產(chǎn)物,這篇文章可以用來回顧MySQL基礎知識以及備戰(zhàn)MySQL常見面試問題。
文末有公眾號二維碼,歡迎關注獲取筆主最新更新文章,并可免費獲取筆主總結的《Java面試突擊》以及Java工程師必備學習資源。
@[toc]
MySQL 是一種關系型數(shù)據(jù)庫,在Java企業(yè)級開發(fā)中非常常用,因為 MySQL 是開源免費的,并且方便擴展。阿里巴巴數(shù)據(jù)庫系統(tǒng)也大量用到了 MySQL,因此它的穩(wěn)定性是有保障的。MySQL是開放源代碼的,因此任何人都可以在 GPL(General Public License) 的許可下下載并根據(jù)個性化的需要對其進行修改。MySQL的默認端口號是3306。
事務相關 什么是事務?事務是邏輯上的一組操作,要么都執(zhí)行,要么都不執(zhí)行。
事務最經(jīng)典也經(jīng)常被拿出來說例子就是轉賬了。假如小明要給小紅轉賬1000元,這個轉賬會涉及到兩個關鍵操作就是:將小明的余額減少1000元,將小紅的余額增加1000元。萬一在這兩個操作之間突然出現(xiàn)錯誤比如銀行系統(tǒng)崩潰,導致小明余額減少而小紅的余額沒有增加,這樣就不對了。事務就是保證這兩個關鍵操作要么都成功,要么都要失敗。
事物的四大特性(ACID)介紹一下?原子性: 事務是最小的執(zhí)行單位,不允許分割。事務的原子性確保動作要么全部完成,要么完全不起作用;
一致性: 執(zhí)行事務前后,數(shù)據(jù)保持一致,多個事務對同一個數(shù)據(jù)讀取的結果是相同的;
隔離性: 并發(fā)訪問數(shù)據(jù)庫時,一個用戶的事務不被其他事務所干擾,各并發(fā)事務之間數(shù)據(jù)庫是獨立的;
持久性: 一個事務被提交之后。它對數(shù)據(jù)庫中數(shù)據(jù)的改變是持久的,即使數(shù)據(jù)庫發(fā)生故障也不應該對其有任何影響。
并發(fā)事務帶來哪些問題?在典型的應用程序中,多個事務并發(fā)運行,經(jīng)常會操作相同的數(shù)據(jù)來完成各自的任務(多個用戶對統(tǒng)一數(shù)據(jù)進行操作)。并發(fā)雖然是必須的,但可能會導致以下的問題。
臟讀(Dirty read): 當一個事務正在訪問數(shù)據(jù)并且對數(shù)據(jù)進行了修改,而這種修改還沒有提交到數(shù)據(jù)庫中,這時另外一個事務也訪問了這個數(shù)據(jù),然后使用了這個數(shù)據(jù)。因為這個數(shù)據(jù)是還沒有提交的數(shù)據(jù),那么另外一個事務讀到的這個數(shù)據(jù)是“臟數(shù)據(jù)”,依據(jù)“臟數(shù)據(jù)”所做的操作可能是不正確的。
丟失修改(Lost to modify): 指在一個事務讀取一個數(shù)據(jù)時,另外一個事務也訪問了該數(shù)據(jù),那么在第一個事務中修改了這個數(shù)據(jù)后,第二個事務也修改了這個數(shù)據(jù)。這樣第一個事務內的修改結果就被丟失,因此稱為丟失修改。 例如:事務1讀取某表中的數(shù)據(jù)A=20,事務2也讀取A=20,事務1修改A=A-1,事務2也修改A=A-1,最終結果A=19,事務1的修改被丟失。
不可重復讀(Unrepeatableread): 指在一個事務內多次讀同一數(shù)據(jù)。在這個事務還沒有結束時,另一個事務也訪問該數(shù)據(jù)。那么,在第一個事務中的兩次讀數(shù)據(jù)之間,由于第二個事務的修改導致第一個事務兩次讀取的數(shù)據(jù)可能不太一樣。這就發(fā)生了在一個事務內兩次讀到的數(shù)據(jù)是不一樣的情況,因此稱為不可重復讀。
幻讀(Phantom read): 幻讀與不可重復讀類似。它發(fā)生在一個事務(T1)讀取了幾行數(shù)據(jù),接著另一個并發(fā)事務(T2)插入了一些數(shù)據(jù)時。在隨后的查詢中,第一個事務(T1)就會發(fā)現(xiàn)多了一些原本不存在的記錄,就好像發(fā)生了幻覺一樣,所以稱為幻讀。
不可重復度和幻讀區(qū)別:
不可重復讀的重點是修改,幻讀的重點在于新增或者刪除。
例1(同樣的條件, 你讀取過的數(shù)據(jù), 再次讀取出來發(fā)現(xiàn)值不一樣了 ):事務1中的A先生讀取自己的工資為 1000的操作還沒完成,事務2中的B先生就修改了A的工資為2000,導 致A再讀自己的工資時工資變?yōu)? 2000;這就是不可重復讀。
例2(同樣的條件, 第1次和第2次讀出來的記錄數(shù)不一樣 ):假某工資單表中工資大于3000的有4人,事務1讀取了所有工資大于3000的人,共查到4條記錄,這時事務2 又插入了一條工資大于3000的記錄,事務1再次讀取時查到的記錄就變?yōu)榱?條,這樣就導致了幻讀。
事務隔離級別有哪些?MySQL的默認隔離級別是?SQL 標準定義了四個隔離級別:
READ-UNCOMMITTED(讀取未提交): 最低的隔離級別,允許讀取尚未提交的數(shù)據(jù)變更,可能會導致臟讀、幻讀或不可重復讀。
READ-COMMITTED(讀取已提交): 允許讀取并發(fā)事務已經(jīng)提交的數(shù)據(jù),可以阻止臟讀,但是幻讀或不可重復讀仍有可能發(fā)生。
REPEATABLE-READ(可重復讀): 對同一字段的多次讀取結果都是一致的,除非數(shù)據(jù)是被本身事務自己所修改,可以阻止臟讀和不可重復讀,但幻讀仍有可能發(fā)生。
SERIALIZABLE(可串行化): 最高的隔離級別,完全服從ACID的隔離級別。所有的事務依次逐個執(zhí)行,這樣事務之間就完全不可能產(chǎn)生干擾,也就是說,該級別可以防止臟讀、不可重復讀以及幻讀。
隔離級別 | 臟讀 | 不可重復讀 | 幻影讀 |
---|---|---|---|
READ-UNCOMMITTED | √ | √ | √ |
READ-COMMITTED | × | √ | √ |
REPEATABLE-READ | × | × | √ |
SERIALIZABLE | × | × | × |
MySQL InnoDB 存儲引擎的默認支持的隔離級別是 REPEATABLE-READ(可重讀)。我們可以通過SELECT @@tx_isolation;命令來查看
mysql> SELECT @@tx_isolation; +-----------------+ | @@tx_isolation | +-----------------+ | REPEATABLE-READ | +-----------------+
這里需要注意的是:與 SQL 標準不同的地方在于InnoDB 存儲引擎在 REPEATABLE-READ(可重讀)事務隔離級別下使用的是Next-Key Lock 鎖算法,因此可以避免幻讀的產(chǎn)生,這與其他數(shù)據(jù)庫系統(tǒng)(如 SQL Server)是不同的。所以說InnoDB 存儲引擎的默認支持的隔離級別是 REPEATABLE-READ(可重讀) 已經(jīng)可以完全保證事務的隔離性要求,即達到了 SQL標準的SERIALIZABLE(可串行化)隔離級別。
因為隔離級別越低,事務請求的鎖越少,所以大部分數(shù)據(jù)庫系統(tǒng)的隔離級別都是READ-COMMITTED(讀取提交內容):,但是你要知道的是InnoDB 存儲引擎默認使用 REPEATABLE-READ(可重讀)并不會有任何性能損失。
InnoDB 存儲引擎在 分布式事務 的情況下一般會用到SERIALIZABLE(可串行化)隔離級別。
索引相關![[思維導圖-索引篇]](http://my-blog-to-use.oss-cn-...
為什么索引能提高查詢速度以下內容整理自: 地址: https://juejin.im/post/5b55b8... 作者 :Java3y
先從 MySQL 的基本存儲結構說起
MySQL的基本存儲結構是頁(記錄都存在頁里邊):
各個數(shù)據(jù)頁可以組成一個雙向鏈表
每個數(shù)據(jù)頁中的記錄又可以組成一個單向鏈表
- 每個數(shù)據(jù)頁都會為存儲在它里邊兒的記錄生成一個頁目錄,在通過主鍵查找某條記錄的時候可以在頁目錄中使用二分法快速定位到對應的槽,然后再遍歷該槽對應分組中的記錄即可快速找到指定的記錄 - 以其他列(非主鍵)作為搜索條件:只能從最小記錄開始依次遍歷單鏈表中的每條記錄。
所以說,如果我們寫select * from user where indexname = "xxx"這樣沒有進行任何優(yōu)化的sql語句,默認會這樣做:
定位到記錄所在的頁:需要遍歷雙向鏈表,找到所在的頁
從所在的頁內中查找相應的記錄:由于不是根據(jù)主鍵查詢,只能遍歷所在頁的單鏈表了
很明顯,在數(shù)據(jù)量很大的情況下這樣查找會很慢!這樣的時間復雜度為O(n)。
索引做了些什么可以讓我們查詢加快速度呢?其實就是將無序的數(shù)據(jù)變成有序(相對):
要找到id為8的記錄簡要步驟:
很明顯的是:沒有用索引我們是需要遍歷雙向鏈表來定位對應的頁,現(xiàn)在通過 “目錄” 就可以很快地定位到對應的頁上了!(二分查找,時間復雜度近似為O(logn))
其實底層結構就是B+樹,B+樹作為樹的一種實現(xiàn),能夠讓我們很快地查找出對應的記錄。
以下內容整理自:《Java工程師修煉之道》什么是最左前綴原則?
MySQL中的索引可以以一定順序引用多列,這種索引叫作聯(lián)合索引。如User表的name和city加聯(lián)合索引就是(name,city),而最左前綴原則指的是,如果查詢的時候查詢條件精確匹配索引的左邊連續(xù)一列或幾列,則此列就可以被用到。如下:
select * from user where name=xx and city=xx ; //可以命中索引 select * from user where name=xx ; // 可以命中索引 select * from user where city=xx ; // 無法命中索引
這里需要注意的是,查詢的時候如果兩個條件都用上了,但是順序不同,如 city= xx and name =xx,那么現(xiàn)在的查詢引擎會自動優(yōu)化為匹配聯(lián)合索引的順序,這樣是能夠命中索引的。
由于最左前綴原則,在創(chuàng)建聯(lián)合索引時,索引字段的順序需要考慮字段值去重之后的個數(shù),較多的放前面。ORDER BY子句也遵循此規(guī)則。
注意避免冗余索引冗余索引指的是索引的功能相同,能夠命中就肯定能命中 ,那么 就是冗余索引如(name,city )和(name )這兩個索引就是冗余索引,能夠命中后者的查詢肯定是能夠命中前者的 在大多數(shù)情況下,都應該盡量擴展已有的索引而不是創(chuàng)建新索引。
MySQLS.7 版本后,可以通過查詢 sys 庫的 schema_redundant_indexes 表來查看冗余索引
Mysql如何為表字段添加索引?1.添加PRIMARY KEY(主鍵索引)
ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` )
2.添加UNIQUE(唯一索引)
ALTER TABLE `table_name` ADD UNIQUE ( `column` )
3.添加INDEX(普通索引)
ALTER TABLE `table_name` ADD INDEX index_name ( `column` )
4.添加FULLTEXT(全文索引)
ALTER TABLE `table_name` ADD FULLTEXT ( `column`)
5.添加多列索引
ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )存儲引擎 一些常用命令
查看MySQL提供的所有存儲引擎
mysql> show engines;
從上圖我們可以查看出 MySQL 當前默認的存儲引擎是InnoDB,并且在5.7版本所有的存儲引擎中只有 InnoDB 是事務性存儲引擎,也就是說只有 InnoDB 支持事務。
查看MySQL當前默認的存儲引擎
我們也可以通過下面的命令查看默認的存儲引擎。
mysql> show variables like "%storage_engine%";
查看表的存儲引擎
show table status like "table_name" ;MyISAM和InnoDB區(qū)別
MyISAM是MySQL的默認數(shù)據(jù)庫引擎(5.5版之前)。雖然性能極佳,而且提供了大量的特性,包括全文索引、壓縮、空間函數(shù)等,但MyISAM不支持事務和行級鎖,而且最大的缺陷就是崩潰后無法安全恢復。不過,5.5版本之后,MySQL引入了InnoDB(事務性數(shù)據(jù)庫引擎),MySQL 5.5版本后默認的存儲引擎為InnoDB。
大多數(shù)時候我們使用的都是 InnoDB 存儲引擎,但是在某些情況下使用 MyISAM 也是合適的比如讀密集的情況下。(如果你不介意 MyISAM 崩潰回復問題的話)。
兩者的對比:
是否支持行級鎖 : MyISAM 只有表級鎖(table-level locking),而InnoDB 支持行級鎖(row-level locking)和表級鎖,默認為行級鎖。
是否支持事務和崩潰后的安全恢復: MyISAM 強調的是性能,每次查詢具有原子性,其執(zhí)行數(shù)度比InnoDB類型更快,但是不提供事務支持。但是InnoDB 提供事務支持事務,外部鍵等高級數(shù)據(jù)庫功能。 具有事務(commit)、回滾(rollback)和崩潰修復能力(crash recovery capabilities)的事務安全(transaction-safe (ACID compliant))型表。
是否支持外鍵: MyISAM不支持,而InnoDB支持。
是否支持MVCC :僅 InnoDB 支持。應對高并發(fā)事務, MVCC比單純的加鎖更高效;MVCC只在 READ COMMITTED 和 REPEATABLE READ 兩個隔離級別下工作;MVCC可以使用 樂觀(optimistic)鎖 和 悲觀(pessimistic)鎖來實現(xiàn);各數(shù)據(jù)庫中MVCC實現(xiàn)并不統(tǒng)一。推薦閱讀:MySQL-InnoDB-MVCC多版本并發(fā)控制
......
《MySQL高性能》上面有一句話這樣寫到:
不要輕易相信“MyISAM比InnoDB快”之類的經(jīng)驗之談,這個結論往往不是絕對的。在很多我們已知場景中,InnoDB的速度都可以讓MyISAM望塵莫及,尤其是用到了聚簇索引,或者需要訪問的數(shù)據(jù)都可以放入內存的應用。
一般情況下我們選擇 InnoDB 都是沒有問題的,但是某事情況下你并不在乎可擴展能力和并發(fā)能力,也不需要事務支持,也不在乎崩潰后的安全恢復問題的話,選擇MyISAM也是一個不錯的選擇。但是一般情況下,我們都是需要考慮到這些問題的。
樂觀鎖與悲觀鎖的區(qū)別 悲觀鎖總是假設最壞的情況,每次去拿數(shù)據(jù)的時候都認為別人會修改,所以每次在拿數(shù)據(jù)的時候都會上鎖,這樣別人想拿這個數(shù)據(jù)就會阻塞直到它拿到鎖(共享資源每次只給一個線程使用,其它線程阻塞,用完后再把資源轉讓給其它線程)。傳統(tǒng)的關系型數(shù)據(jù)庫里邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。Java中synchronized和ReentrantLock等獨占鎖就是悲觀鎖思想的實現(xiàn)。
樂觀鎖總是假設最好的情況,每次去拿數(shù)據(jù)的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數(shù)據(jù),可以使用版本號機制和CAS算法實現(xiàn)。樂觀鎖適用于多讀的應用類型,這樣可以提高吞吐量,像數(shù)據(jù)庫提供的類似于write_condition機制,其實都是提供的樂觀鎖。在Java中java.util.concurrent.atomic包下面的原子變量類就是使用了樂觀鎖的一種實現(xiàn)方式CAS實現(xiàn)的。
兩種鎖的使用場景從上面對兩種鎖的介紹,我們知道兩種鎖各有優(yōu)缺點,不可認為一種好于另一種,像樂觀鎖適用于寫比較少的情況下(多讀場景),即沖突真的很少發(fā)生的時候,這樣可以省去了鎖的開銷,加大了系統(tǒng)的整個吞吐量。但如果是多寫的情況,一般會經(jīng)常產(chǎn)生沖突,這就會導致上層應用會不斷的進行retry,這樣反倒是降低了性能,所以一般多寫的場景下用悲觀鎖就比較合適。
樂觀鎖常見的兩種實現(xiàn)方式樂觀鎖一般會使用版本號機制或CAS算法實現(xiàn)。1. 版本號機制
一般是在數(shù)據(jù)表中加上一個數(shù)據(jù)版本號version字段,表示數(shù)據(jù)被修改的次數(shù),當數(shù)據(jù)被修改時,version值會加一。當線程A要更新數(shù)據(jù)值時,在讀取數(shù)據(jù)的同時也會讀取version值,在提交更新時,若剛才讀取到的version值為當前數(shù)據(jù)庫中的version值相等時才更新,否則重試更新操作,直到更新成功。
舉一個簡單的例子: 假設數(shù)據(jù)庫中帳戶信息表中有一個 version 字段,當前值為 1 ;而當前帳戶余額字段( balance )為 $100 。
操作員 A 此時將其讀出( version=1 ),并從其帳戶余額中扣除 $50( $100-$50 )。
在操作員 A 操作的過程中,操作員B 也讀入此用戶信息( version=1 ),并從其帳戶余額中扣除 $20 ( $100-$20 )。
操作員 A 完成了修改工作,將數(shù)據(jù)版本號加一( version=2 ),連同帳戶扣除后余額( balance=$50 ),提交至數(shù)據(jù)庫更新,此時由于提交數(shù)據(jù)版本大于數(shù)據(jù)庫記錄當前版本,數(shù)據(jù)被更新,數(shù)據(jù)庫記錄 version 更新為 2 。
操作員 B 完成了操作,也將版本號加一( version=2 )試圖向數(shù)據(jù)庫提交數(shù)據(jù)( balance=$80 ),但此時比對數(shù)據(jù)庫記錄版本時發(fā)現(xiàn),操作員 B 提交的數(shù)據(jù)版本號為 2 ,數(shù)據(jù)庫記錄當前版本也為 2 ,不滿足 “ 提交版本必須大于記錄當前版本才能執(zhí)行更新 “ 的樂觀鎖策略,因此,操作員 B 的提交被駁回。
這樣,就避免了操作員 B 用基于 version=1 的舊數(shù)據(jù)修改的結果覆蓋操作員A 的操作結果的可能。
2. CAS算法即compare and swap(比較與交換),是一種有名的無鎖算法。無鎖編程,即不使用鎖的情況下實現(xiàn)多線程之間的變量同步,也就是在沒有線程被阻塞的情況下實現(xiàn)變量的同步,所以也叫非阻塞同步(Non-blocking Synchronization)。CAS算法涉及到三個操作數(shù)
需要讀寫的內存值 V
進行比較的值 A
擬寫入的新值 B
當且僅當 V 的值等于 A時,CAS通過原子方式用新值B來更新V的值,否則不會執(zhí)行任何操作(比較和替換是一個原子操作)。一般情況下是一個自旋操作,即不斷的重試。
關于自旋鎖,大家可以看一下這篇文章,非常不錯:《 面試必備之深入理解自旋鎖》
樂觀鎖的缺點ABA 問題是樂觀鎖一個常見的問題1 ABA 問題
如果一個變量V初次讀取的時候是A值,并且在準備賦值的時候檢查到它仍然是A值,那我們就能說明它的值沒有被其他線程修改過了嗎?很明顯是不能的,因為在這段時間它的值可能被改為其他值,然后又改回A,那CAS操作就會誤認為它從來沒有被修改過。這個問題被稱為CAS操作的 "ABA"問題。
JDK 1.5 以后的 AtomicStampedReference 類就提供了此種能力,其中的 compareAndSet 方法就是首先檢查當前引用是否等于預期引用,并且當前標志是否等于預期標志,如果全部相等,則以原子方式將該引用和該標志的值設置為給定的更新值。
2 循環(huán)時間長開銷大自旋CAS(也就是不成功就一直循環(huán)執(zhí)行直到成功)如果長時間不成功,會給CPU帶來非常大的執(zhí)行開銷。 如果JVM能支持處理器提供的pause指令那么效率會有一定的提升,pause指令有兩個作用,第一它可以延遲流水線執(zhí)行指令(de-pipeline),使CPU不會消耗過多的執(zhí)行資源,延遲的時間取決于具體實現(xiàn)的版本,在一些處理器上延遲時間是零。第二它可以避免在退出循環(huán)的時候因內存順序沖突(memory order violation)而引起CPU流水線被清空(CPU pipeline flush),從而提高CPU的執(zhí)行效率。
3 只能保證一個共享變量的原子操作CAS 只對單個共享變量有效,當操作涉及跨多個共享變量時 CAS 無效。但是從 JDK 1.5開始,提供了AtomicReference類來保證引用對象之間的原子性,你可以把多個變量放在一個對象里來進行 CAS 操作.所以我們可以使用鎖或者利用AtomicReference類把多個共享變量合并成一個共享變量來操作。
鎖機制與InnoDB鎖算法MyISAM和InnoDB存儲引擎使用的鎖:
MyISAM 采用表級鎖(table-level locking)。
InnoDB 支持行級鎖(row-level locking)和表級鎖,默認為行級鎖
表級鎖和行級鎖對比:
表級鎖: Mysql中鎖定 粒度最大 的一種鎖,對當前操作的整張表加鎖,實現(xiàn)簡單,資源消耗也比較少,加鎖快,不會出現(xiàn)死鎖。其鎖定粒度最大,觸發(fā)鎖沖突的概率最高,并發(fā)度最低,MyISAM和 InnoDB引擎都支持表級鎖。
行級鎖: Mysql中鎖定 粒度最小 的一種鎖,只針對當前操作的行進行加鎖。 行級鎖能大大減少數(shù)據(jù)庫操作的沖突。其加鎖粒度最小,并發(fā)度高,但加鎖的開銷也最大,加鎖慢,會出現(xiàn)死鎖。
詳細內容可以參考: Mysql鎖機制簡單了解一下
InnoDB存儲引擎的鎖的算法有三種:
Record lock:單個行記錄上的鎖
Gap lock:間隙鎖,鎖定一個范圍,不包括記錄本身
Next-key lock:record+gap 鎖定一個范圍,包含記錄本身
相關知識點:
innodb對于行的查詢使用next-key lock
Next-locking keying為了解決Phantom Problem幻讀問題
當查詢的索引含有唯一屬性時,將next-key lock降級為record key
Gap鎖設計的目的是為了阻止多個事務將記錄插入到同一范圍內,而這會導致幻讀問題的產(chǎn)生
有兩種方式顯式關閉gap鎖:(除了外鍵約束和唯一性檢查外,其余情況僅使用record lock) A. 將事務隔離級別設置為RC B. 將參數(shù)innodb_locks_unsafe_for_binlog設置為1
大表優(yōu)化當MySQL單表記錄數(shù)過大時,數(shù)據(jù)庫的CRUD性能會明顯下降,一些常見的優(yōu)化措施如下:
1. 限定數(shù)據(jù)的范圍務必禁止不帶任何限制數(shù)據(jù)范圍條件的查詢語句。比如:我們當用戶在查詢訂單歷史的時候,我們可以控制在一個月的范圍內;
2. 讀/寫分離經(jīng)典的數(shù)據(jù)庫拆分方案,主庫負責寫,從庫負責讀;
3. 垂直分區(qū)根據(jù)數(shù)據(jù)庫里面數(shù)據(jù)表的相關性進行拆分。 例如,用戶表中既有用戶的登錄信息又有用戶的基本信息,可以將用戶表拆分成兩個多帶帶的表,甚至放到多帶帶的庫做分庫。
簡單來說垂直拆分是指數(shù)據(jù)表列的拆分,把一張列比較多的表拆分為多張表。 如下圖所示,這樣來說大家應該就更容易理解了。
垂直拆分的優(yōu)點: 可以使得列數(shù)據(jù)變小,在查詢時減少讀取的Block數(shù),減少I/O次數(shù)。此外,垂直分區(qū)可以簡化表的結構,易于維護。
垂直拆分的缺點: 主鍵會出現(xiàn)冗余,需要管理冗余列,并會引起Join操作,可以通過在應用層進行Join來解決。此外,垂直分區(qū)會讓事務變得更加復雜;
4. 水平分區(qū)保持數(shù)據(jù)表結構不變,通過某種策略存儲數(shù)據(jù)分片。這樣每一片數(shù)據(jù)分散到不同的表或者庫中,達到了分布式的目的。 水平拆分可以支撐非常大的數(shù)據(jù)量。
水平拆分是指數(shù)據(jù)表行的拆分,表的行數(shù)超過200萬行時,就會變慢,這時可以把一張的表的數(shù)據(jù)拆成多張表來存放。舉個例子:我們可以將用戶信息表拆分成多個用戶信息表,這樣就可以避免單一表數(shù)據(jù)量過大對性能造成影響。
水平拆分可以支持非常大的數(shù)據(jù)量。需要注意的一點是:分表僅僅是解決了單一表數(shù)據(jù)過大的問題,但由于表的數(shù)據(jù)還是在同一臺機器上,其實對于提升MySQL并發(fā)能力沒有什么意義,所以 水平拆分最好分庫 。
水平拆分能夠 支持非常大的數(shù)據(jù)量存儲,應用端改造也少,但 分片事務難以解決 ,跨節(jié)點Join性能較差,邏輯復雜?!禞ava工程師修煉之道》的作者推薦 盡量不要對數(shù)據(jù)進行分片,因為拆分會帶來邏輯、部署、運維的各種復雜度 ,一般的數(shù)據(jù)表在優(yōu)化得當?shù)那闆r下支撐千萬以下的數(shù)據(jù)量是沒有太大問題的。如果實在要分片,盡量選擇客戶端分片架構,這樣可以減少一次和中間件的網(wǎng)絡I/O。
下面補充一下數(shù)據(jù)庫分片的兩種常見方案:
客戶端代理: 分片邏輯在應用端,封裝在jar包中,通過修改或者封裝JDBC層來實現(xiàn)。 當當網(wǎng)的 Sharding-JDBC 、阿里的TDDL是兩種比較常用的實現(xiàn)。
中間件代理: 在應用和數(shù)據(jù)中間加了一個代理層。分片邏輯統(tǒng)一維護在中間件服務中。 我們現(xiàn)在談的 Mycat 、360的Atlas、網(wǎng)易的DDB等等都是這種架構的實現(xiàn)。
詳細內容可以參考: MySQL大表優(yōu)化方案
一條SQL語句在MySQL中如何執(zhí)行的一條SQL語句在MySQL中如何執(zhí)行的
MySQL高性能優(yōu)化規(guī)范建議MySQL高性能優(yōu)化規(guī)范建議
一條SQL語句執(zhí)行得很慢的原因有哪些?騰訊面試:一條SQL語句執(zhí)行得很慢的原因有哪些?---不看后悔系列
一千行 MySQL 學習筆記一千行 MySQL 學習筆記
公眾號如果大家想要實時關注我更新的文章以及分享的干貨的話,可以關注我的公眾號。
《Java面試突擊》: 由本文檔衍生的專為面試而生的《Java面試突擊》V2.0 PDF 版本公眾號后臺回復 "Java面試突擊" 即可免費領??!
Java工程師必備學習資源: 一些Java工程師常用學習資源公眾號后臺回復關鍵字 “1” 即可免費無套路獲取。
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/75048.html
摘要:哪吒社區(qū)技能樹打卡打卡貼函數(shù)式接口簡介領域優(yōu)質創(chuàng)作者哪吒公眾號作者架構師奮斗者掃描主頁左側二維碼,加入群聊,一起學習一起進步歡迎點贊收藏留言前情提要無意間聽到領導們的談話,現(xiàn)在公司的現(xiàn)狀是碼農太多,但能獨立帶隊的人太少,簡而言之,不缺干 ? 哪吒社區(qū)Java技能樹打卡?【打卡貼 day2...
摘要:雖然有了十全的計劃,但如何高效率去記住上面那么多東西是一個大問題,看看我是怎么做的。 前言 前一篇文章講述了我在三月份毫無準備就去面試的后果,一開始心態(tài)真的爆炸,但是又不服氣,一想到每次回來后家人朋友問我面試結果的期待臉,越覺得必須付出的行動來證明自己了。 面經(jīng)傳送門:一個1年工作經(jīng)驗的PHP程序員是如何被面試官虐的? 下面是我花費兩個星期做的準備,主要分三部分: 有計劃——計劃好...
摘要:獲取的對象范圍方法獲取的是最終應用在元素上的所有屬性對象即使沒有代碼,也會把默認的祖宗八代都顯示出來而只能獲取元素屬性中的樣式。因此對于一個光禿禿的元素,方法返回對象中屬性值如果有就是據(jù)我測試不同環(huán)境結果可能有差異而就是。 花了很長時間整理的前端面試資源,喜歡請大家不要吝嗇star~ 別只收藏,點個贊,點個star再走哈~ 持續(xù)更新中……,可以關注下github 項目地址 https:...
閱讀 1646·2021-10-09 09:44
閱讀 2819·2021-10-08 10:04
閱讀 2482·2021-09-26 09:55
閱讀 3861·2021-09-22 10:02
閱讀 3320·2019-08-29 17:08
閱讀 1077·2019-08-29 15:08
閱讀 2964·2019-08-26 13:52
閱讀 3285·2019-08-26 13:34