0
私は1700万レコードテーブルにカーソルを使用しています。それは実際には遅いです、毎秒30ラウンドと言いましょう。どこから始めたらいいのか分かりません。SQL Serverのストアドプロシージャが極端に遅い
すべてのデータを1つのテーブルから、各ストリームのデータが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
カーソルを使用しないでください。基本クエリの設定を変更しました – Squirrel
特に17億行に! – scsimon