背景:
这是最近一直想的一个问题,按之前的经验来判断应该是连表要快一些,那么接下来来个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; } }