如下是對面試常見面試題整理,來自知乎大神分享的pdf,引用部分連接已給出,若是有沒有標註的,純屬意外,但願提醒。這篇主要整理出來給本身看的
B/B+樹html
B/B+java
B樹中的每一個結點根據實際狀況能夠包含大量的關鍵字信息和分支(固然是不能超過磁盤塊的大小,根據磁盤驅動(disk drives)的不一樣,通常塊的大小在1k~4k左右);這樣樹的深度下降了,這就意味着查找一個元素只要不多結點從外存磁盤中讀入內存,很快訪問到要查找的數據mysql
代碼定義:
web
B樹優點
高度比平衡樹低,因此IO磁盤操做次數少,查找更快面試
當B樹包含N個關鍵字時,B樹的最大高度爲l-1(由於計算B樹高度時,葉結點所在層不計算在內),即:l - 1 = log┌m/2┐((N+1)/2 )+1。sql
B+-tree的磁盤讀寫代價更低:
B+-tree的內部結點並無指向關鍵字具體信息的指針。所以其內部結點相對B 樹更小。若是把全部同一內部結點的關鍵字存放在同一盤塊中,那麼盤塊所能容納的關鍵字數量也越多。一次性讀入內存中的須要查找的關鍵字也就越多。相對來講IO讀寫次數也就下降了。數據庫
舉個例子,假設磁盤中的一個盤塊容納16bytes,而一個關鍵字2bytes,一個關鍵字具體信息指針2bytes。一棵9階B-tree(一個結點最多8個關鍵字)的內部結點須要2個盤快。而B+ 樹內部結點只須要1個盤快。當須要把內部結點讀入內存中的時候,B 樹就比B+ 樹多一次盤塊查找時間(在磁盤中就是盤片旋轉的時間)。設計模式
B+-tree的查詢效率更加穩定:
因爲非終結點並非最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。因此任何關鍵字的查找必須走一條從根結點到葉子結點的路。全部關鍵字查詢的路徑長度相同,致使每個數據的查詢效率至關。數組
在MySQL中,索引屬於存儲引擎級別的概念,不一樣存儲引擎對索引的實現方式是不一樣的,這裏主要討論MyISAM和InnoDB兩個存儲引擎的索引實現方式
索引服務器
MyISAM引擎使用B+Tree做爲索引結構,葉節點的data域存放的是數據記錄的地址。下圖是MyISAM索引的原理圖
假設咱們以Col1爲主鍵,則圖8是一個MyISAM表的主索引(Primary key)示意。能夠看出MyISAM的索引文件僅僅保存數據記錄的地址。在MyISAM中,主索引和輔助索引(Secondary key)在結構上沒有任何區別,只是主索引要求key是惟一的,而輔助索引的key能夠重複
MyISAM的索引方式也叫作「非彙集」的,之因此這麼稱呼是爲了與InnoDB的彙集索引區分。
雖然InnoDB也使用B+Tree做爲索引結構,但具體實現方式卻與MyISAM大相徑庭。
瞭解不一樣存儲引擎的索引實現方式對於正確使用和優化索引都很是有幫助,例如知道了InnoDB的索引實現後,就很容易明白爲何不建議使用過長的字段做爲主鍵,由於全部輔助索引都引用主索引,過長的主索引會令輔助索引變得過大。再例如,用非單調的字段做爲主鍵在InnoDB中不是個好主意,由於InnoDB數據文件自己是一顆B+Tree,非單調的主鍵會形成在插入新記錄時數據文件爲了維持B+Tree的特性而頻繁的分裂調整,十分低效,而使用自增字段做爲主鍵則是一個很好的選擇。
//普通索引 alter table table_name add index index_name (column_list) ; //惟一索引 alter table table_name add unique (column_list) ; //主鍵索引 alter table table_name add primary key (column_list) ;
//CREATE INDEX可用於對錶增長普通索引或UNIQUE索引,可用於建表時建立索引。 CREATE INDEX index_name ON table_name(username(length)); //若是是CHAR,VARCHAR類型,length能夠小於字段實際長度;若是是BLOB和TEXT類型,必須指定 length。 //create只能添加這兩種索引; CREATE INDEX index_name ON table_name (column_list) CREATE UNIQUE INDEX index_name ON table_name (column_list)
drop index index_name on table_name ; alter table table_name drop index index_name ; alter table table_name drop primary key ;
一致性(Consistency):從一個一致性狀態到另外一個一致性狀
態。
例如現有完整性約束 a+b=10,若是一個事務改變了a,那麼必須
得改變b,使得事務結束後依然知足 a+b=10,不然事務失敗。
隔離性(Isolation):一個事務所作的修改在最終提交之前,對其它事務不可見。
好比現有有個交易是從A 帳戶轉100 元至 B 帳戶,在這個交易還
未完成的狀況下,若是此時 B 查詢本身的帳戶,是看不到新增長的
100元的。
(Durability) 持久性
持久性是指一旦事務提交後,它所作的修改將會永久的保存在數據庫
上,即便出現宕機也不會丟失。
儘可能使用數字字段而不是字符字段
儘可能使用timestamp而不是datetime
Public void FindAllUsers(){ //一、裝載sqlserver驅動對象 DriverManager.registerDriver(new SQLServerDriver()); //二、經過JDBC創建數據庫鏈接 Connection con =DriverManager.getConnection("jdbc:sqlserver://192.168.2.6:1433;DatabaseName=customer", "sa", "123"); //三、建立狀態 Statement state =con.createStatement(); //四、查詢數據庫並返回結果 ResultSet result =state.executeQuery("select * from users"); //五、輸出查詢結果 while(result.next()){ System.out.println(result.getString("email")); } //六、斷開數據庫鏈接 result.close(); state.close(); con.close(); }
程序開發過程當中,存在不少問題:首先,每一次web請求都要創建一次數據庫鏈接。創建鏈接是一個費時的活動,每次都得花費0.05s~1s的時間,並且系統還要分配內存資源。這個時間對於一次或幾回數據庫操做,或許感受不出系統有多大的開銷。但是對於如今的web應用,尤爲是大型電子商務網站,同時有幾百人甚至幾千人在線是很正常的事。在這種狀況下,頻繁的進行數據庫鏈接操做勢必佔用不少的系統資源,網站的響應速度一定降低,嚴重的甚至會形成服務器的崩潰。不是危言聳聽,這就是制約某些電子商務網站發展的技術瓶頸問題。其次,對於每一次數據庫鏈接,使用完後都得斷開。不然,若是程序出現異常而未能關閉,將會致使數據庫系統中的內存泄漏,最終將不得不重啓數據庫。還有,這種開發不能控制被建立的鏈接對象數,系統資源會被毫無顧及的分配出去,如鏈接過多,也可能致使內存泄漏,服務器崩潰。
public class MyDataSource implements DataSource { //鏈表 --- 實現棧結構 privateLinkedList<Connection> dataSources = new LinkedList<Connection>(); //初始化鏈接數量 publicMyDataSource() { //一次性建立10個鏈接 for(int i = 0; i < 10; i++) { try { //一、裝載sqlserver驅動對象 DriverManager.registerDriver(new SQLServerDriver()); //二、經過JDBC創建數據庫鏈接 Connection con =DriverManager.getConnection( "jdbc:sqlserver://192.168.2.6:1433;DatabaseName=customer", "sa", "123"); //三、將鏈接加入鏈接池中 dataSources.add(con); } catch (Exception e) { e.printStackTrace(); } } } @Override publicConnection getConnection() throws SQLException { //取出鏈接池中一個鏈接 finalConnection conn = dataSources.removeFirst(); // 刪除第一個鏈接返回 returnconn; } //將鏈接放回鏈接池 publicvoid releaseConnection(Connection conn) { dataSources.add(conn); } }
//查詢全部用戶 Public void FindAllUsers(){ //一、使用鏈接池創建數據庫鏈接 MyDataSource dataSource = new MyDataSource(); Connection conn =dataSource.getConnection(); //二、建立狀態 Statement state =con.createStatement(); //三、查詢數據庫並返回結果 ResultSet result =state.executeQuery("select * from users"); //四、輸出查詢結果 while(result.next()){ System.out.println(result.getString("email")); } //五、斷開數據庫鏈接 result.close(); state.close(); //六、歸還數據庫鏈接給鏈接池 dataSource.releaseConnection(conn); }
前綴查詢,例如「abc%」,仍是索
引策略的問題
對於共享資源,有一個很著名的設計模式:資源池(resource pool)。該模式正是爲了解決資源的頻繁分配﹑釋放所形成的問題。爲解決上述問題,能夠採用數據庫鏈接池技術。數據庫鏈接池的基本思想就是爲數據庫鏈接創建一個「緩衝池」。預先在緩衝池中放入必定數量的鏈接,當須要創建數據庫鏈接時,只需從「緩衝池」中取出一個,使用完畢以後再放回去。咱們能夠經過設定鏈接池最大鏈接數來防止系統無盡的與數據庫鏈接。更爲重要的是咱們能夠經過鏈接池的管理機制監視數據庫的鏈接的數量﹑使用狀況,爲系統開發﹑測試及性能調整提供依據。線程池也是如此,由於頻繁開啓關閉線程會下降系統資源,因此能夠用線程池達到資源共享,統一管理線程資源的目的。初始化一個比較大的線程池,每當程序須要開啓新的線程時,會到線程池中申請。一樣的咱們能夠初始化適當的線程數來達到最大的資源利用率
我的認爲是第三範式,此時數據冗餘較小,範式級別太高對查詢效率也不利
序。
select id from table group by id having avg(score) > 80 order by avg(score) desc
/找出第K大的數 int find_k_big(int A[], int low, int high, int k) { if(low < high) { int pivot_pos = partion2(A, low, high); if(pivot_pos + 1 == k) return A[pivot_pos]; else if(pivot_pos + 1 > k) find_k_big(A, low, pivot_pos - 1, k); else find_k_big(A, pivot_pos + 1, high, k); } else return -1;