一、什么是临时表
临时表属于会话级的,会话结束的时候,临时表被释放,其创建、使用、删除都和普通表一样,临时表空间一般利用虚拟内存,不必进行磁盘I/O,因此效率较高。。临时表有两种:普通临时表 (#TbName)和全局临时表(##TbName)
普通临时表 属于创建该临时表的会话,会话结束时被释放,其他的会话不能使用
全局临时表 属于所有的会话,在所有会话结束时被释放
适用场合:高并发的场合(操作频繁,查询又多)
关于高并发的一些基本内容(后边会将用临时表改善高并发的方法):
1、只要进行表连接,那么肯定会做表的笛卡尔积(如join on时先做表的笛卡尔积,再筛选出满足on条件的数据)
2、数据库中的锁:
本例中锁的粒度在表级别上,用到的是X锁(排他锁)和S锁(共享锁)
insert update delete操作:表上添加X锁(其他的用户不能访问)
select操作:表上添加S锁(其他用户来的时候可以select,但是不能增删改)
3、简单死锁情况:
用户1的操作需要tb1和tb2两个表的资源,已经获取了tb1并给tb1加了X锁
用户2的操作需要tb1和tb2两个表的资源,已经获取了tb2并给tb2加了X锁
用户1和用户2都在等对方释放资源
其他用户来请求tb1和tb2时等待用户1和用户2释放资源
程序无法继续进行了
简单解决死锁:
①用户1和用户2获取资源的顺序都改成先获取资源1,再获取资源2
②获取资源时把资源1和资源2作为一个整体,一起获取
二、临时表的使用
2.1 临时表的基本使用
在创建数据库连接后创建一个临时表,连接期间像使用普通表一样使用
----基础用法 --创建临时表 create table #MyUserInfo ( id int primary key identity(1,1), username nvarchar(20) ) --使用临时表 select * from #MyUserInfo --释放资源 drop table #MyUserInfo --临时表的常用方式,把用户表的数据存入一个临时表(#MyUserInfo)中 select * into #MyUserInfo from Tb_UserInfo select * from #MyUserInfo --全局临时表,用法和普通临时表一样,用##TbName标识(开发中尽量不要自己创建,其他人也可能创建一个相同的全局临时表造成冲突) select into ##myUserInfoG from Tb_UserInfo drop table ##myUserInfoG ----一个简单的栗子 ----建一个临时表存储emp信息,更新task的名字为员工名_任务名 begin transaction ----删除临时表 if OBJECT_ID('tempdb..#emp_202006081740') is not null begin drop table #emp_202006081740 end ----创建临时表 create table #emp_202006081740(empid int ,empname varchar(50)) insert into #emp_202006081740(empid,empname) select emp_id,cname from dbo.emp --查询task表原始数据 select * from dbo.task --更新task名字 update t set t.cname=e.empname+'_'+t.cname from dbo.task t , #emp_202006081740 e where t.emp_id=e.empid --查询task表数据 select * from dbo.task rollback
2.2 临时表改善高并发
用临时表对高并发进行优化时,优化的原则是尽早释放表中的锁,如我们在对Tb_UserInfo和Tb_RoleInfo中的数据进行连接查询时,会对这两种表都添加S锁,其他用户对这两张表进行增删改操作时,要等待查询完成。我们通过临时表实现优化,就是让用户在查询时通过临时表来查询,尽早释放原表的S锁。
--临时表改善高并发 select * into #userinfo from Tb_UserInfo select * into #roleinfo from Tb_RoleInfo --执行下边查询时,原userinfo表和roleinfo表的s锁已经被释放了 select username,rolename from #userinfo as u join #roleinfo as r on u.roleid=r.rid