交换ms sql表

交换ms sql表,sql,swap,Sql,Swap,我想以最好的方式切换到表。 我有一个IpToCountry表,我每周根据导入的外部CSV文件创建一个新表 我发现最快的切换方法是执行以下操作: sp_rename IpToCountry IpToCountryOld go sp_rename IpToCountryNew IpToCountry go 问题是在这段时间内仍可能访问该表。 如何在SQL中处理此问题? 在考虑使用sp_getapplock和sp_releaseapplock时,我希望尽可能快地从表中读取函数。iptocontrol

我想以最好的方式切换到表。
我有一个IpToCountry表,我每周根据导入的外部CSV文件创建一个新表

我发现最快的切换方法是执行以下操作:

sp_rename IpToCountry IpToCountryOld
go
sp_rename IpToCountryNew IpToCountry
go
问题是在这段时间内仍可能访问该表。
如何在SQL中处理此问题?

在考虑使用sp_getapplock和sp_releaseapplock时,我希望尽可能快地从表中读取函数。

iptocontrold会发生什么?你把它扔掉了吗?在这种情况下,为什么不截断IpToCountry并导入我的新数据呢

如果需要保留数据,那么将加载日期存储在表中,并将“当前”加载日期存储在WHERE子句中使用的某个位置如何?然后切换数据成功加载时的当前日期


您没有说您正在使用哪个数据库,所以我不知道这有多大用处,但是您是否有任何引用该表的存储过程?请注意,在某些平台上,SPs是使用表的内部引用进行编译的,这些表不会随重命名而更改,因此存在SPs在不重新编译的情况下无法获取新数据的风险。视图和存储的解析查询也是如此。

您不能在非工作时间导入到一个表吗

或者,为什么不进行数据更新,即在循环导入数据时,更新现有记录并逐个记录添加任何新记录。这将允许表保持活动状态,并减少添加和删除完整表的总体影响


导入数据的结构、表设计、格式、主键等是什么?因此,我们可以给您一个更好的答案。

假设您无法更新/插入到现有表中,为什么不使用一个

例如,您可能最初将数据存储在一个名为IPtoCountry2009 0303的表中,您的视图如下所示:

CREATE VIEW IpToCountry
AS
SELECT * FROM IpToCountry20090303
当新数据输入时,您可以创建并填充IPtoCountry2009 0310表。填充表后,只需更新视图:

ALTER VIEW IpToCountry
AS
SELECT * FROM IpToCountry20090310

该开关将是完全原子的,不需要任何显式锁定或事务。视图更新后,您只需删除旧表(或者保留它,如果您愿意)。

实现您希望实现的另一种方法是使用表分区,这是SQL Server企业版中提供的一种技术

表名可以保持不变。表导入完成后,只需切换出包含旧数据的分区,然后切换到新分区

下面的白皮书包含您开始学习所需的所有信息


干杯,John

我在让分区函数按比例工作时遇到了问题。创建和删除分区都是阻塞操作,您对阻塞几乎没有控制权,如果无法获得锁,它将以16级的严重性失败,并终止您的连接—在不重新建立连接的情况下,您无法捕获并重试连接。但这可能对你很好。此外,MSS企业版是必需的,您不能使用SE——对于一些较小或更关注成本的商店来说,SE可能太多了

我还发现视图redef在sys表和对象上以高比例阻塞(=事务量+不断插入的数据量,在我的例子中),因此这些操作可能会在诸如重新索引和dtcc之类的事情上死锁——在一种情况下,特别是SSMS中的用户(所有的事情)试图在对象浏览器中浏览视图(需要有人告诉那些家伙关于READPAST的事情)。同样,你的里程数可能会有所不同

相比之下,sp_重命名在规模上对我来说效果很好:它让你可以控制锁定和锁定范围。要在交换之前解决阻塞问题,请按如下所示进行尝试。从表面上看,这似乎在高容量下也有同样的规模问题……但我在实践中没有看到。因此,对我来说是可行的……但同样,每个人都需要一个经验是不同的

DECLARE @dummylock bit 
BEGIN TRANSACTION 
BEGIN TRY
   -- necessary to obtain exclusive lock on the table prior to swapping
   SELECT @dummylock = 1 WHERE EXISTS (SELECT 1 FROM A WITH (TABLOCKX))
   -- may or may not be necessary in your case
   SELECT @dummylock = 1 WHERE EXISTS (SELECT 1 FROM B WITH (TABLOCKX))
   exec sp_rename 'A', 'TEMP'
   exec sp_rename 'B', 'A'
   exec sp_rename 'TEMP', 'B'
   COMMIT TRANSACTION
END TRY
BEGIN CATCH
   -- other error handling here if needed
   ROLLBACK TRANSACTION 
END CATCH

刚刚在处理一个临时表时遇到了类似的问题,该表在使用适当的锁进行扩展时遇到了问题

在引用表的任何地方,都可以调用一个存储过程,询问表名


存储过程可以根据提供的参数选择创建新表或返回旧表。

Hi Mike,我使用的是SQL server 2000。基本上,旧表是不相关的。数据导入需要几秒钟(到新表+索引)。我想用最小的系统损坏来替换数据…我使用的是SQL server 2000。IPtoCountryLD不相关,实际上可能已被截断和删除。我正在重命名,因为它更快,然后我删除了旧表…数据是ip地址(fromIp、toIp(加起来就是PK)、国家、地区、城市)。由于IP范围总是在变化,使用delete和insert进行更新将非常困难。我可以在非工作时间进行更新,但替换操作仍会导致停机。我正在尝试找出建议的方法…嗨,John,这是一些有趣的东西。虽然在SQL2000中,我仍将被迫使用视图分区,但这很好。我知道了要做的一些阅读:)您可以对sp_getapplock和sp_releaseapplock执行相同的操作,但OP没有want@gbn,我认为sp_getapplock的工作原理与此不同。sp_getapplock将阻止一个代码块的两次同时执行,但除非读取该数据的每个命令也使用相同的锁(可能在共享模式下),否则当第一个表不存在时,没有什么可以阻止读取的执行。sp_getapplock中的资源名称只是一个任意字符串,除非sp_getapplock对该表的所有访问都设置了门控,否则可能会发生不好的事情。通过在表本身上使用TABLOCKX,不会发生读取,并且您不会