一、數據庫知識(通用)篇
1.說說主鍵、外鍵、超鍵、候選鍵
超鍵:在關系中能唯一標識元組的屬性集稱為關系模式的超鍵。一個屬性可以為作為一個超鍵,多個屬性組合在一起也可以作為一個超鍵。超鍵包含候選鍵和主鍵。候選鍵:是最小超鍵,即沒有冗余元素的超鍵。主鍵:數據庫表中對儲存數據對象予以唯一和完整標識的數據列或屬性的組合。一個數據列只能有一個主鍵,且主鍵的取值不能缺失,即不能為空值(Null)。外鍵:在一個表中存在的另一個表的主鍵稱此表的外鍵。
2.為什么用自增列作為主鍵?
如果我們定義了主鍵(PRIMARY KEY),那么InnoDB會選擇主鍵作為聚集索引、如果沒有顯式定義主鍵,則InnoDB會選擇第一個不包含有NULL值的唯一索引作為主鍵索引、如果也沒有這樣的唯一索引,則InnoDB會選擇內置6字節(jié)長的ROWID作為隱含的聚集索引(ROWID隨著行記錄的寫入而主鍵遞增,這個ROWID不像ORACLE的ROWID那樣可引用,是隱含的)。數據記錄本身被存于主索引(一顆B+Tree)的葉子節(jié)點上。這就要求同一個葉子節(jié)點內(大小為一個內存頁或磁盤頁)的各條數據記錄按主鍵順序存放,因此每當有一條新的記錄插入時,MySQL會根據其主鍵將其插入適當的節(jié)點和位置,如果頁面達到裝載因子(InnoDB默認為15/16),則開辟一個新的頁(節(jié)點)如果表使用自增主鍵,那么每次插入新的記錄,記錄就會順序添加到當前索引節(jié)點的后續(xù)位置,當一頁寫滿,就會自動開辟一個新的頁如果使用非自增主鍵(如果身份證號或學號等),由于每次插入主鍵的值近似于隨機,因此每次新記錄都要被插到現(xiàn)有索引頁的中間某個位置,此時MySQL不得不為了將新記錄插到合適位置而移動數據,甚至目標頁面可能已經被回寫到磁盤上而從緩存中清掉,此時又要從磁盤上讀回來,這增加了很多開銷,同時頻繁的移動、分頁操作造成了大量的碎片,得到了不夠緊湊的索引結構,后續(xù)不得不通過OPTIMIZE TABLE來重建表并優(yōu)化填充頁面。
3.觸發(fā)器的作用是什么?
觸發(fā)器是一種特殊的存儲過程,主要是通過事件來觸發(fā)而被執(zhí)行的。它可以強化約束,來維護數據的完整性和一致性,可以跟蹤數據庫內的操作從而不允許未經許可的更新和變化??梢月?lián)級運算。如,某表上的觸發(fā)器上包含對另一個表的數據操作,而該操作又會導致該表觸發(fā)器被觸發(fā)。
4.什么是存儲過程?用什么來調用?
存儲過程是一個預編譯的SQL語句,優(yōu)點是允許模塊化的設計,就是說只需創(chuàng)建一次,以后在該程序中就可以調用多次。如果某次操作需要執(zhí)行多次SQL,使用存儲過程比單純SQL語句執(zhí)行要快。調用:1)可以用一個命令對象來調用存儲過程。2)可以供外部程序調用,比如:java程序。
5.說說存儲過程的優(yōu)缺點?
優(yōu)點:1)存儲過程是預編譯過的,執(zhí)行效率高。2)存儲過程的代碼直接存放于數據庫中,通過存儲過程名直接調用,減少網絡通訊。3)安全性高,執(zhí)行存儲過程需要有一定權限的用戶。4)存儲過程可以重復使用,可減少數據庫開發(fā)人員的工作量。缺點:移植性差
6.說說存儲過程與函數的區(qū)別
(1)存儲過程用戶在數據庫中完成特定操作或者任務(如插入,刪除等),函數用于返回特定的數據。(2)存儲過程聲明用procedure,函數用function。(3)存儲過程不需要返回類型,函數必須要返回類型。(4)存儲過程可作為獨立的pl-sql執(zhí)行,函數不能作為獨立的plsql執(zhí)行,必須作為表達式的一部分。(5)存儲過程只能通過out和in/out來返回值,函數除了可以使用out,in/out以外,還可以使用return返回值。(6)sql語句(DML或SELECT)中不可用調用存儲過程,而函數可以。
7.什么叫視圖?游標是什么?
視圖:是一種虛擬的表,具有和物理表相同的功能??梢詫σ晥D進行增,改,查,操作,試圖通常是有一個表或者多個表的行或列的子集。對視圖的修改會影響基本表。它使得我們獲取數據更容易,相比多表查詢。游標:是對查詢出來的結果集作為一個單元來有效的處理。游標可以定在該單元中的特定行,從結果集的當前行檢索一行或多行??梢詫Y果集當前行做修改。一般不使用游標,但是需要逐條處理數據的時候,游標顯得十分重要。
8.視圖的優(yōu)缺點有哪些?
優(yōu)點:1對數據庫的訪問,因為視圖可以有選擇性的選取數據庫里的一部分。2)用戶通過簡單的查詢可以從復雜查詢中得到結果。3)維護數據的獨立性,試圖可從多個表檢索數據。4)對于相同的數據可產生不同的視圖。缺點:性能:查詢視圖時,必須把視圖的查詢轉化成對基本表的查詢,如果這個視圖是由一個復雜的多表查詢所定義,那么,那么就無法更改數據
9.說說drop、truncate、 delete區(qū)別
最基本:1) drop直接刪掉表。2) truncate刪除表中數據,再插入時自增長id又從1開始。3) delete刪除表中數據,可以加where字句。
(1) DELETE語句執(zhí)行刪除的過程是每次從表中刪除一行,并且同時將該行的刪除操作作為事務記錄在日志中保存以便進行進行回滾操作。TRUNCATE TABLE 則一次性地從表中刪除所有的數據并不把單獨的刪除操作記錄記入日志保存,刪除行是不能恢復的。并且在刪除的過程中不會激活與表有關的刪除觸發(fā)器。執(zhí)行速度快。(2) 表和索引所占空間。當表被TRUNCATE 后,這個表和索引所占用的空間會恢復到初始大小,而DELETE操作不會減少表或索引所占用的空間。drop語句將表所占用的空間全釋放掉。(3) 一般而言,drop > truncate > delete(4) 應用范圍。TRUNCATE 只能對TABLE;DELETE可以是table和view(5) TRUNCATE 和DELETE只刪除數據,而DROP則刪除整個表(結構和數據)。(6) truncate與不帶where的delete :只刪除數據,而不刪除表的結構(定義)drop語句將刪除表的結構被依賴的約束(constrain),觸發(fā)器(trigger)索引(index);依賴于該表的存儲過程/函數將被保留,但其狀態(tài)會變?yōu)椋篿nvalid。(7) delete語句為DML(data maintain Language),這個操作會被放到 rollback segment中,事務提交后才生效。如果有相應的 tigger,執(zhí)行的時候將被觸發(fā)。(8) truncate、drop是DLL(data define language),操作立即生效,原數據不放到 rollback segment中,不能回滾。(9) 在沒有備份情況下,謹慎使用 drop 與 truncate。要刪除部分數據行采用delete且注意結合where來約束影響范圍。回滾段要足夠大。要刪除表用drop;若想保留表而將表中數據刪除,如果與事務無關,用truncate即可實現(xiàn)。如果和事務有關,或老師想觸發(fā)trigger,還是用delete。(10) Truncate table 表名 速度快,而且效率高,因為:?truncate table 在功能上與不帶 WHERE 子句的 DELETE 語句相同:二者均刪除表中的全部行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系統(tǒng)和事務日志資源少。DELETE 語句每次刪除一行,并在事務日志中為所刪除的每行記錄一項。TRUNCATE TABLE 通過釋放存儲表數據所用的數據頁來刪除數據,并且只在事務日志中記錄頁的釋放。(11) TRUNCATE TABLE 刪除表中的所有行,但表結構及其列、約束、索引等保持不變。新行標識所用的計數值重置為該列的種子。如果想保留標識計數值,請改用 DELETE。如果要刪除表定義及其數據,請使用 DROP TABLE 語句。(12) 對于由 FOREIGN KEY 約束引用的表,不能使用 TRUNCATE TABLE,而應使用不帶 WHERE 子句的 DELETE 語句。由于 TRUNCATE TABLE 不記錄在日志中,所以它不能激活觸發(fā)器。
10.什么是臨時表,臨時表什么時候刪除?
臨時表可以手動刪除:DROP TEMPORARY TABLE IF EXISTS temp_tb;臨時表只在當前連接可見,當關閉連接時,MySQL會自動刪除表并釋放所有空間。因此在不同的連接中可以創(chuàng)建同名的臨時表,并且操作屬于本連接的臨時表。創(chuàng)建臨時表的語法與創(chuàng)建表語法類似,不同之處是增加關鍵字TEMPORARY,如:
CREATE TEMPORARY TABLE tmp_table (
? ? ? ? NAME VARCHAR (10) NOT NULL,
? ? ? ? time date NOT NULL
);
select * from tmp_table;
11.說說非關系型數據庫和關系型數據庫區(qū)別,優(yōu)勢比較?
非關系型數據庫的優(yōu)勢:性能:NOSQL是基于鍵值對的,可以想象成表中的主鍵和值的對應關系,而且不需要經過SQL層的解析,所以性能非常高??蓴U展性:同樣也是因為基于鍵值對,數據之間沒有耦合性,所以非常容易水平擴展。關系型數據庫的優(yōu)勢:復雜查詢:可以用SQL語句方便的在一個表以及多個表之間做非常復雜的數據查詢。事務支持:使得對于安全性能很高的數據訪問要求得以實現(xiàn)。其他:1.對于這兩類數據庫,對方的優(yōu)勢就是自己的弱勢,反之亦然。2.NOSQL數據庫慢慢開始具備SQL數據庫的一些復雜查詢功能,比如MongoDB。3.對于事務的支持也可以用一些系統(tǒng)級的原子操作來實現(xiàn)例如樂觀鎖之類的方法來曲線救國,比如Redis set nx。
12.什么是數據庫范式,根據某個場景設計數據表?
第一范式:(確保每列保持原子性)所有字段值都是不可分解的原子值。第一范式是最基本的范式。如果數據庫表中的所有字段值都是不可分解的原子值,就說明該數據庫表滿足了第一范式。第一范式的合理遵循需要根據系統(tǒng)的實際需求來定。比如某些數據庫系統(tǒng)中需要用到“地址”這個屬性,本來直接將“地址”屬性設計成一個數據庫表的字段就行。但是如果系統(tǒng)經常會訪問“地址”屬性中的“城市”部分,那么就非要將“地址”這個屬性重新拆分為省份、城市、詳細地址等多個部分進行存儲,這樣在對地址中某一部分操作的時候將非常方便。這樣設計才算滿足了數據庫的第一范式,如下表所示。上表所示的用戶信息遵循了第一范式的要求,這樣在對用戶使用城市進行分類的時候就非常方便,也提高了數據庫的性能。第二范式:(確保表中的每列都和主鍵相關)在一個數據庫表中,一個表中只能保存一種數據,不可以把多種數據保存在同一張數據庫表中。第二范式在第一范式的基礎之上更進一層。第二范式需要確保數據庫表中的每一列都和主鍵相關,而不能只與主鍵的某一部分相關(主要針對聯(lián)合主鍵而言)。也就是說在一個數據庫表中,一個表中只能保存一種數據,不可以把多種數據保存在同一張數據庫表中。比如要設計一個訂單信息表,因為訂單中可能會有多種商品,所以要將訂單編號和商品編號作為數據庫表的聯(lián)合主鍵。第三范式:(確保每列都和主鍵列直接相關,而不是間接相關) 數據表中的每一列數據都和主鍵直接相關,而不能間接相關。第三范式需要確保數據表中的每一列數據都和主鍵直接相關,而不能間接相關。比如在設計一個訂單數據表的時候,可以將客戶編號作為一個外鍵和訂單表建立相應的關系。而不可以在訂單表中添加關于客戶其它信息(比如姓名、所屬公司等)的字段。BCNF:符合3NF,并且,主屬性不依賴于主屬性。若關系模式屬于第二范式,且每個屬性都不傳遞依賴于鍵碼,則R屬于BC范式。通常BC范式的條件有多種等價的表述:每個非平凡依賴的左邊必須包含鍵碼;每個決定因素必須包含鍵碼。BC范式既檢查非主屬性,又檢查主屬性。當只檢查非主屬性時,就成了第三范式。滿足BC范式的關系都必然滿足第三范式。還可以這么說:若一個關系達到了第三范式,并且它只有一個候選碼,或者它的每個候選碼都是單屬性,則該關系自然達到BC范式。一般,一個數據庫設計符合3NF或BCNF就可以了。第四范式:要求把同一表內的多對多關系刪除。第五范式:從最終結構重新建立原始結構。
13.什么是 內連接、外連接、交叉連接、笛卡爾積等?
內連接: 只連接匹配的行左外連接: 包含左邊表的全部行(不管右邊的表中是否存在與它們匹配的行),以及右邊表中全部匹配的行右外連接: 包含右邊表的全部行(不管左邊的表中是否存在與它們匹配的行),以及左邊表中全部匹配的行例如1:
SELECT a.,b. FROM luntan LEFT JOIN usertable as b ON a.username=b.username
例如2:
SELECT a.,b. FROM city as a FULL OUTER JOIN user as b ON a.username=b.username
全外連接: 包含左、右兩個表的全部行,不管另外一邊的表中是否存在與它們匹配的行。交叉連接: 生成笛卡爾積-它不使用任何匹配或者選取條件,而是直接將一個數據源中的每個行與另一個數據源的每個行都一一匹配例如:
SELECT type,pub_name FROM titles CROSS JOIN publishers ORDER BY type
14.varchar和char的使用場景?
1.char的長度是不可變的,而varchar的長度是可變的。定義一個char[10]和varchar[10]。如果存進去的是‘csdn’,那么char所占的長度依然為10,除了字符‘csdn’外,后面跟六個空格,varchar就立馬把長度變?yōu)?了,取數據的時候,char類型的要用trim()去掉多余的空格,而varchar是不需要的。2.char的存取速度還是要比varchar要快得多,因為其長度固定,方便程序的存儲與查找。char也為此付出的是空間的代價,因為其長度固定,所以難免會有多余的空格占位符占據空間,可謂是以空間換取時間效率。varchar是以空間效率為首位。3.char的存儲方式是:對英文字符(ASCII)占用1個字節(jié),對一個漢字占用兩個字節(jié)。varchar的存儲方式是:對每個英文字符占用2個字節(jié),漢字也占用2個字節(jié)。4.兩者的存儲數據都非unicode的字符數據。
15.SQL語言分類
SQL語言共分為四大類:一、數據查詢語言DQL二、數據操縱語言DML三、數據定義語言DDL四、數據控制語言DCL。
數據查詢語言DQL數據查詢語言DQL基本結構是由SELECT子句,F(xiàn)ROM子句,WHERE子句組成的查詢塊:SELECTFROMWHERE
數據操縱語言DML數據操縱語言DML主要有三種形式:1) 插入:INSERT2) 更新:UPDATE3) 刪除:DELETE
數據定義語言DDL數據定義語言DDL用來創(chuàng)建數據庫中的各種對象-----表、視圖、索引、同義詞、聚簇等如:CREATE TABLE/VIEW/INDEX/SYN/CLUSTER表 視圖 索引 同義詞 簇DDL操作是隱性提交的!不能rollback
數據控制語言DCL數據控制語言DCL用來授予或回收訪問數據庫的某種特權,并控制數據庫操縱事務發(fā)生的時間及效果,對數據庫實行監(jiān)視等。如:1) GRANT:授權。2) ROLLBACK [WORK] TO [SAVEPOINT]:回退到某一點。回滾---ROLLBACK;回滾命令使數據庫狀態(tài)回到上次最后提交的狀態(tài)。其格式為:SQL>ROLLBACK;3) COMMIT [WORK]:提交。在數據庫的插入、刪除和修改操作時,只有當事務在提交到數據庫時才算完成。在事務提交前,只有操作數據庫的這個人才能有權看到所做的事情,別人只有在最后提交完成后才可以看到。提交數據有三種類型:顯式提交、隱式提交及自動提交。下面分別說明這三種類型。(1) 顯式提交用COMMIT命令直接完成的提交為顯式提交。其格式為:SQL>COMMIT;(2) 隱式提交用SQL命令間接完成的提交為隱式提交。這些命令是:ALTER,AUDIT,COMMENT,CONNECT,CREATE,DISCONNECT,DROP,EXIT,GRANT,NOAUDIT,QUIT,REVOKE,RENAME。(3) 自動提交若把AUTOCOMMIT設置為ON,則在插入、修改、刪除語句執(zhí)行后,系統(tǒng)將自動進行提交,這就是自動提交。其格式為:SQL>SET AUTOCOMMIT ON;
16.說說like %和-的區(qū)別
通配符的分類%百分號通配符:表示任何字符出現(xiàn)任意次數(可以是0次).下劃線通配符:表示只能匹配單個字符,不能多也不能少,就是一個字符.like操作符: LIKE作用是指示mysql后面的搜索模式是利用通配符而不是直接相等匹配進行比較.注意: 如果在使用like操作符時,后面的沒有使用通用匹配符效果是和=一致的,SELECT * FROM products WHERE products.prod_name like '1000';只能匹配的結果為1000,而不能匹配像JetPack 1000這樣的結果.%通配符使用: 匹配以"yves"開頭的記錄:(包括記錄"yves") SELECT FROM products WHERE products.prod_name like 'yves%';匹配包含"yves"的記錄(包括記錄"yves") SELECT FROM products WHERE products.prod_name like '%yves%';匹配以"yves"結尾的記錄(包括記錄"yves",不包括記錄"yves ",也就是yves后面有空格的記錄,這里需要注意) SELECT * FROM products WHERE products.prod_name like '%yves';通配符使用: SELECT FROM products WHERE products.prod_name like 'yves'; 匹配結果為: 像"yyves"這樣記錄. SELECT FROM products WHERE products.prodname like 'yves'; 匹配結果為: 像"yvesHe"這樣的記錄.(一個下劃線只能匹配一個字符,不能多也不能少)注意事項:注意大小寫,在使用模糊匹配時,也就是匹配文本時,mysql是可能區(qū)分大小的,也可能是不區(qū)分大小寫的,這個結果是取決于用戶對MySQL的配置方式.如果是區(qū)分大小寫,那么像YvesHe這樣記錄是不能被"yves__"這樣的匹配條件匹配的.注意尾部空格,"%yves"是不能匹配"heyves "這樣的記錄的.注意NULL,%通配符可以匹配任意字符,但是不能匹配NULL,也就是說SELECT * FROM products WHERE products.prod_name like '%;是匹配不到products.prod_name為NULL的的記錄.技巧與建議:正如所見, MySQL的通配符很有用。但這種功能是有代價的:通配符搜索的處理一般要比前面討論的其他搜索所花時間更長。這里給出一些使用通配符要記住的技巧。不要過度使用通配符。如果其他操作符能達到相同的目的,應該 使用其他操作符。在確實需要使用通配符時,除非絕對有必要,否則不要把它們用 在搜索模式的開始處。把通配符置于搜索模式的開始處,搜索起 來是最慢的。仔細注意通配符的位置。如果放錯地方,可能不會返回想要的數.
17.說說count(*)、count(1)、count(column)的區(qū)別
count()對行的數目進行計算,包含NULLcount(column)對特定的列的值具有的行數進行計算,不包含NULL值。count()還有一種使用方式,count(1)這個用法和count()的結果是一樣的。性能問題:1.任何情況下SELECT COUNT() FROM tablename是最優(yōu)選擇;2.盡量減少SELECT COUNT() FROM tablename WHERE COL = ‘value’ 這種查詢;3.杜絕SELECT COUNT(COL) FROM tablename WHERE COL2 = ‘value’ 的出現(xiàn)。如果表沒有主鍵,那么count(1)比count()快。如果有主鍵,那么count(主鍵,聯(lián)合主鍵)比count()快。如果表只有一個字段,count()最快。count(1)跟count(主鍵)一樣,只掃描主鍵。count()跟count(非主鍵)一樣,掃描整個表。明顯前者更快一些。
18.什么是最左前綴原則?
多列索引:
ALTER TABLE people ADD INDEX lname_fname_age (lame,fname,age);
為了提高搜索效率,我們需要考慮運用多列索引,由于索引文件以B-Tree格式保存,所以我們不用掃描任何記錄,即可得到最終結果。注:在mysql中執(zhí)行查詢時,只能使用一個索引,如果我們在lname,fname,age上分別建索引,執(zhí)行查詢時,只能使用一個索引,mysql會選擇一個最嚴格(獲得結果集記錄數最少)的索引。最左前綴原則:顧名思義,就是最左優(yōu)先,上例中我們創(chuàng)建了lname_fname_age多列索引,相當于創(chuàng)建了(lname)單列索引,(lname,fname)組合索引以及(lname,fname,age)組合索引。
19.什么是索引?
何為索引:數據庫索引,是數據庫管理系統(tǒng)中一個排序的數據結構,索引的實現(xiàn)通常使用B樹及其變種B+樹。在數據之外,數據庫系統(tǒng)還維護著滿足特定查找算法的數據結構,這些數據結構以某種方式引用(指向)數據,這樣就可以在這些數據結構上實現(xiàn)高級查找算法。這種數據結構,就是索引。
20.索引的作用?它的優(yōu)點缺點是什么?
索引作用:協(xié)助快速查詢、更新數據庫表中數據。為表設置索引要付出代價的:一是增加了數據庫的存儲空間二是在插入和修改數據時要花費較多的時間(因為索引也要隨之變動)。
21.索引的優(yōu)缺點有哪些?
創(chuàng)建索引可以大大提高系統(tǒng)的性能(優(yōu)點):(1)通過創(chuàng)建唯一性索引,可以保證數據庫表中每一行數據的唯一性。(2)可以大大加快數據的檢索速度,這也是創(chuàng)建索引的最主要的原因。(3)可以加速表和表之間的連接,特別是在實現(xiàn)數據的參考完整性方面特別有意義。(4)在使用分組和排序子句進行數據檢索時,同樣可以顯著減少查詢中分組和排序的時間。(5)通過使用索引,可以在查詢的過程中,使用優(yōu)化隱藏器,提高系統(tǒng)的性能。增加索引也有許多不利的方面(缺點):(1).創(chuàng)建索引和維護索引要耗費時間,這種時間隨著數據量的增加而增加。(2).索引需要占物理空間,除了數據表占數據空間之外,每一個索引還要占一定的物理空間,如果要建立聚簇索引,那么需要的空間就會更大。(3).當對表中的數據進行增加、刪除和修改的時候,索引也要動態(tài)的維護,這樣就降低了數據的維護速度。(4).哪些列適合建立索引、哪些不適合建索引?索引是建立在數據庫表中的某些列的上面。在創(chuàng)建索引的時候,應該考慮在哪些列上可以創(chuàng)建索引,在哪些列上不能創(chuàng)建索引。一般來說,應該在這些列上創(chuàng)建索引:(1)在經常需要搜索的列上,可以加快搜索的速度;(2)在作為主鍵的列上,強制該列的唯一性和組織表中數據的排列結構;(3)在經常用在連接的列上,這些列主要是一些外鍵,可以加快連接的速度;(4)在經常需要根據范圍進行搜索的列上創(chuàng)建索引,因為索引已經排序,其指定的范圍是連續(xù)的;(5)在經常需要排序的列上創(chuàng)建索引,因為索引已經排序,這樣查詢可以利用索引的排序,加快排序查詢時間;(6)在經常使用在WHERE子句中的列上面創(chuàng)建索引,加快條件的判斷速度。
對于有些列不應該創(chuàng)建索引:(1)對于那些在查詢中很少使用或者參考的列不應該創(chuàng)建索引。這是因為,既然這些列很少使用到,因此有索引或者無索引,并不能提高查詢速度。相反,由于增加了索引,反而降低了系統(tǒng)的維護速度和增大了空間需求。(2)對于那些只有很少數據值的列也不應該增加索引。這是因為,由于這些列的取值很少,例如人事表的性別列,在查詢的結果中,結果集的數據行占了表中數據行的很大比例,即需要在表中搜索的數據行的比例很大。增加索引,并不能明顯加快檢索速度。(3)對于那些定義為text, image和bit數據類型的列不應該增加索引。這是因為,這些列的數據量要么相當大,要么取值很少。(4)當修改性能遠遠大于檢索性能時,不應該創(chuàng)建索引。這是因為,修改性能和檢索性能是互相矛盾的。當增加索引時,會提高檢索性能,但是會降低修改性能。當減少索引時,會提高修改性能,降低檢索性能。因此,當修改性能遠遠大于檢索性能時,不應該創(chuàng)建索引。索引詳解:帶你從頭到尾捋一遍MySQL索引結構!
22.什么樣的字段適合建索引?
唯一、不為空、經常被查詢的字段
23.說說MySQL B+Tree索引和Hash索引的區(qū)別?
Hash索引和B+樹索引的特點:Hash索引結構的特殊性,其檢索效率非常高,索引的檢索可以一次定位;B+樹索引需要從根節(jié)點到枝節(jié)點,最后才能訪問到頁節(jié)點這樣多次的IO訪問;為什么不都用Hash索引而使用B+樹索引?Hash索引僅僅能滿足"=","IN"和""查詢,不能使用范圍查詢,因為經過相應的Hash算法處理之后的Hash值的大小關系,并不能保證和Hash運算前完全一樣;Hash索引無法被用來避免數據的排序操作,因為Hash值的大小關系并不一定和Hash運算前的鍵值完全一樣;Hash索引不能利用部分索引鍵查詢,對于組合索引,Hash索引在計算Hash值的時候是組合索引鍵合并后再一起計算Hash值,而不是單獨計算Hash值,所以通過組合索引的前面一個或幾個索引鍵進行查詢的時候,Hash索引也無法被利用;Hash索引在任何時候都不能避免表掃描,由于不同索引鍵存在相同Hash值,所以即使取滿足某個Hash鍵值的數據的記錄條數,也無法從Hash索引中直接完成查詢,還是要回表查詢數據;Hash索引遇到大量Hash值相等的情況后性能并不一定就會比B+樹索引高。補充:(1).MySQL中,只有HEAP/MEMORY引擎才顯示支持Hash索引。(2).常用的InnoDB引擎中默認使用的是B+樹索引,它會實時監(jiān)控表上索引的使用情況,如果認為建立哈希索引可以提高查詢效率,則自動在內存中的“自適應哈希索引緩沖區(qū)”建立哈希索引(在InnoDB中默認開啟自適應哈希索引),通過觀察搜索模式,MySQL會利用index key的前綴建立哈希索引,如果一個表幾乎大部分都在緩沖池中,那么建立一個哈希索引能夠加快等值查詢。B+樹索引和哈希索引的明顯區(qū)別是:(3).如果是等值查詢,那么哈希索引明顯有絕對優(yōu)勢,因為只需要經過一次算法即可找到相應的鍵值;當然了,這個前提是,鍵值都是唯一的。如果鍵值不是唯一的,就需要先找到該鍵所在位置,然后再根據鏈表往后掃描,直到找到相應的數據;(4).如果是范圍查詢檢索,這時候哈希索引就毫無用武之地了,因為原先是有序的鍵值,經過哈希算法后,有可能變成不連續(xù)的了,就沒辦法再利用索引完成范圍查詢檢索;同理,哈希索引沒辦法利用索引完成排序,以及l(fā)ike ‘xxx%’ 這樣的部分模糊查詢(這種部分模糊查詢,其實本質上也是范圍查詢);(5).哈希索引也不支持多列聯(lián)合索引的最左匹配規(guī)則;(6).B+樹索引的關鍵字檢索效率比較平均,不像B樹那樣波動幅度大,在有大量重復鍵值情況下,哈希索引的效率也是極低的,因為存在所謂的哈希碰撞問題。(7)在大多數場景下,都會有范圍查詢、排序、分組等查詢特征,用B+樹索引就可以了。
24.說說B樹和B+樹的區(qū)別
B樹,每個節(jié)點都存儲key和data,所有節(jié)點組成這棵樹,并且葉子節(jié)點指針為nul,葉子結點不包含任何關鍵字信息。B+樹,所有的葉子結點中包含了全部關鍵字的信息,及指向含有這些關鍵字記錄的指針,且葉子結點本身依關鍵字的大小自小而大的順序鏈接,所有的非終端結點可以看成是索引部分,結點中僅含有其子樹根結點中最大(或最小)關鍵字。(而B 樹的非終節(jié)點也包含需要查找的有效信息)
25.為什么說B+比B樹更適合實際應用中操作系統(tǒng)的文件索引和數據庫索引?
1.B+的磁盤讀寫代價更低B+的內部結點并沒有指向關鍵字具體信息的指針。因此其內部結點相對B樹更小。如果把所有同一內部結點的關鍵字存放在同一盤塊中,那么盤塊所能容納的關鍵字數量也越多。一次性讀入內存中的需要查找的關鍵字也就越多。相對來說IO讀寫次數也就降低了。2.B+tree的查詢效率更加穩(wěn)定由于非終結點并不是最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。所以任何關鍵字的查找必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每一個數據的查詢效率相當。
26.說說聚集索引和非聚集索引區(qū)別?
聚合索引(clustered index):聚集索引表記錄的排列順序和索引的排列順序一致,所以查詢效率快,只要找到第一個索引值記錄,其余就連續(xù)性的記錄在物理也一樣連續(xù)存放。聚集索引對應的缺點就是修改慢,因為為了保證表中記錄的物理和索引順序一致,在記錄插入的時候,會對數據頁重新排序。聚集索引類似于新華字典中用拼音去查找漢字,拼音檢索表于書記順序都是按照a~z排列的,就像相同的邏輯順序于物理順序一樣,當你需要查找a,ai兩個讀音的字,或是想一次尋找多個傻(sha)的同音字時,也許向后翻幾頁,或緊接著下一行就得到結果了。非聚合索引(nonclustered index):非聚集索引指定了表中記錄的邏輯順序,但是記錄的物理和索引不一定一致,兩種索引都采用B+樹結構,非聚集索引的葉子層并不和實際數據頁相重疊,而采用葉子層包含一個指向表中的記錄在數據頁中的指針方式。非聚集索引層次多,不會造成數據重排。非聚集索引類似在新華字典上通過偏旁部首來查詢漢字,檢索表也許是按照橫、豎、撇來排列的,但是由于正文中是a~z的拼音順序,所以就類似于邏輯地址于物理地址的不對應。同時適用的情況就在于分組,大數目的不同值,頻繁更新的列中,這些情況即不適合聚集索引。根本區(qū)別:聚集索引和非聚集索引的根本區(qū)別是表記錄的排列順序和與索引的排列順序是否一致。
二、數據庫MySql基礎篇
1.函數的分類?經常使用的函數有哪些?
loweruppersubstrlengthtrim(去首尾空格,不會去除中間的空格)str_to_date(%Y-%m-%d)date_formatformat(保留小數)roundrand()隨機數ifnull(如果為空,則替換為0)聚合函數/分組函數分組函數自動忽略空值countsumavgminmax
2.分組查詢需要注意條件?
如果使用了order by,order by 必須放到group by后面。在sql語句中,select語句后面只能跟分組函數+參與分組的字段。如果想要對分組數據再進行過濾需要使用having子句。
3.limit使用方法?
select * from emp limit m,n;
4.mysql常見數據類型?
char:定長字符串,適合做主鍵或者外鍵varchar:可變長字符串double/floatint/bigintdate
5.如何增加刪除修改表結構
alter table 表名 add 字段名 數據類型(長度) --添加字段
alter table 表名 modify 字段名 數據類型(長度) --修改字段長度
alter table 表名 change 原字段名 現(xiàn)在字段名 數據類型(長度) --修改字段名稱
alter table 表名 drop 字段名 --刪除字段
6.如何開啟MySQL服務,關閉My服務
開啟服務:
service mysqld start
/init.d/mysqld start
safe_mysql &
關閉服務:
service mysqld stop
/etc/init.d/mysqld stop
mysqladmin -uroot -p123456 shutdown
7.檢測端口是否運行
lsof -i:3306
netstat -tunlp|grep 3306
ss -tulnp|grep 3306
8.如何為MySQL設置密碼或者修改密碼。
方法一
mysqladmin -u root -p123456 password 'abc123' ?? #比較常用
方法二(sql語句修改)
update mysql.user set password=password(123456) where user='root' and host='localhost';
flush privileges;
方法三(sql語句修改)
set password=password('abc123');
9.如何登陸MySQL數據庫。
單實例登陸
mysql -uroot -p123456
多實例登陸
mysql -uroot -p123456 -S /data/3306/mysql.sock
10.查看當前數據庫的字符集
mysql> show variables like "%charac%";
11.如何查看當前數據庫版本
# mysql -V
mysql> select version();
12.如何 查看當前登錄的用戶。
mysql> select user();
13.查看T1數據庫中有哪兒些表
mysql> use T1;
mysql> show tables;
14.創(chuàng)建GBK字符集的數據庫oldboy,并查看已建庫完整語句
mysql> create database oldboy default character set gbk;
mysql> show create database oldboy;
15.創(chuàng)建用戶oldboy,使之可以管理數據庫oldboy
mysql> grant select,update,insert,delete,alter on oldboy.* to oldboy@'localhost' identified by '123456';
16.查看創(chuàng)建的用戶oldboy擁有哪些權限
mysql> show grants for oldboy@'localhost';
17.查看當前數據庫里有哪些用戶
mysql> select user,host from mysql.user;
18.如何進入oldboy數據庫
mysql> use oldboy();
19.請寫一個腳本:? 創(chuàng)建一個innodb GBK表test,字段id int(4)和name varchar(16)
mysql> create table test (id int(4),name varchar(16)) engine=InnoDB default charset=gbk;
20.查看建表結構及表結構的SQL語句
mysql> desc test;
mysql> show create table test\G
21.請使用腳本查詢一條數據:插入一條數據“1,oldboy”
mysql> insert into test (id,name) values (1,'oldboy');
22.再批量插入2行數據 “2,老男孩”,“3,oldboyedu”
mysql> insert into test (id,name) values (2,'老男孩'),(3,'oldboyedu');
23.查詢名字為oldboy的記錄
mysql> select * from test where name='oldboy';
24.把數據id等于1的名字oldboy更改為oldgirl
mysql> update test set name='oldgirl' where id=1;
25.在字段name前插入age字段,類型tinyint(2)
mysql> alter table test add age tinyint(2) after id;
26.不退出數據庫,完成備份oldboy數據庫
mysql> system mysqldump -uroot -p123456 -B -x -F --events oldboy >/opt/bak.sql
27.刪除test表中的所有數據,并查看
mysql> delete from test;
三、數據庫MySql篇
1.說一下 MySQL 的行鎖和表鎖?
MyISAM 只支持表鎖,InnoDB 支持表鎖和行鎖,默認為行鎖。 表級鎖:開銷小,加鎖快,不會出現(xiàn)死鎖。鎖定粒度大,發(fā)生鎖沖突的概率最高,并發(fā)量最低。 行級鎖:開銷大,加鎖慢,會出現(xiàn)死鎖。鎖力度小,發(fā)生鎖沖突的概率小,并發(fā)度最高。
2.MySQL的默認事務隔離級別是?
讀未提交(RU): 一個事務還沒提交時, 它做的變更就能被別的事務看到.讀提交(RC): 一個事務提交之后, 它做的變更才會被其他事務看到.可重復讀(RR): 一個事務執(zhí)行過程中看到的數據, 總是跟這個事務在啟動時看到的數據是一致的. 當然在可重復讀隔離級別下, 未提交變更對其他事務也是不可見的.串行化(S): 對于同一行記錄, 讀寫都會加鎖. 當出現(xiàn)讀寫鎖沖突的時候, 后訪問的事務必須等前一個事務執(zhí)行完成才能繼續(xù)執(zhí)行.
3.Mysql數據庫表類型有哪些?
MyISAM、InnoDB、HEAP、BOB,ARCHIVE,CSV等。MyISAM:成熟、穩(wěn)定、易于管理,快速讀取。一些功能不支持(事務等),表級鎖。InnoDB:支持事務、外鍵等特性、數據行鎖定??臻g占用大,不支持全文索引等。
4.MySQL怎么恢復半個月前的數據?
通過整庫備份+binlog進行恢復. 前提是要有定期整庫備份且保存了binlog日志.
5.一張自增表里面總共有 7 條數據,刪除了最后 2 條數據,重啟 MySQL 數據庫,又插入了一條數據,此時 id 是幾?
表類型如果是 MyISAM ,那 id 就是 8。表類型如果是 InnoDB,那 id 就是 6。InnoDB 表只會把自增主鍵的最大 id 記錄在內存中,所以重啟之后會導致最大 id 丟失。
6.MySQL 的內連接、左連接、右連接有什么區(qū)別?
內連接關鍵字:inner join;左連接:left join;右連接:right join。 內連接是把匹配的關聯(lián)數據顯示出來;左連接是左邊的表全部顯示出來,右邊的表顯示出符合條件的數據;右連接正好相反。
7.MySQL 問題排查都有哪些手段?
使用 show processlist 命令查看當前所有連接信息。 使用 explain 命令查詢 SQL 語句執(zhí)行計劃。 開啟慢查詢日志,查看慢查詢的 SQL。
8.如何做 MySQL 的性能優(yōu)化?
為搜索字段創(chuàng)建索引。避免使用 select *,列出需要查詢的字段。垂直分割分表。選擇正確的存儲引擎。
讀寫分離
9.MySQL數據庫作發(fā)布系統(tǒng)的存儲,一天五萬條以上的增量,預計運維三年,怎么優(yōu)化?
(1)設計良好的數據庫結構,允許部分數據冗余,盡量避免join查詢,提高效率。(2) 選擇合適的表字段數據類型和存儲引擎,適當的添加索引。(3) 做mysql主從復制讀寫分離。(4)對數據表進行分表,減少單表中的數據量提高查詢速度。(5)添加緩存機制,比如redis,memcached等。(6)對不經常改動的頁面,生成靜態(tài)頁面(比如做ob緩存)。(7)書寫高效率的SQL。比如 SELECT * FROM TABEL 改為 SELECT field_1, field_2, field_3 FROM TABLE.
10.MySQL由哪些部分組成, 分別用來做什么?
(1)Server(2)連接器: 管理連接, 權限驗證.(3)分析器: 詞法分析, 語法分析.(4)優(yōu)化器: 執(zhí)行計劃生成, 索引的選擇.(5)執(zhí)行器: 操作存儲引擎, 返回執(zhí)行結果.(6)存儲引擎: 存儲數據, 提供讀寫接口.
11.怎么驗證 MySQL 的索引是否滿足需求?
使用 explain 查看 SQL 是如何執(zhí)行查詢語句的,從而分析你的索引是否滿足需求。 explain 語法:explain select * from table where type=1。
12.請你介紹一下 mysql的主從復制?
考察點:數據庫
MySQL主從復制是其最重要的功能之一。主從復制是指一臺服務器充當主數據庫服務器,另一臺或多臺服務器充當從數據庫服務器,主服務器中的數據自動復制到從服務器之中。對于多級復制,數據庫服務器即可充當主機,也可充當從機。MySQL主從復制的基礎是主服務器對數據庫修改記錄二進制日志,從服務器通過主服務器的二進制日志自動執(zhí)行更新。
MySQL主從復制的兩種情況:同步復制和異步復制,實際復制架構中大部分為異步復制。
復制的基本過程如下:
Slave上面的IO進程連接上Master,并請求從指定日志文件的指定位置(或者從最開始的日志)之后的日志內容。
Master接收到來自Slave的IO進程的請求后,負責復制的IO進程會根據請求信息讀取日志指定位置之后的日志信息,返回給Slave的IO進程。返回信息中除了日志所包含的信息之外,還包括本次返回的信息已經到Master端的bin-log文件的名稱以及bin-log的位置。
Slave的IO進程接收到信息后,將接收到的日志內容依次添加到Slave端的relay-log文件的最末端,并將讀取到的Master端的bin-log的文件名和位置記錄到master-info文件中,以便在下一次讀取的時候能夠清楚的告訴Master“我需要從某個bin-log的哪個位置開始往后的日志內容,請發(fā)給我”。
Slave的Sql進程檢測到relay-log中新增加了內容后,會馬上解析relay-log的內容成為在Master端真實執(zhí)行時候的那些可執(zhí)行的內容,并在自身執(zhí)行。
13.請你介紹一下mysql的MVCC機制
MVCC是一種多版本并發(fā)控制機制,是MySQL的InnoDB存儲引擎實現(xiàn)隔離級別的一種具體方式,用于實現(xiàn)提交讀和可重復讀這兩種隔離級別。MVCC是通過保存數據在某個時間點的快照來實現(xiàn)該機制,其在每行記錄后面保存兩個隱藏的列,分別保存這個行的創(chuàng)建版本號和刪除版本號,然后Innodb的MVCC使用到的快照存儲在Undo日志中,該日志通過回滾指針把一個數據行所有快照連接起來。
14.常用的Mysql復制架構有哪些?
(1)一主多從 在主庫讀取請求壓力非常大的場景下, 可以通過配置一主多從復制架構實現(xiàn)讀寫分離, 把大量對實時性要求不是特別高的讀請求通過負載均衡分布到多個從庫上, 降低主庫的讀取壓力,在主庫出現(xiàn)異常宕機的情況下, 可以把一個從庫切換為主庫繼續(xù)提供服務 。
(2)多級復制 一主多從的架構能夠解決大部分讀請求壓力特別大的場景的需求, 考慮到 MysQL的復制是主庫“推送” Binlog日志到從庫,主庫的 I/0壓力和網絡壓力會隨著從庫的增加而增長(每個從庫都會在主庫上有一個獨立的 Binlog Dump線程來發(fā)送事件), 而多級復制架構解決了一主多從場景下,主庫額外的 I/0和網絡壓力。
(3)雙主復制/Dual Master 其實就是主庫 Master和 Master2互為主從, client客戶端的寫請求都訪問主庫 Master,而讀請求可以選擇訪問主庫 Master或 Master2。
15.Mysql 的存儲引擎,myisam和innodb的區(qū)別?
(1)InnoDB支持事務, MyISAM不支持.
(2)InnoDB支持行級鎖, MyISAM支持表級鎖.
(3)InnoDB支持多版本并發(fā)控制(MVVC), MyISAM不支持.
(4)InnoDB支持外鍵, MyISAM不支持.
(5)MyISAM支持全文索引, InnoDB不支持(但可以使用Sphinx插件)
16.請問MySQL的端口號是多少,如何修改這個端口號
查看端口號:
使用命令show global variables like 'port';查看端口號 ,mysql的默認端口是3306。(補充:sqlserver默認端口號為:1433;oracle默認端口號為:1521;DB2默認端口號為:5000;PostgreSQL默認端口號為:5432)
修改端口號:
修改端口號:編輯/etc/my.cnf文件,早期版本有可能是my.conf文件名,增加端口參數,并且設定端口,注意該端口未被使用,保存退出。
17.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` )
18.說說自己對于 MySQL 常見的兩種存儲引擎:MyISAM與InnoDB的理解?
InnoDB 引擎:InnoDB 引擎提供了對數據庫 acid 事務的支持,并且還提供了行級鎖和外鍵的約束,它的設計的目標就是處理大數據容量的數據庫系統(tǒng)。MySQL 運行的時候,InnoDB 會在內存中建立緩沖池,用于緩沖數據和索引。但是該引擎是不支持全文搜索,同時啟動也比較的慢,它是不會保存表的行數的,所以當進行 select count() from table 指令的時候,需要進行掃描全表。由于鎖的粒度小,寫操作是不會鎖定全表的,所以在并發(fā)度較高的場景下使用會提升效率的。
MyIASM 引擎:MySQL 的默認引擎,但不提供事務的支持,也不支持行級鎖和外鍵。因此當執(zhí)行插入和更新語句時,即執(zhí)行寫操作的時候需要鎖定這個表,所以會導致效率會降低。不過和 InnoDB 不同的是,MyIASM 引擎是保存了表的行數,于是當進行 select count() from table 語句時,可以直接的讀取已經保存的值而不需要進行掃描全表。所以,如果表的讀操作遠遠多于寫操作時,并且不需要事務的支持的,可以將 MyIASM 作為數據庫引擎的首選。