在 SQL Server 数据库之间移动数据行是不是有比使用 CTE 更快的方法?

Posted

技术标签:

【中文标题】在 SQL Server 数据库之间移动数据行是不是有比使用 CTE 更快的方法?【英文标题】:Is there a faster way of moving rows of data between SQL Server databases than using CTE's?在 SQL Server 数据库之间移动数据行是否有比使用 CTE 更快的方法? 【发布时间】:2015-03-25 16:50:09 【问题描述】:

我在 SQL Server 2012 Express 上使用以下查询将 4 天以前的数据从一个 [主] 数据库移到另一个 [辅助数据库] 以进行归档。唯一的问题是这会使数据库脱机,因为它通常要移动大约 50 万行数据,而且随着更多数据点被添加到数据库中,这个数字正在攀升。结果是我的基于 Web 的应用程序无法访问数据库(在大多数情况下)大约 2 小时,这会导致许多其他进程以及应用程序停止。

DECLARE @4daysago datetime
SELECT @4daysago = DATEADD(d, -4, GetDate());

SET IDENTITY_INSERT [activetrackarchivedb].dbo.[Data Import] ON;

--Transfer from current (production) DB to Archive DB
WITH CTE as (
    SELECT TOP 1000000 *
    FROM [activetrackdb].dbo.[Data Import] 
    WHERE [activetrackdb].dbo.[Data Import].[Receive Date] < @7daysago
    ORDER BY [Receive Date] ASC)
DELETE CTE
  OUTPUT DELETED.id, 
  DELETED.[Company id], 
  DELETED.[Site id],
  DELETED.[Site name],
  DELETED.[Receive date],
  DELETED.[Detect date],
  INTO  [activetrackarchivedb].dbo.[Data Import] 
  (id, 
  [Company id], 
  [Site id],
  [Site name],
  [Receive date],
  [Detect date]);

有没有更好的方法可以用来“转移”这些行?即使新方法速度较慢,如果它至少仍然可以允许访问数据库。这个花了我一周的时间来实现(我是新手),并参与了 *** 社区的帮助。到现在为止都很好,但是随着数据量的增加,它变得非常繁琐。

这也不是用于备份目的。将行转移到的数据库只是具有更高的容量,并且归档数据仍在生产环境中使用(它只是使主数据库在与其他维护和索引脚本结合时更具可维护性和响应性)

任何帮助将不胜感激。

【问题讨论】:

如果您没有接收日期的索引,您还可以测试创建它是否会使其更快。特别是如果您以较小的批次多次执行此操作,那么索引应该会有所帮助。 尽管 Stack Overflow 有许多成员拥有扎实的 SQL Server 编程技能,但这可能更像是一个 DBA 问题,我会将问题发布到Database Administrators,因为该社区更针对管理问题(或者我相信)。 您为什么使用 CTE?你想以某种方式批处理这个吗? 感谢 bot 的回复。我已经在那个coloumn上有一个索引,它确实有帮助,但它仍然很慢......我将在Database Administrators Excahnge上重新发布 - 好点。将保持两者,直到我解决这个问题:) 没有特殊原因 RE CTE,有什么更好的? 【参考方案1】:

在 SSIS (2008) 和许多其他地方,SQL Server 默认行号大小为 10000。您可能想尝试一次执行的行大小,但我怀疑较小的大小可能最终会执行快很多。

【讨论】:

【参考方案2】:

为什么不直接运行这样的东西(假设表具有相同的字段):

SET IDENTITY_INSERT [activetrackarchivedb].dbo.[Data Import] ON;

DELETE FROM [activetrackdb].dbo.[Data Import]
OUTPUT DELETED.* INTO  [activetrackarchivedb].dbo.[Data Import] 
WHERE [activetrackdb].dbo.[Data Import].[Receive Date] < DATEADD(DAY,-4,GETDATE())

我不明白为什么这需要一分钟以上的时间,而且可能比这要少得多。 500k 行对于 SQL Server 来说并不算多。在我的笔记本电脑上完成具有该行数的类似语句大约需要 5 秒。

【讨论】:

我不知道我为什么会到达我所做的地方,所以你可能是对的。我已经尝试过,但出现以下错误: Msg 8101, Level 16, State 1, Line 1 只有在使用列列表并且 IDENTITY_INSERT 时才能指定表“activetrackarchivedb.dbo.Data Import”中标识列的显式值已开启。 哦,是的,如果您要将数据插入到目标表的主键中,您仍然需要在查询中使用该语句。我更新了我的代码示例。 现在得到了这个,但我的列是相同的,日期时间和 varchars? '从字符串转换日期和/或时间时,消息 241,级别 16,状态 1,第 3 行转换失败。'【参考方案3】:

根据您的评论,CTE 似乎没有必要。您可以使用更简单的查询来完成。

DELETE FROM [activetrackdb].dbo.[Data Import]
  OUTPUT 
      DELETED.id, 
      DELETED.[Company id], 
      DELETED.[Site id],
      DELETED.[Site name],
      DELETED.[Receive date],
      DELETED.[Detect date]
  INTO  [activetrackarchivedb].dbo.[Data Import] 
      (id, 
       [Company id], 
       [Site id],
       [Site name],
       [Receive date],
       [Detect date]) 
WHERE [Receive Date] < @7daysago

【讨论】:

这会加快速度吗? @Chen_Dogg 可能。不必创建 CTE 会有所帮助。这在很大程度上取决于实际的执行计划、索引等。真正知道的唯一方法是尝试。 (我的猜测是应该的,但要确定的因素太多了。)

以上是关于在 SQL Server 数据库之间移动数据行是不是有比使用 CTE 更快的方法?的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 中是不是有一种方法可以显示两个具有相同布局并共享一些公共数据的表之间的字段差异

sqlserver支持的字符集都有哪些

确定一个 POINT 是不是位于 LINESTRING 上的两个其他 POINT 之间(SQL Server 2008 Geography)

MS SQL Server“之间”是不是包括范围边界?

MySql数据库数据类型和Sql Server 数据库数据类型之间的差异

如何修改sql server 2000 里的表中的内容?