首先,感謝大家的瀏覽,還有朋友給推薦工作,由於本人目前在北京,且年后本人在北京還有部分課程需要上,因此現在不便於遠行前往深圳,廣州等地。還是非常感謝大家!
今天主要是把之前的工具,做了一些設置與調整,工欲善其事,必先利其器嘛。主要涉及到Eclipse設置,maven使用(之前工作都是使用自有構建工具,現在用開源,開源工具功能大而全,但是,往往也坑比較多),git工具的使用(以前工作一直使用SVN,版本管理以后稍作介紹),Mysql安裝使用(之前工作一直使用oracle,關於這一部分以后做詳加使用說明)。下面還是接昨天的,把面試涉及到的東西寫完整。
====================================華麗分割線===========================================
1.索引的使用,聯合索引的使用,是否索引越多越好?
答:[以oracle為例]索引好比是一本書前面的目錄,能加快數據庫表的查詢速度。索引分為聚簇索引和非聚簇索引兩種,聚簇索引 是按照數據存放的物理位置為順序的,而非聚簇索引就不一樣了;聚簇索引能提高多行檢索的速度,而非聚簇索引對於單行的檢索很快。
用的最多也最好的是B-tree索引,它主要是避免了大量數據的排序操作。
數據庫中存儲數據的基礎單位就是頁,數據庫的頁大小和操作系統類似,是指存放數據時,每一塊的大小。比如一個1M的數據存放在數據庫中時, 需要大概12塊頁來存放。如果是在操作系統上安裝的數據庫,最好將數據庫頁大小設置為操作系統頁大小的倍數,才是最佳設置。數據庫可以將數據從邏輯上分成頁,磁盤的I/O操作就是在頁級執行。
- 96字節大小的標頭,存儲統計信息,包括頁碼、頁類型、頁的可用空間以及擁有該頁的對象的分配單元 ID。數據庫頁類型主要分如下三類:
- 數據頁,除了大型對象的數據列之外的數據存儲頁,比如int,float,varchar等。
- 索引頁,存放索引的條目。
- 大型對象數據類型,比如text,image,nvarchar(max)等。
- 一個區包含8個頁,它是管理空間的單位,分為如下兩類
- 統一區,由單個對象所有。
- 混合區,最多可由八個對象共享
知道了區以及頁的概念,再看下數據表和這兩者之間的聯系, 表包含一個或多個分區,每個分區在一個堆或一個聚集索引結構中包含數據行。
索引中的底層節點稱為葉節點。根節點與葉節點之間的任何索引級別統稱為中間級。在聚集索引中,葉節點包含基礎表的數據頁。根節點和中間級節點包含存有索引行的索引頁。每個索引行包含一個鍵值和一個指針,該指針指向 B -樹上的某一中間級頁或葉級索引中的某個數據行。每級索引中的頁均被鏈接在雙向鏈接列表中。
非聚集索引與聚集索引之間的顯著差別在於以下兩點:
- 基礎表的數據行不按非聚集鍵的順序排序和存儲。
- 非聚集索引的葉層是由索引頁而不是由數據頁組成。
索引的優點:正確的索引會大大提高數據查詢,對結果進行排序、分組的操作效率。
索引的缺點:
1.創建索引需要額外的磁盤空間,索引最大一般為表大小的1.2倍左右。
2.在表數據修改時,例如增加,刪除,更新,都需要維護索引表,這是需要系統開銷的。
3.不合理的索引設計非但不能利於系統,反而會使系統性能下降。例如我們在一個創建有非聚集索引的列上做范圍查詢,此列的索引不會起到任何的優化效果,反而由於數據的修改而需要維護索引表,從而影響了對數據修改的性能。
什么字段不適合創建索引?
1.不經常使用的列,這種索引帶來缺點遠大於帶來的優點。
2.邏輯性的字段,例如性別字段等等,匹配的記錄太多,和全表掃描比起來差不多。
3.字段內容特別大的字段,例如大字段等,這會大大增大索引所占用的空間以及索引維護時的速度。
4.涉及到計算的列,或者是需要利用數據庫函數進行加工處理的列不應當創建索引。
聯合索引:
1.查詢條件中出現聯合索引第一列,或者全部,則能利用聯合索引.
2.條件列中只要條件相連在一起,無論前后,都會利用上聯合索引.
3.查詢條件中沒有出現聯合索引的第一列,而出現聯合索引的第二列,或者第三列,都不會利用聯合索引查詢.
單一列索引:
1.只要條件列中出現索引列,無論在什么位置,都能利用索引查詢.
另外,實際使用過程中,經常遇到索引丟失的情況,這種情況一般需要重建索引,有的涉及到復雜業務查詢的語句,需要優化查詢,對於具體的SQL,可能由於優化的原因,有不是理想的執行計划。
======================================華麗分割線==========================================
2.實現二路歸並排序(面試是要求畫出圖)
答:二路歸並理解起來比較容易,主要是利用分治法。但是,具體代碼還是要下一些功夫。
歸並排序其實要做兩件事:
1.分解——將序列每次折半划分。
2.合並——將划分后的序列段兩兩合並后排序。
合並的規則:
在每次合並過程中,都是對兩個有序的序列段進行合並,然后排序。這兩個有序序列段分別為 arr[low, mid] 和 arr[mid+1, high]。先將他們合並到一個局部的暫存數組tmparr中,待合並完成后再將tmparr復制回R中。這里稱 arr[low, mid] 第一段,arr[mid+1, high] 為第二段。每次從兩個段中取出一個記錄進行關鍵字的比較,將較小者放入tmparr中。最后將各段中余下的部分直接復制到tmparr中。經過這樣的過程,tmparr已經是一個有序的序列,再將其復制回arr中,一次合並排序就完成了。
注意,若子表個數為奇數,則最后一個子表無須和其他子表歸並(即本趟處理輪空):若子表個數為偶數,則要注意到最后一對子表中后一個子表區間的上限為n-1。
/** * @FileName MergeSort.java * @Package com.algorithm.sort * @Description * <li>二路歸並排序,它相對與快排序和堆排序來說,是穩定的排序方法,時間復雜度o(nlnn),空間復雜度為o(n)</li> * @Author ali blog:http://www.cnblogs.com/accipiter * @Date 上午1:06:31 * @Version V1.0.1 */ package com.algorithm.sort; /** * @ClassName MergeSort * @Description TODO * @Date 下午11:14:51 */ public class MergeSort { /** * @Title Merge * @Description TODO * @param arr * @param low * @param mid * @param high * @Return void * @Throws * @user Administrator */ public void merge(int[] arr, int low, int mid, int high) { int i = low; // i是第一段序列的起始 int j = mid + 1; // j是第二段序列的起始 int k = 0; // k是臨時存放合並序列的起始 int[] tmparr = new int[high - low + 1]; // tmparr是臨時合並序列 while (i <= mid && j <= high) { if (arr[i] <= arr[j]) { tmparr[k++] = arr[i++]; } else { tmparr[k++] = arr[j++]; } } while (i <= mid) { tmparr[k++] = arr[i++]; } while (j <= high) { tmparr[k++] = arr[j++]; } for (k = 0, i = low; i <= high; i++, k++) { arr[i] = tmparr[k]; } } /** * @Title MergeStep * @Description TODO * @param arr * @param len * @param length * @Return void * @Throws * @user Administrator */ public void mergeStep(int[] arr, int len, int length) { int i = 0; for (i=0;i+ 2*len-1<length;i+=2*len){ merge(arr,i, i+len-1, i+ 2*len-1); } if (i+len-1<length){ merge(arr,i, i+len-1,length-1); } } /** * @Title sort * @Description TODO * @param list * @return * @Return int[] * @Throws * @user Administrator */ public int[] sort(int[] list) { for (int len = 1; len < list.length; len = 2 * len) { mergeStep(list, len, list.length); System.out.print("len = " + len + ":\t"); this.printAll(list); } return list; } /** * @Title printAll * @Description TODO * @param list * @Return void * @Throws * @user Administrator */ public void printAll(int[] list) { for(int value : list){ System.out.print(value + "\t"); } System.out.println(); } /** * @Title MSort * @Description * <li>純遞歸實現二路歸並排序</li> * @param arr * @param low * @param high * @Return void * @Throws * @user Administrator */ public void mSort(int []arr,int low,int high){ if(low<high){ int mid=(low+high)/2; mSort(arr,low,mid); mSort(arr,mid+1,high); merge(arr,low,mid,high); this.printAll(arr); } } public static void main(String[] args) { int[] array = { 8, 1, 7, 3, 1, 2, 6, 9, 5}; MergeSort merge = new MergeSort(); System.out.print("排序前:\t\t"); merge.printAll(array); // merge.sort(array); merge.mSort(array,0,array.length-1); System.out.print("排序后:\t\t"); merge.printAll(array); } }
==================================華麗分割線=============================================
此次面試主要內容就以上,不再深究了。接下來一段時間,我會利用好,出一些系列的東西,也想自己實現點東西。感謝支持!