10-07 31—35


31.什么是覆蓋索引?

如果一個索引包含(或覆蓋)所有需要查詢的字段的值,稱為‘覆蓋索引’。即只需掃描索引而無須回表。
只掃描索引而無需回表的優點:
    1.索引條目通常遠小於數據行大小,只需要讀取索引,則mysql會極大地減少數據訪問量。
    2.因為索引是按照列值順序存儲的,所以對於IO密集的范圍查找會比隨機從磁盤讀取每一行數據的IO少很多。
    3.一些存儲引擎如myisam在內存中只緩存索引,數據則依賴於操作系統來緩存,因此要訪問數據需要一次系統調用
    4.innodb的聚簇索引,覆蓋索引對innodb表特別有用。(innodb的二級索引在葉子節點中保存了行的主鍵值,所以如果二級主鍵能夠覆蓋查詢,則可以避免對主鍵索引的二次查詢)

覆蓋索引必須要存儲索引列的值,而哈希索引、空間索引和全文索引不存儲索引列的值,所以mysql只能用B-tree索引做覆蓋索引。

當發起一個索引覆蓋查詢時,在explain的extra列可以看到using index的信息

32.簡述數據庫讀寫分離?

MySQL Proxy最強大的一項功能是實現“讀寫分離(Read/Write Splitting)”。基本的原理是讓主數據庫處理事務性查詢,而從數據庫處理SELECT查詢。數據庫復制被用來把事務性查詢導致的變更同步到集群中的從數據庫。 當然,主服務器也可以提供查詢服務。使用讀寫分離最大的作用無非是環境服務器壓力。

讀寫分離的好處
1、增加冗余
2、增加了機器的處理能力
3、對於讀操作為主的應用,使用讀寫分離是最好的場景,因為可以確保寫的服務器壓力更小,而讀又可以接受點時間上的延遲。

讀寫分離提高性能之原因
1、物理服務器增加,負荷增加
2、主從只負責各自的寫和讀,極大程度的緩解X鎖和S鎖爭用
3、從庫可配置myisam引擎,提升查詢性能以及節約系統開銷
4、從庫同步主庫的數據和主庫直接寫還是有區別的,通過主庫發送來的binlog恢復數據,但是,最重要區別在於主庫向從庫發送binlog是異步的,從庫恢復數據也是異步的
5、讀寫分離適用與讀遠大於寫的場景,如果只有一台服務器,當select很多時,update和delete會被這些select訪問中的數據堵塞,等待select結束,並發性能不高。 對於寫和讀比例相近的應用,應該部署雙主相互復制
6、可以在從庫啟動是增加一些參數來提高其讀的性能,例如--skip-innodb、--skip-bdb、--low-priority-updates以及--delay-key-write=ALL。當然這些設置也是需要根據具體業務需求來定得,不一定能用上
7、分攤讀取。假如我們有1主3從,不考慮上述1中提到的從庫單方面設置,假設現在1分鍾內有10條寫入,150條讀取。那么,1主3從相當於共計40條寫入,而讀取總數沒變,因此平均下來每台服務器承擔了10條寫入和50條讀取(主庫不承擔讀取操作)。因此,雖然寫入沒變,但是讀取大大分攤了,提高了系統性能。另外,當讀取被分攤后,又間接提高了寫入的性能。所以,總體性能提高了,說白了就是拿機器和帶寬換性能。MySQL官方文檔中有相關演算公式:官方文檔 見6.9FAQ之“MySQL復制能夠何時和多大程度提高系統性能”
8、MySQL復制另外一大功能是增加冗余,提高可用性,當一台數據庫服務器宕機后能通過調整另外一台從庫來以最快的速度恢復服務,因此不能光看性能,也就是說1主1從也是可以的。

33.簡述數據庫分庫分表?(水平、垂直)

# 水平分庫
1、概念:以字段為依據,按照一定策略(hash、range等),將一個庫中的數據拆分到多個庫中。
2、結果:
  每個庫的結構都一樣;
  每個庫的數據都不一樣,沒有交集;
  所有庫的並集是全量數據;
3、場景:系統絕對並發量上來了,分表難以根本上解決問題,並且還沒有明顯的業務歸屬來垂直分庫。
4、分析:庫多了,io和cpu的壓力自然可以成倍緩解。

# 水平分表
1、概念:以字段為依據,按照一定策略(hash、range等),將一個表中的數據拆分到多個表中。
2、結果:
  每個表的結構都一樣;
  每個表的數據都不一樣,沒有交集;
  所有表的並集是全量數據;
3、場景:系統絕對並發量並沒有上來,只是單表的數據量太多,影響了SQL效率,加重了CPU負擔,以至於成為瓶頸。
4、分析:表的數據量少了,單次SQL執行效率高,自然減輕了CPU的負擔。

# 垂直分庫
1、概念:以表為依據,按照業務歸屬不同,將不同的表拆分到不同的庫中。
2、結果:
  每個庫的結構都不一樣;
  每個庫的數據也不一樣,沒有交集;
  所有庫的並集是全量數據;
3、場景:系統絕對並發量上來了,並且可以抽象出單獨的業務模塊。
4、分析:到這一步,基本上就可以服務化了。例如,隨着業務的發展一些公用的配置表、字典表等越來越多,這時可以將這些表拆到單獨的庫中,甚至可以服務化。再有,隨着業務的發展孵化出了一套業務模式,這時可以將相關的表拆到單獨的庫中,甚至可以服務化。

# 垂直分表
1、概念:以字段為依據,按照字段的活躍性,將表中字段拆到不同的表(主表和擴展表)中。
2、結果:
  2.1、每個表的結構都不一樣;
  2.2、每個表的數據也不一樣,一般來說,每個表的字段至少有一列交集,一般是主鍵,用於關聯數據;
  2.3、所有表的並集是全量數據;
3、場景:系統絕對並發量並沒有上來,表的記錄並不多,但是字段多,並且熱點數據和非熱點數據在一起,單行數據所需的存儲空間較大。以至於數據庫緩存的數據行減少,查詢時會去讀磁盤數據產生大量的隨機讀IO,產生IO瓶頸。
4、分析:可以用列表頁和詳情頁來幫助理解。垂直分表的拆分原則是將熱點數據(可能會冗余經常一起查詢的數據)放在一起作為主表,非熱點數據放在一起作為擴展表。這樣更多的熱點數據就能被緩存下來,進而減少了隨機讀IO。拆了之后,要想獲得全部數據就需要關聯兩個表來取數據。
但記住,千萬別用join,因為join不僅會增加CPU負擔並且會講兩個表耦合在一起(必須在一個數據庫實例上)。關聯數據,應該在業務Service層做文章,分別獲取主表和擴展表數據然后用關聯字段關聯得到全部數據。

34.數據庫鎖的作用?

根據不同的鎖的作用域我們可以把數據庫的鎖分為三種,分別為:
  行鎖:對表中的某一行進行加鎖。
  頁鎖:對表中一組連續的行進行加鎖。
  表鎖:對整張表進行加鎖
不同的作用域對並發性能是有很大影響的,比如說如果數據庫的插入都是使用表鎖,那在大量用戶對某張表進行插入讀取操作的話,同時只能有一個用戶可以訪問該表,那並發量肯定就是慘不忍睹了。

樂觀鎖
在樂觀鎖中,我們有3種常用的做法來實現:

第一種就是在數據取得的時候把整個數據都copy到應用中,在進行提交的時候比對當前數據庫中的數據和開始的時候更新前取得的數據。當發現兩個數據一模一樣以后,就表示沒有沖突可以提交,否則則是並發沖突,需要去用業務邏輯進行解決。

第二種樂觀鎖的做法就是采用版本戳,這個在Hibernate中得到了使用。采用版本戳的話,首先需要在你有樂觀鎖的數據庫table上建立一個新的column,比如為number型,當你數據每更新一次的時候,版本數就會往上增加1。比如同樣有2個session同樣對某條數據進行操作。兩者都取到當前的數據的版本號為1,當第一個session進行數據更新后,在提交的時候查看到當前數據的版本還為1,和自己一開始取到的版本相同。就正式提交,然后把版本號增加1,這個時候當前數據的版本為2。當第二個session也更新了數據提交的時候,發現數據庫中版本為2,和一開始這個session取到的版本號不一致,就知道別人更新過此條數據,這個時候再進行業務處理,比如整個Transaction都Rollback等等操作。在用版本戳的時候,可以在應用程序側使用版本戳的驗證,也可以在數據庫側采用Trigger(觸發器)來進行驗證。不過數據庫的Trigger的性能開銷還是比較的大,所以能在應用側進行驗證的話還是推薦不用Trigger。

第三種做法和第二種做法有點類似,就是也新增一個Table的Column,不過這次這個column是采用timestamp型,存儲數據最后更新的時間。在Oracle9i以后可以采用新的數據類型,也就是timestamp with time zone類型來做時間戳。這種Timestamp的數據精度在Oracle的時間類型中是最高的,精確到微秒(還沒與到納秒的級別),一般來說,加上數據庫處理時間和人的思考動作時間,微秒級別是非常非常夠了,其實只要精確到毫秒甚至秒都應該沒有什么問題。和剛才的版本戳類似,也是在更新提交的時候檢查當前數據庫中數據的時間戳和自己更新前取到的時間戳進行對比,如果一致則OK,否則就是版本沖突。如果不想把代碼寫在程序中或者由於別的原因無法把代碼寫在現有的程序中,也可以把這個時間戳樂觀鎖邏輯寫在Trigger或者存儲過程中

悲觀鎖(排他鎖)
悲觀鎖也稱之為互斥鎖,可以寫為X鎖,指的是同時只能有一個事務可以對某個資源進行訪問操作。如果有兩個事務同時要操作某張表,我們稱之為事務A和事務B,如果事務A獲得了這張表的表鎖,那事務B只能等待事務A釋放了這個鎖之后才能對該表進行操作。

數據庫的insert,update操作默認是采用互斥鎖進行加鎖,讀取select則不是,如果要對select操作使用互斥鎖,可以這樣寫

select * from table where id = 1 for update
共享鎖
共享鎖是一種樂觀鎖,可以寫為S鎖,在數據庫中共享鎖的作用主要是針對讀取操作的。如果讀取操作使用X鎖的話,並發量會非常低,所以數據庫提供了共享鎖S鎖,提高讀取操作的並發性能,多個事務可以同時持有一個資源的S鎖,不像X鎖,同時只能有一個事務持有。

舉個例子:

事務A和事務B對表TABLE進行訪問,事務A想查看id = 1的行信息

select * from TABLE where id = 1 lock in share mode
如果當前id = 1的行對應的X鎖沒有被其他事務獲取,那事務A就順利的獲得了該行的S鎖。

現在事務B也想查看id = 1 的行信息,會怎么樣?

select * from TABLE where id = 1 lock in share mode
現在持有該行鎖的只有事務A,持有的是S鎖,所以事務B也可以獲取該行的S鎖,兩個事務可以並發的讀取id = 1的行。

這個和之前所說的樂觀鎖實現是有區別的,最大的不同就是讀取的時候共享鎖是要真的去持有鎖,但是樂觀鎖只是實現了一種CAS模式,但是並讀取的時候沒有真的持有鎖。

35.where 子句中有 a,b,c 三個查詢條件, 創建一個組合索引 abc(a,b,c),以下哪 種會命中索引

(a)   *****
(b)
(c)
(a,b)    *****
(b,c)
(a,c)
(a,b,c)   *****


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM