所周知, 临时表的特性如下,生命周期跟连接有关。
- /*
- 1、局部临时表(#开头)只对当前连接有效,当前连接断开时自动删除。
- 2、全局临时表(##开头)对其它连接也有效,在当前连接和其他访问过它的连接都断开时自动删除。
- 3、不管局部临时表还是全局临时表,只要连接有访问权限,都可以用drop table #Tmp(或者drop table ##Tmp)来显式删除临时表。
- */
那程序中到底是否应该显式地删除临时表呢?
很多人认为, 既然生命周期就是创建到连接关闭, 那我关闭连接就可以了呀, 这不是省了好多事吗?
到底是不是这样, 让我们来做个试验:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Data.SqlClient;
-
- namespace ConsoleApplication10
- {
- class Program
- {
- static void Main(string[] args)
- {
- string[] titleArr = { "带连接池", "默认不写连接池相关内容", "不带连接池" };
- string[] connStringArr ={
- @"data source=(local)\sqlserver2014;initial catalog=tempdb;Integrated Security=True;pooling=true;Min Pool Size=5;Max Pool Size=512;",
- @"data source=(local)\sqlserver2014;initial catalog=tempdb;Integrated Security=True;",
- @"data source=(local)\sqlserver2014;initial catalog=tempdb;Integrated Security=True;pooling=false" };
- string[] sqlArr = {
- @"create table #tmpLocalWithPool(id int);create table ##tmpGolbalWithPool(id int)",
- @"create table #tmpLocal(id int);create table ##tmpGolbal(id int)",
- @"create table #tmpLocalWithoutPool(id int);create table ##tmpGolbalWithoutPool(id int)"
- };
-
- for (int i = 0; i < titleArr.Length; i++)
- {
- try
- {
- using (SqlConnection conn = new SqlConnection(connStringArr[i]))
- {
- conn.Open();
- SqlCommand cmd = new SqlCommand(sqlArr[i], conn);
- cmd.ExecuteNonQuery();
- }
- Console.WriteLine(titleArr[i] + " 执行成功!");
- }
- catch (Exception ex)
- {
- Console.WriteLine(titleArr[i] + "执行失败!原因:" + ex.Message);
- }
- }
-
- Console.Read();
- }
- }
- }
注意:运行完毕先不要关闭控制台, 看一下对应 tempdb 库中的情况:
很明显, 带连接池的和不写连接池的都没有主动清除, 只有不用连接池的才帮我们清除了。
不写连接池,其实也是开启了的(默认开启连接池, 最小0, 最大100)。点击打开链接
其实也相当于是带连接池。
但生产环境的应用,有多少同学敢不用连接池?
用连接池,但又不主动删除, 最终会导致 tempdb 庞大无比, 一堆垃圾占用着宝贵的系统资源……
当然, 不仅是程序, SSMS等客户端开查询窗口也是一样的, 也需要显式删除临时表。
见过有人导报表一直不关闭窗口, 查一个新开一个, 临时表也不显式删除, 最终导致C盘爆满(tempdb放在了C盘)。
勿以善小而不为, 勿以恶小而为之。
不管哪里, 还是养成好习惯——临时表用完就主动 drop 吧。