我在1700万条记录表上使用了光标。它真的很慢,比方说每秒30发。我不知道从哪里开始。
它将1个表中的所有数据传输到多个表中,每个表每年都有数据。
以下是代码:
CREATE PROCEDURE [dbo].[Importer2]
AS
BEGIN
SET NOCOUNT ON;
DECLARE @LogId bigint;
DECLARE @SensorID int;
DECLARE @ValueNumeric decimal(12,4);
DECLARE @ValueString nvarchar(20);
DECLARE @DateAdded datetime;
DECLARE @Status_ NVARCHAR(10)
DECLARE @SQLString_ NVARCHAR(MAX)
DECLARE @Year_ NVARCHAR(4)
DECLARE @TableName_ NVARCHAR(100) --= '[ScadaData].[dbo].[2016_123456]'
DECLARE @TableNameOnly_ NVARCHAR(100)
DECLARE @ValueStringTMP_ NVARCHAR(20)
DECLARE @Measure_ datetime
DECLARE @ImporterCursor AS CURSOR;
SET @Status_ = 'OK'
SELECT @LogId = Value
FROM dbo.AppSettings
WHERE dbo.AppSettings.Setting = 'LastImportedId';
SET @ImporterCursor = CURSOR FAST_FORWARD FOR
SELECT *
FROM dbo.Logs l
WHERE l.LogID > @LogId;
OPEN @ImporterCursor;
FETCH NEXT FROM @ImporterCursor INTO @LogId, @SensorID, @ValueNumeric, @ValueString, @DateAdded;
WHILE @@FETCH_STATUS = 0
BEGIN
IF (@DateAdded IS NOT null)
BEGIN
SET @TableName_ = '[ScadaData].[dbo].[Y' + CONVERT(varchar,YEAR(@DateAdded)) + 'S' + CONVERT(varchar,@SensorID) + ']'
SET @TableNameOnly_ = 'Y' + CONVERT(varchar,YEAR(@DateAdded)) + 'S' + CONVERT(varchar,@SensorID)
--table does not exists. Create one
IF NOT EXISTS (SELECT 1 FROM ScadaData.dbo.sysobjects
WHERE xtype = 'U' AND name = @TableNameOnly_)
BEGIN
SET @SQLString_ = 'CREATE TABLE ' + @TableName_ + '(
[LogID] [bigint] IDENTITY(1,1) NOT NULL,
[ValueNumeric] [decimal](12, 4) NULL,
[ValueString] [nvarchar](20) NULL,
[DateAdded] [datetime2](7) NULL DEFAULT (GETUTCDATE()),
CONSTRAINT [PK_Logs' + @TableNameOnly_ + '] PRIMARY KEY CLUSTERED ([LogID] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY];
CREATE NONCLUSTERED INDEX [DateAddedDESC_' + @TableNameOnly_ + '] ON [dbo].[' + @TableNameOnly_ + '] ([DateAdded] DESC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON);'
EXEC sp_executesql @SQLString_
END
--Insert or Update if ValueNumeric is sent
IF @ValueNumeric IS NOT NULL
BEGIN
SET @SQLString_ = 'DECLARE @ValueNumericTmp_ DECIMAL(12,4);'
SET @SQLString_ = @SQLString_ + 'DECLARE @LogID BIGINT;'
SET @SQLString_ = @SQLString_ + 'SELECT TOP 1 @ValueNumericTmp_ = ValueNumeric, @LogID = LogID FROM ' + @TableName_ + ' ORDER BY DateAdded DESC;'
SET @SQLString_ = @SQLString_ + 'IF (@ValueNumericTmp_ = ' + CONVERT(varchar, @ValueNumeric) + ')'
SET @SQLString_ = @SQLString_ + ' UPDATE ' + @TableName_ + ' SET DateAdded = ''' + CONVERT(varchar,@DateAdded,121) + ''' WHERE LogID = @LogID;'
SET @SQLString_ = @SQLString_ + 'ELSE'
SET @SQLString_ = @SQLString_ + ' INSERT INTO ' + @TableName_ + ' (ValueNumeric, ValueString, DateAdded) VALUES (' + CONVERT(varchar,@ValueNumeric) +', ' + ISNULL('''' + @ValueString + '''','NULL') + ', GETUTCDATE());'
EXEC (@SQLString_)
END
--Insert or Update if ValueString is sent
IF @ValueString IS NOT NULL
BEGIN
SET @SQLString_ = 'DECLARE @ValueStringTMP_ NVARCHAR(20);'
SET @SQLString_ = @SQLString_ + 'DECLARE @LogID BIGINT;'
SET @SQLString_ = @SQLString_ + 'SELECT TOP 1 @ValueStringTMP_ = ValueString, @LogID = LogID FROM ' + @TableName_ + ' ORDER BY DateAdded DESC;'
SET @SQLString_ = @SQLString_ + 'IF (@ValueStringTMP_ = ''' + @ValueString + ''')'
SET @SQLString_ = @SQLString_ + ' UPDATE ' + @TableName_ + ' SET DateAdded = ''' + CONVERT(varchar,@DateAdded,121) + ''' WHERE LogID = @LogID;'
SET @SQLString_ = @SQLString_ + 'ELSE'
SET @SQLString_ = @SQLString_ + ' INSERT INTO ' + @TableName_ + ' (ValueNumeric, ValueString, DateAdded) VALUES (' + CONVERT(varchar,@ValueNumeric) +', ''' + @ValueString + ''', GETUTCDATE());'
EXEC sp_executesql @SQLString_
END
END
UPDATE dbo.AppSettings
SET dbo.AppSettings.[Value] = CAST(@LogId AS VARCHAR (50))
WHERE dbo.AppSettings.Setting = 'LastImportedId';
FETCH NEXT FROM @ImporterCursor INTO @LogId, @SensorID, @ValueNumeric, @ValueString, @DateAdded;
END
CLOSE @ImporterCursor;
DEALLOCATE @ImporterCursor;
END
答案 0 :(得分:2)
你有很多问题 如前所述,第一个红旗是光标 但是,有时你不能在没有光标的情况下支持逻辑,这是你的理由。
其次,您使用动态SQL。它也有助于提高绩效。
但是,你最大的问题是应用程序设计 您不得从日志中为每个传感器创建单独的表。
简单的解决方案是创建仅一个" tbl_Sensors
"带有附加列SensorID
的表,并重复使用1700次,而不是重新创建1700个表。