MySQL面試題


MySQL面試題

1.數據庫三范式是什么?

  1. 第一范式(1NF):字段具有原子性,不可再分。(所有關系型數據庫系統都滿足第一范式數據庫表中的字段都是單一屬性的,不可再分)
  2. 第二范式(2NF)是在第一范式(1NF)的基礎上建立起來的,即滿足第二范式(2NF)必須先滿足第一范式(1NF)。要求數據庫表中的每個實例或行必須可以被惟一地區分。通常需要為表加上一個列,以存儲各個實例的惟一標識。這個惟一屬性列被稱為主關鍵字或主鍵。
  3. 滿足第三范式(3NF)必須先滿足第二范式(2NF)。簡而言之,第三范式(3NF)要求一個數據庫表中不包含已在其它表中已包含的非主關鍵字信息。 >所以第三范式具有如下特征: >>1. 每一列只有一個值 >>2. 每一行都能區分。 >>3. 每一個表都不包含其他表已經包含的非主關鍵字信息。

2.有哪些數據庫優化方面的經驗?

  1. 用PreparedStatement, 一般來說比Statement性能高:一個sql 發給服務器去執行,涉及步驟:語法檢查、語義分析, 編譯,緩存。
  2. 有外鍵約束會影響插入和刪除性能,如果程序能夠保證數據的完整性,那在設計數據庫時就去掉外鍵。
  3. 表中允許適當冗余,譬如,主題帖的回復數量和最后回復時間等
  4. UNION ALL 要比UNION快很多,所以,如果可以確認合並的兩個結果集中不包含重復數據且不需要排序時的話,那么就使用UNION ALL。 >>UNION和UNION ALL關鍵字都是將兩個結果集合並為一個,但這兩者從使用和效率上來說都有所不同。 >1. 對重復結果的處理:UNION在進行表鏈接后會篩選掉重復的記錄,Union All不會去除重復記錄。 >2. 對排序的處理:Union將會按照字段的順序進行排序;UNION ALL只是簡單的將兩個結果合並后就返回。

3.請簡述常用的索引有哪些種類?

  1. 普通索引: 即針對數據庫表創建索引
  2. 唯一索引: 與普通索引類似,不同的就是:MySQL數據庫索引列的值必須唯一,但允許有空值
  3. 主鍵索引: 它是一種特殊的唯一索引,不允許有空值。一般是在建表的時候同時創建主鍵索引
  4. 組合索引: 為了進一步榨取MySQL的效率,就要考慮建立組合索引。即將數據庫表中的多個字段聯合起來作為一個組合索引。

4.以及在mysql數據庫中索引的工作機制是什么?

數據庫索引,是數據庫管理系統中一個排序的數據結構,以協助快速查詢、更新數據庫表中數據。索引的實現通常使用B樹及其變種B+樹

5.MySQL的基礎操作命令:

  1. MySQL 是否處於運行狀態:Debian 上運行命令 service mysql status,在RedHat 上運行命令 service mysqld status
  2. 開啟或停止 MySQL 服務 :運行命令 service mysqld start 開啟服務;運行命令 service mysqld stop 停止服務
  3. Shell 登入 MySQL: 運行命令 mysql -u root -p
  4. 列出所有數據庫:運行命令 show databases;
  5. 切換到某個數據庫並在上面工作:運行命令 use databasename; 進入名為 databasename 的數據庫
  6. 列出某個數據庫內所有表: show tables;
  7. 獲取表內所有 Field 對象的名稱和類型 :describe table_name;

6.mysql的復制原理以及流程。

Mysql內建的復制功能是構建大型,高性能應用程序的基礎。將Mysql的數據分布到多個系統上去,這種分布的機制,是通過將Mysql的某一台主機的數據復制到其它主機(slaves)上,並重新執行一遍來實現的。 * 復制過程中一個服務器充當主服務器,而一個或多個其它服務器充當從服務器。主服務器將更新寫入二進制日志文件,並維護文件的一個索引以跟蹤日志循環。這些日志可以記錄發送到從服務器的更新。 當一個從服務器連接主服務器時,它通知主服務器在日志中讀取的最后一次成功更新的位置。從服務器接收從那時起發生的任何更新,然后封鎖並等待主服務器通知新的更新。 過程如下 1. 主服務器把更新記錄到二進制日志文件中。 2. 從服務器把主服務器的二進制日志拷貝到自己的中繼日志(replay log)中。 3. 從服務器重做中繼日志中的時間,把更新應用到自己的數據庫上。

7.mysql支持的復制類型?

  1. 基於語句的復制: 在主服務器上執行的SQL語句,在從服務器上執行同樣的語句。MySQL默認采用基於語句的復制,效率比較高。 一旦發現沒法精確復制時,會自動選着基於行的復制。
  2. 基於行的復制:把改變的內容復制過去,而不是把命令在從服務器上執行一遍. 從mysql5.0開始支持
  3. 混合類型的復制: 默認采用基於語句的復制,一旦發現基於語句的無法精確的復制時,就會采用基於行的復制。

8.mysql中myisam與innodb的區別?

  1. 事務支持 > MyISAM:強調的是性能,每次查詢具有原子性,其執行數度比InnoDB類型更快,但是不提供事務支持。 > InnoDB:提供事務支持事務,外部鍵等高級數據庫功能。 具有事務(commit)、回滾(rollback)和崩潰修復能力(crash recovery capabilities)的事務安全(transaction-safe (ACID compliant))型表。
  2. InnoDB支持行級鎖,而MyISAM支持表級鎖. >> 用戶在操作myisam表時,select,update,delete,insert語句都會給表自動加鎖,如果加鎖以后的表滿足insert並發的情況下,可以在表的尾部插入新的數據。
  3. InnoDB支持MVCC, 而MyISAM不支持
  4. InnoDB支持外鍵,而MyISAM不支持
  5. 表主鍵 > MyISAM:允許沒有任何索引和主鍵的表存在,索引都是保存行的地址。 > InnoDB:如果沒有設定主鍵或者非空唯一索引,就會自動生成一個6字節的主鍵(用戶不可見),數據是主索引的一部分,附加索引保存的是主索引的值。
  6. InnoDB不支持全文索引,而MyISAM支持。
  7. 可移植性、備份及恢復 > MyISAM:數據是以文件的形式存儲,所以在跨平台的數據轉移中會很方便。在備份和恢復時可單獨針對某個表進行操作。 > InnoDB:免費的方案可以是拷貝數據文件、備份 binlog,或者用 mysqldump,在數據量達到幾十G的時候就相對痛苦了
  8. 存儲結構 > MyISAM:每個MyISAM在磁盤上存儲成三個文件。第一個文件的名字以表的名字開始,擴展名指出文件類型。.frm文件存儲表定義。數據文件的擴展名為.MYD (MYData)。索引文件的擴展名是.MYI (MYIndex)。 > InnoDB:所有的表都保存在同一個數據文件中(也可能是多個文件,或者是獨立的表空間文件),InnoDB表的大小只受限於操作系統文件的大小,一般為2GB。

9.mysql中varchar與char的區別以及varchar(50)中的50代表的涵義?

  1. varchar與char的區別: char是一種固定長度的類型,varchar則是一種可變長度的類型.
  2. varchar(50)中50的涵義 : 最多存放50個字節
  3. int(20)中20的涵義: int(M)中的M indicates the maximum display width (最大顯示寬度)for integer types. The maximum legal display width is 255.

10.MySQL中InnoDB支持的四種事務隔離級別名稱,以及逐級之間的區別?

  1. Read Uncommitted(讀取未提交內容) >> 在該隔離級別,所有事務都可以看到其他未提交事務的執行結果。本隔離級別很少用於實際應用,因為它的性能也不比其他級別好多少。讀取未提交的數據,也被稱之為臟讀(Dirty Read)。
  2. Read Committed(讀取提交內容) >> 這是大多數數據庫系統的默認隔離級別(但不是MySQL默認的)。它滿足了隔離的簡單定義:一個事務只能看見已經提交事務所做的改變。這種隔離級別也支持所謂的不可重復讀(Nonrepeatable Read),因為同一事務的其他實例在該實例處理其間可能會有新的commit,所以同一select可能返回不同結果。
  3. Repeatable Read(可重讀) >> 這是MySQL的默認事務隔離級別,它確保同一事務的多個實例在並發讀取數據時,會看到同樣的數據行。不過理論上,這會導致另一個棘手的問題:幻讀(Phantom Read)。簡單的說,幻讀指當用戶讀取某一范圍的數據行時,另一個事務又在該范圍內插入了新行,當用戶再讀取該范圍的數據行時,會發現有新的“幻影” 行。InnoDB和Falcon存儲引擎通過多版本並發控制(MVCC,Multiversion Concurrency Control 間隙鎖)機制解決了該問題。注:其實多版本只是解決不可重復讀問題,而加上間隙鎖(也就是它這里所謂的並發控制)才解決了幻讀問題。
  4. Serializable(可串行化) >> 這是最高的隔離級別,它通過強制事務排序,使之不可能相互沖突,從而解決幻讀問題。簡言之,它是在每個讀的數據行上加上共享鎖。在這個級別,可能導致大量的超時現象和鎖競爭。 <table> <thead> <tr> <th align="left">隔離級別</th> <th align="left">臟讀(Dirty Read)</th> <th align="left">不可重復讀(NonRepeatable Read)</th> <th align="left">幻讀(Phantom Read)</th> </tr> </thead> <tbody><tr> <td align="left">未提交讀(Read uncommitted)</td> <td align="left">可能</td> <td align="left">可能</td> <td align="left">可能</td> </tr> <tr> <td align="left">已提交讀(Read committed)</td> <td align="left">不可能</td> <td align="left">可能</td> <td align="left">可能</td> </tr> <tr> <td align="left">可重復讀(Repeatable read)</td> <td align="left">不可能</td> <td align="left">不可能</td> <td align="left">可能</td> </tr> <tr> <td align="left">可串行化(SERIALIZABLE)</td> <td align="left">不可能</td> <td align="left">不可能</td> <td align="left">不可能</td> </tr> </tbody></table>

11.表中有大字段X(例如:text類型),且字段X不會經常更新,以讀為為主,將該字段拆成子表好處是什么?

如果字段里面有大字段(text,blob)類型的,而且這些字段的訪問並不多,這時候放在一起就變成缺點了。 MYSQL數據庫的記錄存儲是按行存儲的,數據塊大小又是固定的(16K),每條記錄越小,相同的塊存儲的記錄就越多。此時應該把大字段拆走,這樣應付大部分小字段的查詢時,就能提高效率。當需要查詢大字段時,此時的關聯查詢是不可避免的,但也是值得的。拆分開后,對字段的UPDAE就要UPDATE多個表了

12.MySQL中InnoDB引擎的行鎖是通過加在什么上完成(或稱實現)的?

InnoDB行鎖是通過給索引上的索引項加鎖來實現的,這一點MySQL與Oracle不同,后者是通過在數據塊中對相應數據行加鎖來實現的。InnoDB這種行鎖實現特點意味着:只有通過索引條件檢索數據,InnoDB才使用行級鎖,否則,InnoDB將使用表鎖!

13.MySQL中控制內存分配的全局參數,有哪些?

  1. Keybuffersize: > * keybuffersize指定索引緩沖區的大小,它決定索引處理的速度,尤其是索引讀的速度。通過檢查狀態值Keyreadrequests和Keyreads,可以知道keybuffersize設置是否合理。比例keyreads /keyreadrequests應該盡可能的低,至少是1:100,1:1000更好(上述狀態值可以使用SHOW STATUS LIKE ‘keyread%'獲得)。 > * keybuffersize只對MyISAM表起作用。即使你不使用MyISAM表,但是內部的臨時磁盤表是MyISAM表,也要使用該值。可以使用檢查狀態值createdtmpdisktables得知詳情。對於1G內存的機器,如果不使用MyISAM表,推薦值是16M(8-64M) > * keybuffersize設置注意事項 >>>1. 單個keybuffer的大小不能超過4G,如果設置超過4G,就有可能遇到下面3個bug: >>>>> http://bugs.mysql.com/bug.php?id=29446 <br /> >>>>> http://bugs.mysql.com/bug.php?id=29419 <br /> >>>>> http://bugs.mysql.com/bug.php?id=5731 <br /> >>>2. 建議keybuffer設置為物理內存的1/4(針對MyISAM引擎),甚至是物理內存的30%~40%,如果keybuffersize設置太大,系統就會頻繁的換頁,降低系統性能。因為MySQL使用操作系統的緩存來緩存數據,所以我們得為系統留夠足夠的內存;在很多情況下數據要比索引大得多。 >>>3. 如果機器性能優越,可以設置多個keybuffer,分別讓不同的keybuffer來緩存專門的索引

  2. innodbbufferpool_size > 表示緩沖池字節大小,InnoDB緩存表和索引數據的內存區域。mysql默認的值是128M。最大值與你的CPU體系結構有關,在32位操作系統,最大值是 4294967295 (2^32-1) ,在64 位操作系統,最大值為18446744073709551615 (2^64-1)。 > 在32位操作系統中,CPU和操作系統實用的最大大小低於設置的最大值。如果設定的緩沖池的大小大於1G,設置innodbbufferpoolinstances的值大於1. > * 數據讀寫在內存中非常快, innodbbufferpoolsize 減少了對磁盤的讀寫。 當數據提交或滿足檢查點條件后才一次性將內存數據刷新到磁盤中。然而內存還有操作系統或數據庫其他進程使用, 一般設置 buffer pool 大小為總內存的 3/4 至 4/5。 若設置不當, 內存使用可能浪費或者使用過多。 對於繁忙的服務器, buffer pool 將划分為多個實例以提高系統並發性, 減少線程間讀寫緩存的爭用。buffer pool 的大小首先受 innodbbufferpool_instances 影響, 當然影響較小。

  3. querycachesize > 當mysql接收到一條select類型的query時,mysql會對這條query進行hash計算而得到一個hash值,然后通過該hash值到query cache中去匹配,如果沒有匹配中,則將這個hash值存放在一個hash鏈表中,同時將query的結果集存放進cache中,存放hash值的鏈表的每一個hash節點存放了相應query結果集在cache中的地址,以及該query所涉及到的一些table的相關信息;如果通過hash值匹配到了一樣的query,則直接將cache中相應的query結果集返回給客戶端。如果mysql任何一個表中的任何一條數據發生了變化,便會通知query cache需要與該table相關的query的cache全部失效,並釋放占用的內存地址。 > query cache優缺點 >> 1. query語句的hash計算和hash查找帶來的資源消耗。mysql會對每條接收到的select類型的query進行hash計算然后查找該query的cache是否存在,雖然hash計算和查找的效率已經足夠高了,一條query所帶來的消耗可以忽略,但一旦涉及到高並發,有成千上萬條query時,hash計算和查找所帶來的開銷就的重視了; >> 2. query cache的失效問題。如果表變更比較頻繁,則會造成query cache的失效率非常高。表變更不僅僅指表中的數據發生變化,還包括結構或者索引的任何變化; >> 3. 對於不同sql但同一結果集的query都會被緩存,這樣便會造成內存資源的過渡消耗。sql的字符大小寫、空格或者注釋的不同,緩存都是認為是不同的sql(因為他們的hash值會不同); >> 4. 相關參數設置不合理會造成大量內存碎片,相關的參數設置會稍后介紹。

  4. readbuffersize >是MySQL讀入緩沖區大小。對表進行順序掃描的請求將分配一個讀入緩沖區,MySQL會為它分配一段內存緩沖區。readbuffersize變量控制這一緩沖區的大小。如果對表的順序掃描請求非常頻繁,並且你認為頻繁掃描進行得太慢,可以通過增加該變量值以及內存緩沖區大小提高其性能。

14.若一張表中只有一個字段VARCHAR(N)類型,utf8編碼,則N最大值為多少(精確到數量級即可)?

由於utf8的每個字符最多占用3個字節。而MySQL定義行的長度不能超過65535,因此N的最大值計算方法為:(65535-1-2)/3。減去1的原因是實際存儲從第二個字節開始,減去2的原因是因為要在列表長度存儲實際的字符長度,除以3是因為utf8限制:每個字符最多占用3個字節。

15. [SELECT *] 和[SELECT 全部字段]的2種寫法有何優缺點?

  1. 前者要解析數據字典,后者不需要
  2. 結果輸出順序,前者與建表列順序相同,后者按指定字段順序。
  3. 表字段改名,前者不需要修改,后者需要改
  4. 后者可以建立索引進行優化,前者無法優化
  5. 后者的可讀性比前者要高

16.HAVNG 子句 和 WHERE的異同點?

  1. 語法上:where 用表中列名,having用select結果別名
  2. 影響結果范圍:where從表讀出數據的行數,having返回客戶端的行數
  3. 索引:where 可以使用索引,having不能使用索引,只能在臨時結果集操作
  4. where后面不能使用聚集函數,having是專門使用聚集函數的。

17.MySQL當記錄不存在時insert,當記錄存在時update,語句怎么寫?

INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1;

18.MySQL的insert和update的select語句語法

`SQL insert into student (stuid,stuname,deptid) select 10,'xzm',3 from student where stuid > 8;

update student a inner join student b on b.stuID=10 set a.stuname=concat(b.stuname, b.stuID) where a.stuID=10 ; `


免責聲明!

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



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