java(數據存儲)面試要點3

1. 不要在列上使用函數和進行運算
2. 儘可能避免使用 != 或 not in或 <> 等否認操做符
3. 儘可能避免使用 or 來鏈接條件
4. 多個單列索引並非最佳選擇
5. 複合索引的最左前綴原則
6. 覆蓋索引的好處
7. 範圍查詢對多列查詢的影響
8. 索引不會包含有NULL值的列
9. 隱式轉換的影響
10. like 語句的索引失效問題html

    即空間換取時間,採起數據冗餘的方式避免表之間的關聯查詢。mysql

    實際上,垂直拆分後的表依然存在單表數據量過大的問題,須要進行水平拆分。所以,實際狀況中,水平拆分每每會和垂直拆分結合使用。假設,隨着用戶數的不斷增長,用戶表單表存在上千萬的數據,這時能夠把一張用戶表的數據拆成多張用戶表來存放。web

數據遷移與擴容問題
表關聯問題
分頁與排序問題
分佈式事務問題
分佈式全局惟一ID算法

分庫與分表主要用於應對當前互聯網常見的兩個場景:海量數據和高併發。然而,分庫與分表是一把雙刃劍,雖然很好的應對海量數據和高併發對數據庫的衝擊和壓力,可是卻提升的系統的複雜度和維護成本。sql

所以,個人建議:須要結合實際需求,不宜過分設計,在項目一開始不採用分庫與分表設計,而是隨着業務的增加,在沒法繼續優化的狀況下,再考慮分庫與分表提升系統的性能。mongodb

單列索引:單列索引是最基本的索引,它沒有任何限制。數據庫

複合索引:複合索引是在多個字段上建立的索引。複合索引遵照「最左前綴」原則,即在查詢條件中使用了複合索引的第一個字段,索引纔會被使用。所以,在複合索引中索引列的順序相當重要。併發

惟一索引:惟一索引和單列索引相似,主要的區別在於,惟一索引限制列的值必須惟一,但容許有空值。對於多個字段,惟一索引規定列值的組合必須惟一。分佈式

主鍵索引:主鍵索引是一種特殊的惟一索引,不容許有空值。此外, CREATE INDEX 不能建立主鍵索引,須要使用 ALTER TABLE 代替,例如:函數

alter table tbl_name add primary key(index_col_name);
強制索引
有時,由於使用 MySQL 的優化器機制,本來應該使用索引的優化器,反而選擇執行全表掃描或者執行的不是預期的索引。此時,能夠經過強制索引的方式引導優化器採起正確的執行計劃。

使用強制索引,SQL 語句只使用創建在 index_col_name 上的索引,而不使用其它的索引。

select * from tbl_name force index (index_col_name) …
切記,不要濫用強制索引,由於 MySQL 的優化器會同時評估 I/O 和 CPU 的成本,通常狀況下,能夠自動分析選擇最合適的索引。

若是優化器成本評估錯誤,於是沒有選擇最佳方案,最好的方法應該是將合適的索引修改得更好。

若是某個 SQL 語句使用強制索引,須要在系統迭代開發過程當中時時維護強制索引,一方面,須要保證使用的強制索引最優,另一面,須要保證所使用的強制索引不能被誤刪,否則將致使 SQL 報錯。

所以,若是某個 SQL 語句必需要使用強制索引,建議在團隊內部開展嚴格地評審後纔可使用。

全文索引
在通常狀況下,模糊查詢都是經過 like 的方式進行查詢。可是,對於海量數據,這並非一個好辦法,在 like 「value%」 可使用索引,可是對於 like 「%value%」 這樣的方式,執行全表查詢,這在數據量小的表,不存在性能問題,可是對於海量數據,全表掃描是很是可怕的事情,因此 like 進行模糊匹配性能不好。

這種狀況下,須要考慮使用全文搜索的方式進行優化。全文搜索在 MySQL 中是一個 FULLTEXT 類型索引。 FULLTEXT 索引在 MySQL 5.6 版本以後支持 InnoDB,而以前的版本只支持 MyISAM 表。

 

爲中文內容表提供一個全文索引表,存儲全文索引分詞信息,兩張表根據中文內容表的 ID 進行關聯。
將內容進行分詞後,用 base64 編碼,保存在全文索引表中。
關鍵的一步,如何分詞,分詞的命中率問題。很簡單,自定義分詞庫,寫一個分詞算法將全部的組合進行分詞,在內容很少的狀況下很是有用。舉個例子,「梁桂釗」,能夠進行自定義分詞:[梁、桂、釗、梁桂、桂釗、梁桂釗]。
事實上,MySQL 全文搜索只是一個臨時方案,對於全文搜索場景,更專業的作法是使用全文搜索引擎,例如 ElasticSearch 或 Solr。

 

  • MySQL 遇到的死鎖問題

在數據庫中有兩種基本的鎖類型:排它鎖(Exclusive Locks,即X鎖)和共享鎖(Share Locks,即S鎖)。當數據對象被加上排它鎖時,其餘的事務不能對它讀取和修改。加了共享鎖的數據對象能夠被其餘事務讀取,但不能修改。數據庫利用這兩 種基本的鎖類型來對數據庫的事務進行併發控制。

死鎖的第一種狀況

一個用戶A 訪問表A(鎖住了表A),而後又訪問表B;另外一個用戶B 訪問表B(鎖住了表B),而後企圖訪問表A;這時用戶A因爲用戶B已經鎖住表B,它必須等待用戶B釋放表B才能繼續,一樣用戶B要等用戶A釋放表A才能繼續,這就死鎖就產生了。

解決方法:

這種死鎖比較常見,是因爲程序的BUG產生的,除了調整的程序的邏輯沒有其它的辦法。仔細分析程序的邏輯,對於數據庫的多表操做時,儘可能按照相同的順序進 行處理,儘可能避免同時鎖定兩個資源,如操做A和B兩張表時,老是按先A後B的順序處理, 必須同時鎖定兩個資源時,要保證在任什麼時候刻都應該按照相同的順序來鎖定資源。

死鎖的第二種狀況

用戶A查詢一條紀錄,而後修改該條紀錄;這時用戶B修改該條紀錄,這時用戶A的事務裏鎖的性質由查詢的共享鎖企圖上升到獨佔鎖,而用戶B裏的獨佔鎖因爲A 有共享鎖存在因此必須等A釋放掉共享鎖,而A因爲B的獨佔鎖而沒法上升的獨佔鎖也就不可能釋放共享鎖,因而出現了死鎖。這種死鎖比較隱蔽,但在稍大點的項 目中常常發生。如在某項目中,頁面上的按鈕點擊後,沒有使按鈕馬上失效,使得用戶會屢次快速點擊同一按鈕,這樣同一段代碼對數據庫同一條記錄進行屢次操 做,很容易就出現這種死鎖的狀況。

解決方法:

一、對於按鈕等控件,點擊後使其馬上失效,不讓用戶重複點擊,避免對同時對同一條記錄操做。
二、使用樂觀鎖進行控制。樂觀鎖大可能是基於數據版本(Version)記錄機制實現。即爲數據增長一個版本標識,在基於數據庫表的版本解決方案中,通常是 經過爲數據庫表增長一個「version」字段來實現。讀取出數據時,將此版本號一同讀出,以後更新時,對此版本號加一。此時,將提交數據的版本數據與數 據庫表對應記錄的當前版本信息進行比對,若是提交的數據版本號大於數據庫表當前版本號,則予以更新,不然認爲是過時數據。樂觀鎖機制避免了長事務中的數據 庫加鎖開銷(用戶A和用戶B操做過程當中,都沒有對數據庫數據加鎖),大大提高了大併發量下的系統總體性能表現。Hibernate 在其數據訪問引擎中內置了樂觀鎖實現。須要注意的是,因爲樂觀鎖機制是在咱們的系統中實現,來自外部系統的用戶更新操做不受咱們系統的控制,所以可能會造 成髒數據被更新到數據庫中。
三、使用悲觀鎖進行控制。悲觀鎖大多數狀況下依靠數據庫的鎖機制實現,如Oracle的Select … for update語句,以保證操做最大程度的獨佔性。但隨之而來的就是數據庫性能的大量開銷,特別是對長事務而言,這樣的開銷每每沒法承受。如一個金融系統, 當某個操做員讀取用戶的數據,並在讀出的用戶數據的基礎上進行修改時(如更改用戶帳戶餘額),若是採用悲觀鎖機制,也就意味着整個操做過程當中(從操做員讀 出數據、開始修改直至提交修改結果的全過程,甚至還包括操做員中途去煮咖啡的時間),數據庫記錄始終處於加鎖狀態,能夠想見,若是面對成百上千個併發,這 樣的狀況將致使災難性的後果。因此,採用悲觀鎖進行控制時必定要考慮清楚。

死鎖的第三種狀況

若是在事務中執行了一條不知足條件的update語句,則執行全表掃描,把行級鎖上升爲表級鎖,多個這樣的事務執行後,就很容易產生死鎖和阻塞。相似的情 況還有當表中的數據量很是龐大而索引建的過少或不合適的時候,使得常常發生全表掃描,最終應用系統會愈來愈慢,最終發生阻塞或死鎖。

解決方法:

SQL語句中不要使用太複雜的關聯多表的查詢;使用「執行計劃」對SQL語句進行分析,對於有全表掃描的SQL語句,創建相應的索引進行優化。
5.小結
整體上來講,產生內存溢出與鎖表都是因爲代碼寫的很差形成的,所以提升代碼的質量是最根本的解決辦法。有的人認爲先把功能實現,有BUG時再在測試階段進 行修正,這種想法是錯誤的。正如一件產品的質量是在生產製造的過程當中決定的,而不是質量檢測時決定的,軟件的質量在設計與編碼階段就已經決定了,測試只是 對軟件質量的一個驗證,由於測試不可能找出軟件中全部的BUG。

MyISAM 不支持行級鎖,換句話說,MyISAM 會對整張表加鎖,而不是針對行。同時,MyISAM 不支持事務和外鍵。MyISAM 可被壓縮,存儲空間較小,並且 MyISAM 在篩選大量數據時很是快。

InnoDB 是事務型引擎,當事務異常提交時,會被回滾。同時,InnoDB 支持行鎖。此外,InnoDB 須要更多存儲空間,會在內存中創建其專用的緩衝池用於高速緩衝數據和索引。InnoDB 支持自動奔潰恢復特性。

  • 數據庫索引的原理

    https://www.cnblogs.com/aspwebchh/p/6652855.html

  • 爲何要用 B-tree

    https://blog.csdn.net/bigtree_3721/article/details/73151472

    重要:https://www.kancloud.cn/kancloud/theory-of-mysql-index/41855

  • InnoDB索引和MyISAM索引的區別:

        一是主索引的區別,InnoDB的數據文件自己就是索引文件。而MyISAM的索引和數據是分開的。

        二是輔助索引的區別:InnoDB的輔助索引data域存儲相應記錄主鍵的值而不是地址。而MyISAM的輔助索引和主索引沒有多大區別。

  • 彙集索引與非彙集索引的區別

    https://www.cnblogs.com/s-b-b/p/8334593.html

  • limit 20000 加載很慢怎麼解決

http://uule.iteye.com/blog/2422189

當一個數據庫表過於龐大,LIMIT offset, length中的offset值過大,則SQL查詢語句會很是緩慢,你需增長order by,而且order by字段須要創建索引。

   若是使用子查詢去優化LIMIT的話,則子查詢必須是連續的,某種意義來說,子查詢不該該有where條件,where會過濾數據,使數據失去連續性。

   若是你查詢的記錄比較大,而且數據傳輸量比較大,好比包含了text類型的field,則能夠經過創建子查詢。

創建複合索引。

相關文章
相關標籤/搜索