我编写了一个带有 SQL Server 后端的应用程序,用于收集和存储大量记录。我已经计算出,在高峰期,平均记录量大约为每天 3-40 亿条(运行 20 小时)。
我最初的解决方案(在我完成数据的实际计算之前)是让我的应用程序将记录插入到我的客户查询的同一个表中。显然,这会很快崩溃并烧毁,因为不可能查询插入了这么多记录的表。
我的第二个解决方案是使用 2 个数据库,一个用于应用程序接收的数据,另一个用于客户端就绪数据。
我的应用程序将接收数据,将其分成大约 10 万条记录的批次,然后批量插入到临时表中。在大约 100k 条记录之后,应用程序将使用与之前相同的架构即时创建另一个临时表,并开始插入到该表中。它将在具有 10 万条记录的作业表中创建一条记录,并且 SQL Server 端的存储过程会将数据从临时表移动到客户端就绪的生产表,然后删除我的应用程序创建的表临时表。
除了具有作业表的临时数据库外,两个数据库都具有相同的 5 个表集,具有相同的架构。临时数据库在大量记录将驻留的表上没有完整性约束、键、索引等。如下所示,表名是SignalValues_staging
. 目标是让我的应用程序尽快将数据发送到 SQL Server。动态创建表以便轻松迁移的工作流程非常有效。
以下是我的临时数据库中的 5 个相关表,以及我的工作表:
我编写的存储过程处理从所有临时表中移动数据并将其插入到生产中。下面是我的存储过程的一部分,它从临时表插入到生产中:
-- Signalvalues jobs table.
SELECT *
,ROW_NUMBER() OVER (ORDER BY JobId) AS 'RowIndex'
INTO #JobsToProcess
FROM
(
SELECT JobId
,ProcessingComplete
,SignalValueStagingTableName AS 'TableName'
,(DATEDIFF(SECOND, (SELECT last_user_update
FROM sys.dm_db_index_usage_stats
WHERE database_id = DB_ID(DB_NAME())
AND OBJECT_ID = OBJECT_ID(SignalValueStagingTableName))
,GETUTCDATE())) SecondsSinceLastUpdate
FROM SignalValueJobs
) cte
WHERE cte.ProcessingComplete = 1 …
Run Code Online (Sandbox Code Playgroud) 我有一个存储过程,它每隔一段时间运行一次作业,以 BCP 处理我编写的应用程序留下的一些文件。
我注意到文件堆积如山,而 BCP 没有提取它们,因此我使用以下命令在 Management Studio 中进行了测试:
DECLARE @sql VARCHAR(MAX)
DECLARE @path VARCHAR(512) = 'C:\BCPFiles\'
--Use BCP to copy files in character format from the target directly into the table.
SET @sql = 'bcp [MyDB].[dbo].[MyTable] in ' + @path + 'bcpFile.dat -c -T'
EXEC master..xp_cmdshell @sql
Run Code Online (Sandbox Code Playgroud)
并收到此错误消息
使用相同的命令从同一台服务器上的命令行执行没有问题。
以下是其他一些观察结果:
EXEC master..xp_cmdshell 'dir C:\*.*'
并且结果按预期返回。NT SERVICE\MSSQLSERVER
对目录具有完全控制权限。任何帮助表示赞赏。
我一直在尝试让这个 Service Broker 和计时器的东西连续工作一个多星期,所以如果这看起来像……呃……愤怒,请耐心等待。在 SQL Server 方面,我也相当缺乏经验。
我已经建立了两个数据库来处理非常大量的数据。第一个数据库用于暂存,表没有参照完整性,我的应用程序将重磅这些表只是为了将数据放入数据库中。这很好用。第二个数据库用于生产就绪数据,具有完整性约束等......我已经设置了指向Production
的表的同义词Staging
。
我已经设置了一个 Service Broker 计时器队列/服务,每隔几秒钟执行一次,以将数据从已完成的临时表迁移到生产中。其 SQL 如下:
IF EXISTS (SELECT * FROM sys.services WHERE name = 'My_MigrationService')
BEGIN
DROP SERVICE My_MigrationService
END
GO
IF EXISTS (SELECT * FROM sys.service_queues WHERE name = 'My_MigrationQueue')
BEGIN
DROP QUEUE My_MigrationQueue
END
GO
CREATE QUEUE My_MigrationQueue
GO
CREATE SERVICE My_MigrationService ON QUEUE My_MigrationQueue ([DEFAULT])
GO
ALTER QUEUE My_MigrationQueue
WITH ACTIVATION (
STATUS = ON
, MAX_QUEUE_READERS = 1
, EXECUTE AS OWNER
, …
Run Code Online (Sandbox Code Playgroud)