java【mysql】面試題
一、為什麼網際網路公司一般選擇mysql而不是Oracle?
免費、流行、夠用。
二、資料庫的三正規化是什麼?什麼是反模式?
資料庫正規化是為解決關係資料庫中資料冗餘、更新異常、插入異常、刪除異常問題而引入的。簡單的理解,資料庫正規化可以避免資料冗餘,減少資料庫的空間,並且減輕維護資料完整性的麻煩。
第一正規化:
強調的是資料庫中每個表中的屬性,具有原子性,不再進行分解。
比如:如果涉及到設計一張活動表,這個表中,包含了屬性(活動id,活動名稱,活動地址等屬性)其中,活動名稱符合原子性,但是活動地址還可以進行分割成活動國家,活動省,活動地區,活動市等等。活動地址這個屬性就不滿足第一正規化。
第二正規化:
強調的是資料庫中的資料必須有唯一主鍵,並且這個表中的非主鍵欄位,都必須完全依賴主鍵。不能存在部分依賴。
比如說:版本表(有四個欄位:版本編碼,版本名稱,產品編碼,產品名稱),其中主鍵是(版本編碼、產品編碼),那麼這個場景中,資料庫設計並不符合第二正規化,因為產品名稱依賴於產品編碼。存在部分依賴,所以,為了使其滿足第二正規化,可以改造成兩個表()產品表和編碼表。
第三正規化:
強調屬性冗餘性的約束,即非主鍵列必須直接依賴於主鍵。
比如:訂單表:(訂單編碼、顧客編碼、顧客名稱),其中主鍵是(訂單編碼、顧客編碼、顧客名稱),其中主鍵是(訂單編號),這個場景中,顧客編碼、顧客名稱都完全依賴於主鍵,因此符合第二正規化,但是顧客名稱依賴於顧客比那嗎,從而間接依賴於主鍵,所以不滿足第三正規化,可以拆分成兩個表:訂單表(訂單編碼、顧客編碼)和顧客表(顧客編碼、顧客名稱),拆分後的資料庫設計,就可以完全滿足第三正規化的要求了。
注意事項:第二正規化的側重點是非主鍵列是否完全依賴於主鍵,還是依賴於主鍵的一部分。第三正規化的側重點是非主鍵列是直接依賴於主鍵,還是直接依賴於非主鍵列。
反模式:
雖然正規化可以避免資料冗餘,減少資料庫的空間,減輕維護資料的完整性的麻煩。
然而,通過資料庫正規化化設計,將導致資料庫業務涉及的表變多,並且可能需要將涉及的業務表進行多表連線查詢,這樣將導致效能變差,且不利於分庫分表。因此,處於效能有限的考量,可能在資料庫的結構中需要使用反模式的設計,即空間獲取時間,採取資料冗餘的方式避免表之間的關聯查詢。至於資料一致性問題,因為難以滿足資料強一致性,一般情況下,使儲存資料儘可能達到使用者一致,保證系統經過一段較短的時間的自我恢復和修正,資料最終達到一致。
需要謹慎使用反模式設計資料庫。一般情況下,儘可能使用正規化化的資料庫設計。因為正規化化的資料設計能讓產品更加靈活,並且能在資料庫層保持資料完整性。
有的時候,提升效能最好的方法是在同一張表中保持冗餘資料,如果能容許少量的髒資料,建立一張完全獨立的彙總表或者快取表是非常好的方法。舉個例子,設計一張“下載次數表“來快取下載次數資訊,可使在海量資料的情況下,提高查詢總數資訊的速度。
另外一個比較典型的場景,處於拓展性考慮,可能會使用BLOB和TEXT型別的列儲存JSON結構的資料,這樣的好處在於可以在任何時候,將新的屬性新增到這個欄位中。而不需要更改表的結構,但是,這個設計的缺點也比較明顯,就是需要獲取整個欄位內容進行解碼來獲取指定的屬性,並且無法使用所以、排序、聚和等操作。因此,需要考慮更加複雜的使用場景,更加建議使用MongoDB這樣的文件型資料庫。
三、MySql的資料型別有那些?
數值、日期/時間和字串型別。
MySql中varchar與char的區別?varchar(50)中的50代表什麼含義?
1.Varchar與char的區別,char是一種固定長度的型別,varchar則是一種可變長度的型別。
2.varchar(50)中50的涵義最多可以存放50個字元,varchar(50)和varchar(200)儲存hello所佔的空間一樣,但是後者在排序時會消耗更多的記憶體。因為order By clo採用的fixed_length計算col長度(memory引擎也是一樣。)
所以,實際場景下,選擇合適的varchar長度還是必要的。
int(11)中的11代表了什麼含義?
int(11)中的11,不影響欄位儲存範圍,只是影響展示效果。
金額(金錢)相關的資料,選擇什麼資料型別?
- 方式一、使用int或者bigint型別,如果需要儲存到分的維度,需要*100進行放大。
- 方式二、使用decimal型別,避免精度丟失。如果使用java語言時,需要使用bigDecimal進行對應
四、一張表,裡面有ID自增主鍵,當insert17條資料之後,刪除了第15,16,17條資料,再把MySql重啟,再insert一條,這條記錄的id是多少?
- 一般情況下,我們建立的表的型別是innoDB,如果新增一條記錄(不重啟Mysql情況下)這時的ID是18,但是如果重新啟動的話,這條記錄就是15,因為InnooDB表只把自增主鍵的最大值記錄到記憶體中,所以重啟資料庫或者對錶OPTIMIZE操作,都會使最大ID丟失。
- 但是如果我們使用的表的型別是MYISAM,那麼這條記錄的ID就是18,因為MYISAM表會把自增主鍵的最大ID記錄到資料檔案裡面,重啟MYISAM後,自增主鍵的最大ID也不會丟失。
五、表中有大欄位X(例如:text型別),且欄位X不會經常更新,以讀為主,請問您是選擇拆成子表,還是繼續放在一起?寫出您的理由。
- 拆帶來的問題:連線消耗+儲存拆分空間。
如果能容忍拆分帶來的空間問題,拆的話,最好和經常要查詢的表的主鍵再物理結構上放置在一起(分割槽)順序IO,減少連線消耗,最後這是一個文字列再加上一個全文索引來儘量抵消連線消耗。
- 不拆可能帶來的問題:查詢效能
如果能容忍不拆分帶來的查詢效能損失的話,上面的方案再某個極致條件下可能會出現問題,那麼不拆就是最好的選擇。
實際場景下,例如說商品表資料量比較大的情況下,會將商品描述單獨儲存到一個表中。即使用拆的方案。
六、MYSQL常用的儲存引擎有哪些?
- InnoDB
- MyISAM
- MRG_MYISAM
- MEMORY
- CSV
- ARCHIVE
- BLACKHOLE
- PERFORMEANCE_SCHEMA
- FEDERATED
- 。。。
如何選擇合適的儲存引擎?
提供幾個選擇的標準,然後按照標準來進行選擇合適的儲存引擎,也可以根據常用引擎對比,來選擇你使用的儲存引擎,使用哪種引擎需要根據需求靈活選擇,一個數據庫中多個表可以使用不同的引擎滿足各種效能與實際需求。使用合適的儲存引擎,將會提高整個資料庫的效能。
- 1.是否需要支援事務。
- 2.對索引和快取的支援。
- 3.是否需要使用熱備
- 4.崩潰恢復,能否接受崩潰
- 5.儲存的限制。
- 6.是否需要外來鍵支援。
目前,MySQL預設的儲存引擎是InnoDB,並且也是最主流的選擇。主要原因是:
- 1.支援事務
- 2.支援行級鎖和表級鎖,能支援更多的併發量。
- 3.查詢不加鎖,完全不影響效能。
- 4.支援崩潰後恢復。
在Mysql5.1以及之前的版本,預設的儲存引擎是MYISAM,但是目前已經不再更新,且它有幾個比較關鍵的缺點:
- 不支援事務
- 使用表級鎖,如果資料量大,一個插入操作鎖定表後,其他請求都將阻塞。
Innodb的四大特性?
- 插入快取,
- 二次寫
- 自適應雜湊索引
- 預讀
六、為什麼select count(*) from table 在InnoDB比MyISAM慢?
對於SELECT COUNT(*) FROM table語句,在沒有WHERE條件的情況下,InnoDB比MyISAM可能會慢很多,尤其在大表的情況下。因為,InnoDB是去實時統計結果,會全表掃描;而MyISAM內部維持了一個計數器,預存了結果,所以直接返回即可。 各種不同MySQL版本的Innodb的改進? MySQL5.6下Innodb引擎的主要改進:- 1. online DDL
- 2. memcached NoSQL介面
- 3. transportable tablespace(alter table discard/import tablespace)
- 4. MySQL正常關閉時,可以dump出buffffer pool的(space,page_no),重啟時reload,加快預熱速度
- 5.索引和表的統計資訊持久化到mysql.innodb_table_stats和mysql.innodb_index_stats,可提供穩定的執行計劃
- 6. Compressed row format支援壓縮表
- 1、修改varchar欄位長度有時可以使用
- 2、Buffffer pool支援線上改變大小
- 3、Buffffer pool支援匯出部分比例
- 4、支援新建innodb tablespace,並可以在其中建立多張表
- 5、磁碟臨時表採用innodb儲存,並且儲存在innodb temp tablespace裡面,以前是MyISAM儲存
- 6、透明表空間壓縮功能
七、什麼是索引?
MySQL中儲存引擎使用類似的方式進行查詢,先去索引中查詢對應的值,然後根據匹配的索引找到對應的資料行。
索引有什麼好處?
- 1.提高資料的檢索速度,降低資料庫IO成本:使用索引的意義就是通過縮小表中需要查詢的記錄的數目從而加快搜索的速度。
- 2.降低資料排序的成本,降低CPU消耗:索引之所以查的快,是因為先將資料排好序,若該欄位正好需要排序,則正好降低了排序的成本。
索引有什麼壞處?
- 1.佔用儲存空間:索引實際上也是一張表,記錄了主鍵和索引欄位,一般以索引檔案的形式儲存在磁碟上。
- 2.降低更新表的速度:表的資料發生了變化,對應的索引也需要一起變更,從而減低的更新速度,否則索引指向的物理資料可能不對,這也是索引失效的原因之一。
索引的使用場景?
- 對非常小的表,大部分情況下全表掃描效率更高。
- 對中大型表,索引非常有效。
- 特大型的表,建立和使用索引的代價隨著增長,可以使用分割槽技術來解決。
索引的型別?
索引,都是實現在儲存引擎層的。主要有六種型別:
- 1、普通索引:最基本的索引,沒有任何約束
- 2、唯一索引:與普通索引類似,但具有唯一性約束。
- 3、主鍵索引:特殊的唯一索引,不允許有空值。
- 4、複合索引:將多個列組合在一起建立索引,可以覆蓋多個列
- 5、外來鍵索引:只有InnoDB型別的表才可以使用外來鍵索引,保證資料的一致性,完整性和實現級聯操作。
- 6、全文索引:MySQL自帶的全文索引只能用於InnoDB、MyISAM,並且只能對引文進行全文檢索,一般使用全文索引引擎。
Mysql索引的“建立”原則?
- 1、最適合的索引的列是出現在where子句中的列,或者連線子句中的列。而不是出現在Select關鍵字後的列。
- 2、索引列的基數越大,索引效果越好。
- 3、根據情況建立複合索引,複合索引可以提高查詢效率。
- 4、避免建立過多的索引,索引會額外佔用磁碟空間,降低寫操作效率。
- 5、主鍵儘可能選擇較短的資料型別,可以有效減少索引的磁碟佔用提高查詢效率。
- 6、對字串進行索引,應該定製一個字首長度,可以節省大量的索引空間。
MySQL索引的“使用”注意事項?
- 1.應儘量避免在where子句中使用!=或者<>操作符,否則將引擎放棄使用索引而進行全表掃描。優化器將無法通過索引來確定將要命中的行數,因此需要搜尋該表的所有行。
- 2.應儘量避免在where子句中使用or連線,否則將導致引擎放棄使用索引而進行全表掃描,如:SELECT id FROM t WHERE num = 10 OR num = 20。
- 3.應儘量避免在where子句中對欄位進行表示式操作,這將導致引擎放棄使用索引而進行全表掃描。
- 4.應儘量避免在where子句中對欄位進行函式操作,這將導致引擎放棄使用索引而進行全表掃描。
- 5.不要在where子句中的==左邊進行函式、算數運算或者其他表示式運算,否則系統將可能無法正確使用索引。
- 6.複合索引怎訊字首原則。
- 7.如果mysql評估使用索引比全表掃描更慢,會放棄使用索引。如果此時想要索引,可以在語句中新增強制索引。
- 8.列型別是字串型別,查詢時一定要給值加引號,否則索引將失效。
- 9.like查詢,%不能在前,因為無法使用索引,如果需要模糊匹配,可以使用全文索引。
以下三條SQL如何建立索引,只建一條怎麼建?
WHERE a = 1 AND b = 1
WHERE b = 1
WHERE b = 1 ORDER BY time DESC
- 以順序b , a, time建立複合索引,CREATE INDEX table1_b_a_time ON index_test01(b, a, time)。
- 對於第一條SQL,因為最新MySQL版本會優化WHERE子句後面的列順序,以匹配複合索引順序。
想知道一個查詢用到了那個索引,如何檢視?
EXPLAIN顯示了MYSQL如何使用索引來處理SELECT語句以及連線表,可以幫助選擇更好的索引和寫出更優化的查詢語句。
使用方法,在SELECT語句前加上EXPLAIN就可以了。
MYSQL索引的原理?
-----
MySQl有那些索引?
B-Tree索引
Hash索引
什麼是B-Tree索引?
B-Tree是為磁碟等外儲存裝置設計的一種平衡查詢樹,因此在講B-Tree之前先了解一卡磁碟的相關知識。
- 系統從磁碟讀取資料到記憶體時以磁碟塊(block)為基本單位的,位於同一個磁碟塊中的資料會被一次性讀取出來,而不是需要什麼取什麼。
- InnoDB儲存引擎中有頁(Page)的概念,頁是其磁碟管理的最小單位。Innodb儲存引擎中預設每個頁的大小為16kb,可通過引數innodb_page_size將頁的大小設定為4K、8K、16K,在Mysql中可通過如下命令檢視頁的大小:
Mysql> show variables list 'innodb_page_size'
- 而系統一個磁碟塊的儲存空間往往沒有那麼大,因此innodb每次申請磁碟空間時都會是若干個地址連續磁碟塊來達到頁的大小16kb。Innodb在把磁碟資料讀入到磁碟時會以頁為基本單位,在查詢資料時如果一個頁中的每條資料都能有助於定位資料記錄的位置,這將會減少磁碟IO次數,提高查詢效率。
B-Tree結構的資料可以讓系統高效的找到資料所在的磁碟塊,為了描述B-Tree,首先定一條記錄為一個二元組【key,data】,key為記錄的鍵值,對應表中的主鍵值,data為一行記錄中除主鍵外的資料。對於不同的記錄,key值互不相同。
一棵m階的B-Tree有如下特性:
- 1.每個節點最多有m個孩子。
- 除了根節點和葉子節點外,其他每個節點至少有ceil(m/2)個孩子。
- 若根節點不是葉子節點,則至少有2個孩子。
- 2.所有葉子節點都在同一層,且不包含其他關鍵字資訊。
- 3.每個非葉子節點包含n個關鍵字資訊(p0,p1,p2,pn)