背景:
這是最近一直想的一個問題,按之前的經驗來判斷應該是連表要快一些,那么接下來來個Demo測試一下。本次測試采取兩張表(Order表-20w左右數據量,OrderLog-105w左右數據量),實驗代碼見附錄
實驗:
1. 先來測試左連操作的情況


2. 接下來看下兩次連庫的情況


3. 注意:兩次查詢注意清除數據庫緩存,以免影響查詢結果
DBCC
DROPCLEANBUFFERS
從緩沖池中刪除所有清除緩沖區。
DBCC FREEPROCCACHE
從過程緩存中刪除所有元素。
DBCC FREESYSTEMCACHE
從所有緩存中釋放所有未使用的緩存條目。
從緩沖池中刪除所有清除緩沖區。
DBCC FREEPROCCACHE
從過程緩存中刪除所有元素。
DBCC FREESYSTEMCACHE
從所有緩存中釋放所有未使用的緩存條目。
4. 試着 在OrderLog表中添加非聚集索引(Index_OrderLog_OrderID)后再來看查詢結果


沒錯,不到1秒就出結果了,強大的索引呀
分析:
兩個表都有索引,都是以ID為聚集索引,看上面的結果,貌似差不多的樣子,的確也差不多,不過根據現實中的經驗一般都會
用連表,而不是去多次去連庫查詢,我覺得原因有以下幾個吧
1. 每次連庫都會產生較大的性能消耗(相比較於查詢數據而言)
2. 多次連庫也會存在不穩定性,如果其中的一次連庫失敗,那么最終的結果就不會出來
3. 連表查詢如果遇到性能問題可以建索引來解決,而連庫的性能消耗大了很難去解決(受外部網絡影響)
附錄:
private static string connectionStr = "data source=192.168.6.37;database=Tidebuy;uid=sa;pwd=123456;"; private static string idStr = @"73498,73514,73546,73716,73798,74029,74042"; static void Main(string[] args) { #region 生成數據 //for (int index = 100001; index <=200000; index++) //{ // Test1 entity = new Test1() // { // Name = "Test" + index.ToString(), // Description = "" // }; // Encoding gb = System.Text.Encoding.GetEncoding("GB2312"); // //調用函數產生4個隨機中文漢字編碼 // object[] bytes = CreateRegionCode(150); // string number = index % 3 == 0 ? index.ToString() : ""; // //根據漢字編碼的字節數組解碼出中文漢字 // for (int i = 0; i < 10; i++) // { // entity.Description += gb.GetString((byte[])Convert.ChangeType(bytes[i], typeof(byte[]))) + number; // } // if (InsertData(entity, connectionStr)) // { // //輸出的控制台 // Console.WriteLine(entity.Name); // } //} #endregion DateTime start = DateTime.Now; Console.WriteLine("左連操作執行開始:" + start.ToString("yyyy-MM-dd HH:mm:ss fff")); int count = SelectFromTB_OrderLeftJoinTB_OrderLog(); Console.WriteLine("左連操作結果:" + count); DateTime end = DateTime.Now; Console.WriteLine("左連操作執行結束:" + end.ToString("yyyy-MM-dd HH:mm:ss fff")); Console.WriteLine("耗時:" + (end - start).ToString()); //DateTime start = DateTime.Now; //Console.WriteLine("連庫操作執行開始:" + start.ToString("yyyy-MM-dd HH:mm:ss fff")); //string orderIdStr = SelectFromTB_Order(); //int count = SelectFromTB_OrderLog(orderIdStr); //Console.WriteLine("連庫操作結果:" + count); //DateTime end = DateTime.Now; //Console.WriteLine("連庫操作執行結束:" + end.ToString("yyyy-MM-dd HH:mm:ss fff")); //Console.WriteLine("耗時:" + (end - start).ToString() + "\r\n\r\n"); } /// <summary> /// 20w數據的表 /// </summary> /// <returns></returns> public static string SelectFromTB_Order() { string sql = string.Format(@"SELECT * FROM TB_Order WHERE ID IN({0})", idStr); DataTable table = new DataTable(); TbDatabase.Fill(connectionStr, sql,table); StringBuilder orderIdStr = new StringBuilder(); if (table!=null&&table.Rows.Count>0) { foreach (DataRow row in table.Rows) { orderIdStr.Append(row["ID"].ToString() + ","); } } if (orderIdStr.Length>0) { return orderIdStr.ToString().Substring(0, orderIdStr.Length - 1); } else { return ""; } } /// <summary> /// 105w的數據量 /// </summary> /// <param name="orderIdStr"></param> /// <returns></returns> public static int SelectFromTB_OrderLog(string orderIdStr) { string sql = string.Format(@"SELECT * FROM TB_OrderLog WHERE OrderID IN({0})", orderIdStr); DataTable table = new DataTable(); TbDatabase.Fill(connectionStr, sql, table); if (table != null && table.Rows.Count > 0) { return table.Rows.Count; } else { return 0; } } /// <summary> /// 20w*105w左連 /// </summary> /// <returns></returns> public static int SelectFromTB_OrderLeftJoinTB_OrderLog() { string sql = string.Format(@"SELECT * FROM TB_OrderLog ol WITH(NOLOCK) LEFT JOIN TB_Order o ON ol.[OrderID]=o.[ID] WHERE o.ID IN({0})",idStr); DataTable table = new DataTable(); TbDatabase.Fill(connectionStr, sql, table); if (table != null && table.Rows.Count > 0) { return table.Rows.Count; } else { return 0; } }