Sql server SQL Server-优化并提高此过程的效率
Azure SQL Server 2016 w/Azure SQL数据库: 我们每24小时运行一次此过程。目前,执行该程序平均每天需要10-12小时 程序如下:Sql server SQL Server-优化并提高此过程的效率,sql-server,stored-procedures,azure-sql-database,sql-server-2016,Sql Server,Stored Procedures,Azure Sql Database,Sql Server 2016,Azure SQL Server 2016 w/Azure SQL数据库: 我们每24小时运行一次此过程。目前,执行该程序平均每天需要10-12小时 程序如下: EXEC PROCEDURE [dbo].[SyncDataFromTransfer] AS BEGIN DECLARE @taskSourceId bigint, @syncBatch uniqueidentifier = newid() DECLARE curSources cursor FOR SELECT
EXEC PROCEDURE [dbo].[SyncDataFromTransfer]
AS
BEGIN
DECLARE @taskSourceId bigint,
@syncBatch uniqueidentifier = newid()
DECLARE curSources cursor
FOR
SELECT TaskSourceId
FROM [Transfer].CaptureSync
GROUP BY TaskSourceId
OPEN curSources
FETCH NEXT FROM curSources
INTO @taskSourceId
WHILE @@fetch_status = 0
BEGIN
-- insert the rows into the capture table, but do not flag as active
INSERT INTO [Data].Capture (
[TaskSourceId]
,[Identifier]
,[IndividualName]
,[EntityName]
,[Text]
,[RawSource]
,[CaptureBatch]
,[IsActive]
,[CaptureDateTime]
,[SyncBatchId]
)
SELECT [TaskSourceId]
,[Identifier]
,[IndividualName]
,[EntityName]
,[Text]
,[RawSource]
,[CaptureBatch]
,0 -- isActive
,[CaptureDateTime]
,@syncBatch -- SyncBatchId
FROM [Transfer].CaptureSync
WHERE TaskSourceId = @taskSourceId
-- flag the new rows as active
UPDATE [Data].Capture
SET IsActive = 1
WHERE TaskSourceId = @taskSourceId
AND SyncBatchId = @syncBatch
-- remove the existing rows
DELETE [Data].Capture
WHERE TaskSourceId = @taskSourceId
AND SyncBatchId != @syncBatch
-- get the next source
FETCH NEXT FROM curSources INTO @taskSourceId
END -- end of the cursor
CLOSE curSources
DEALLOCATE curSources
END
GO
简而言之:Data.Capture
是我们的生产表,它包含了我们所有的最新记录。此表每24小时刷新一次(通过上述存储过程),以创建最新信息的数据集。Data.Capture
中的记录按TaskSourceId
分组。一个TaskSourceId
具有许多来自同一web源的记录
每24小时一次,web scraper将数据写入Transfer.CaptureSync
表,该表充当保留表。此存储过程的目的是进入Transfer.CaptureSync
的记录,一次一个TaskSourceId
,替换数据中的记录组。捕获与该TaskSourceId
相关的记录,因此,对于给定的TaskSourceId
,我们总是在Data.Capture
中获取最新信息
然而,并非所有的TaskSourceId的
每天都有新记录,哪些每天都有新记录,每天都会有所不同。因此,当给定的TaskSourceId
在某一天没有新记录时,我们只想保留数据中已经存在的最新记录。捕获
我希望这一解释有意义——概括一下:
从网站获取最新信息并写入Transfer.CaptureSync
将数据中的信息。通过TaskSourceId
捕获替换为Transfer.CaptureSync
中的信息
如果在传输.CaptureSync
中不存在给定TaskSourceId
的一组记录,则在数据.Capture
中保留与该TaskSourceId
相关的上一次传输的记录集
每天完成该过程后,Transfer.CaptureSync表将被截断
Data.Capture
表大约有400万条记录,而Transfer.CaptureSync
表每天大约有300万条记录
考虑到所有这些信息,我们回到手头的问题。此过程平均每天运行10-12小时,占用宝贵的资源很长时间
这是实现这一目标的最有效和最佳方法吗?我意识到“最有效和最佳”有些主观。我正在寻找SQL专家,而我不是。你看过表的分区吗
如果按TaskSourceId对Transfer.CaptureSync表和Data.Capture表进行分区,则应该能够切换分区和切换分区。将分区切换作为事务处理,传输过程应该减少到几秒钟而不是几小时,同时保持数据完整性
再想一想:
这是假设表是相同的结构。如果不是,您可以拥有一个分区的暂存表,其结构与Data.Capture表相同。数据暂存不应花费太多时间,因为您所要做的只是复制数据,而不进行任何特定的更新或删除
正如前面所讨论的分区示例(请确保您在生产环境中没有这样做,或者没有任何重要的数据库称为“游乐场”)::
现在我只使用了三行,但是切换过程是一个元数据操作,几乎是瞬时的。无论临时表是有3行还是有100万行,这个过程都将花费大约相同的时间您看过表的分区了吗
如果按TaskSourceId对Transfer.CaptureSync表和Data.Capture表进行分区,则应该能够切换分区和切换分区。将分区切换作为事务处理,传输过程应该减少到几秒钟而不是几小时,同时保持数据完整性
再想一想:
这是假设表是相同的结构。如果不是,您可以拥有一个分区的暂存表,其结构与Data.Capture表相同。数据暂存不应花费太多时间,因为您所要做的只是复制数据,而不进行任何特定的更新或删除
正如前面所讨论的分区示例(请确保您在生产环境中没有这样做,或者没有任何重要的数据库称为“游乐场”)::
现在我只使用了三行,但是切换过程是一个元数据操作,几乎是瞬时的。无论临时表有3行还是100万行,[CaptureSync]每天都会被截断,因此,请删除光标,通过在TaskSourceId上加入[CaptureSync]将其插入[CAPTURE]。这只会影响[CAPTURESYNC]中存在TaskSourceId的行
您可以保留更新,但如果您四处询问为什么插入新行时不活动设置为0的业务原因,您可能找不到。(我看不到技术原因)如果是这种情况,请将不活动插入修改为1
删除应该更改为在TaskSooSeCID上考虑[CopturSyc]的行。
Delete C
From Capture C
Inner join DataCapture D on D.TaskSourceId = C.TaskSourceId
And C.SyncBatchId <> @SyncBatch
删除C
从捕获C
D.TaskSourceId=C.TaskSourceId上的内部联接数据捕获D
和C.SyncBatchId@SyncBatch
[CaptureSync]每天都会被截断,因此请移除光标,通过加入TaskSourceId上的[CaptureSync]插入[CAPTURE]。这只会影响[CAPTURESYNC]中存在TaskSourceId的行
您可以保留更新,但如果您四处询问为什么插入新行时未激活设置为0的业务原因,您可能找不到。(我看不到技术。)
Delete C
From Capture C
Inner join DataCapture D on D.TaskSourceId = C.TaskSourceId
And C.SyncBatchId <> @SyncBatch