Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*******************************************************************
- * Script: JackRabbitOAK8977.sql ( https://pastebin.com/csh4fy42 )
- * By: Solomon Rutzky ( https://SqlQuantumLeap.com/ )
- * On: 2020-03-29
- * Issue: RDBBlobStore performance improvement for SQL Server (MSSQL)
- * https://issues.apache.org/jira/browse/OAK-8977
- * Purpose: Prove best combination is binary collation and stored proc.
- *******************************************************************/
- GO
- -- https://sqlquantumleap.com/2018/12/28/prevent-full-script-execution-understanding-and-using-parseonly-and-noexec/
- SET PARSEONLY ON;
- GO
- -- add RDBBlobStore performance test ( https://issues.apache.org/jira/browse/OAK-8926 )
- -- http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBBlobStoreDB.java?revision=1874271&view=markup
- --------------------------------------------------------------------------------
- --- BEGIN SETUP
- --- Highlight down to "END SETUP" and execute
- --------------------------------------------------------------------------------
- USE [tempdb];
- ---------------------------------------------------------
- -- DROP TABLE dbo.[DATASTORE_DATA];
- -- DROP TABLE dbo.[DATASTORE_META];
- CREATE TABLE dbo.[DATASTORE_DATA]
- (
- [ID] VARCHAR(64) COLLATE Latin1_General_CI_AS NOT NULL, -- Scenario = 1
- [DATA] VARBINARY(MAX),
- CONSTRAINT [DATASTORE_DATA_PK] PRIMARY KEY CLUSTERED ([ID] ASC)
- );
- CREATE TABLE dbo.[DATASTORE_META]
- (
- [ID] VARCHAR(64) COLLATE Latin1_General_CI_AS NOT NULL, -- Scenario = 1
- [LVL] INT,
- [LASTMOD] BIGINT,
- CONSTRAINT [DATASTORE_META_PK] PRIMARY KEY CLUSTERED ([ID] ASC)
- );
- ---------------------------------------------------------
- GO
- IF (OBJECT_ID(N'dbo.StoreBlockInDatabase') IS NULL)
- BEGIN
- EXEC(N'CREATE PROCEDURE dbo.[StoreBlockInDatabase] AS SET NOCOUNT ON;');
- END;
- GO
- ALTER PROCEDURE dbo.[StoreBlockInDatabase]
- (
- @Digest VARBINARY(32),
- @Level INT,
- @Data VARBINARY(MAX)
- )
- AS
- SET NOCOUNT ON;
- DECLARE @Id VARCHAR(64) = CONVERT(VARCHAR(64), @Digest, 2),
- @Now BIGINT;
- SELECT @Now = [cpu_ticks]
- FROM sys.dm_os_sys_info;
- BEGIN TRY
- UPDATE dbo.[DATASTORE_META]
- SET [LASTMOD] = @Now
- WHERE [ID] = @Id;
- IF (@@ROWCOUNT = 0)
- BEGIN
- INSERT INTO dbo.[DATASTORE_DATA] ([ID], [DATA]) VALUES (@Id, @Data);
- INSERT INTO dbo.[DATASTORE_META] ([ID], [LVL], [LASTMOD]) VALUES (@Id, @Level, @Now);
- END;
- END TRY
- BEGIN CATCH
- ;THROW;
- END CATCH;
- GO
- ---------------------------------------------------------
- GO
- IF (OBJECT_ID(N'dbo.StoreBlockInDatabase2') IS NULL)
- BEGIN
- EXEC(N'CREATE PROCEDURE dbo.[StoreBlockInDatabase2] AS SET NOCOUNT ON;');
- END;
- GO
- ALTER PROCEDURE dbo.[StoreBlockInDatabase2]
- (
- @Digest VARBINARY(32),
- @Level INT,
- @Data VARBINARY(MAX)
- )
- AS
- SET NOCOUNT ON;
- DECLARE @Id VARCHAR(64) = CONVERT(VARCHAR(64), @Digest, 2),
- @Now BIGINT;
- SELECT @Now = [cpu_ticks]
- FROM sys.dm_os_sys_info;
- BEGIN TRY
- IF (EXISTS(
- SELECT *
- FROM dbo.[DATASTORE_META]
- WHERE [ID] = @Id
- ))
- BEGIN
- UPDATE dbo.[DATASTORE_META]
- SET [LASTMOD] = @Now
- WHERE [ID] = @Id;
- END;
- ELSE
- BEGIN
- INSERT INTO dbo.[DATASTORE_DATA] ([ID], [DATA]) VALUES (@Id, @Data);
- INSERT INTO dbo.[DATASTORE_META] ([ID], [LVL], [LASTMOD]) VALUES (@Id, @Level, @Now);
- END;
- END TRY
- BEGIN CATCH
- ;THROW;
- END CATCH;
- GO
- ---------------------------------------------------------
- GO
- IF (OBJECT_ID(N'tempdb..#RunTests') IS NULL)
- BEGIN
- EXEC(N'CREATE PROCEDURE #RunTests AS SET NOCOUNT ON;');
- END;
- GO
- ALTER PROCEDURE #RunTests
- (
- @Iterations TINYINT = 10,
- @BlockSize INT = 1500,
- @DurationMS INT = 2000,
- @SingleTestPattern TINYINT = NULL
- )
- AS
- SET NOCOUNT ON;
- IF (OBJECT_ID(N'dbo.[TestResults]') IS NULL)
- BEGIN
- -- DROP TABLE dbo.[TestResults];
- CREATE TABLE dbo.[TestResults]
- (
- [TestResultsID] INT NOT NULL
- IDENTITY(1, 1)
- CONSTRAINT [PK_TestResults] PRIMARY KEY,
- [TestTime] DATETIME2 NOT NULL
- CONSTRAINT [DF_TestResults_TestTime] DEFAULT (SYSDATETIME()),
- [Scenario] TINYINT NOT NULL,
- [TestPattern] TINYINT NOT NULL,
- [RowsInserted] INT NOT NULL,
- [TotalRows] INT NOT NULL
- );
- END;
- DECLARE @TestPattern TINYINT = 1;
- DECLARE @Iteration TINYINT = 0,
- @RowCount INT = 0,
- @EndTime DATETIME2,
- @DATA VARBINARY(MAX),
- @Digest BINARY(32),
- @ID VARCHAR(64),
- @SQL NVARCHAR(MAX),
- @Scenario TINYINT;
- -- NOTE: Does not yet handle scenario 3!!
- SELECT @Scenario = CASE col.[collation_name]
- WHEN N'Latin1_General_CI_AS' THEN 1
- WHEN N'Latin1_General_BIN2' THEN 2
- ELSE 0
- END
- FROM sys.columns col
- WHERE col.[object_id] = OBJECT_ID(N'dbo.DATASTORE_META')
- AND col.[name] = N'ID';
- WHILE (@TestPattern < 7)
- BEGIN
- SET @Iteration = 0;
- -- Execute the following 2 statements when changing either TestPattern or Scenario (for consistency):
- TRUNCATE TABLE dbo.[DATASTORE_DATA];
- TRUNCATE TABLE dbo.[DATASTORE_META];
- WHILE (@Iteration < @Iterations)
- BEGIN
- SET @RowCount = 0;
- SET @EndTime = DATEADD(MILLISECOND, @DurationMS, SYSDATETIME());
- WHILE (SYSDATETIME() < @EndTime)
- BEGIN
- SET @DATA = CRYPT_GEN_RANDOM(@BlockSize);
- SET @Digest = HASHBYTES('SHA2_256', @DATA);
- SET @ID = CONVERT(VARCHAR(64), @Digest, 2);
- BEGIN TRAN; -- I think the JDBC code is doing this
- IF (@TestPattern = 1)
- BEGIN
- UPDATE dbo.[DATASTORE_META]
- SET [LASTMOD] = CONVERT(INT, GETDATE()) -- not a long / ticks, but close enough for this test
- WHERE [ID] = @ID;
- IF (@@ROWCOUNT = 0)
- BEGIN
- INSERT INTO dbo.[DATASTORE_DATA] ([ID], [DATA]) VALUES (@ID, @DATA);
- INSERT INTO dbo.[DATASTORE_META] ([ID], [LVL], [LASTMOD]) VALUES (@ID, 0, CONVERT(INT, GETDATE()));
- END;
- END;
- IF (@TestPattern = 2)
- BEGIN
- IF (EXISTS(
- SELECT *
- FROM dbo.[DATASTORE_META]
- WHERE [ID] = @ID
- ))
- BEGIN
- UPDATE dbo.[DATASTORE_META]
- SET [LASTMOD] = CONVERT(INT, GETDATE()) -- not a long / ticks, but close enough for this test
- WHERE [ID] = @ID;
- END;
- ELSE
- BEGIN
- INSERT INTO dbo.[DATASTORE_DATA] ([ID], [DATA]) VALUES (@ID, @DATA);
- INSERT INTO dbo.[DATASTORE_META] ([ID], [LVL], [LASTMOD]) VALUES (@ID, 0, CONVERT(INT, GETDATE()));
- END;
- END;
- IF (@TestPattern = 3)
- BEGIN
- SET @SQL = N'
- UPDATE dbo.[DATASTORE_META]
- SET [LASTMOD] = CONVERT(INT, GETDATE()) -- not a long / ticks, but close enough for this test
- WHERE [ID] = ''' + @ID + N''';
- IF (@@ROWCOUNT = 0)
- BEGIN
- INSERT INTO dbo.[DATASTORE_DATA] ([ID], [DATA]) VALUES (''' + @ID + N''', ' + CONVERT(NVARCHAR(MAX), @DATA, 1) + N');
- INSERT INTO dbo.[DATASTORE_META] ([ID], [LVL], [LASTMOD]) VALUES (''' + @ID + N''', 0, CONVERT(INT, GETDATE()));
- END;
- ';
- EXEC(@SQL);
- END;
- IF (@TestPattern = 4)
- BEGIN
- SET @SQL = N'EXEC dbo.[StoreBlockInDatabase] 0x' + @ID + N', 0, ' + CONVERT(NVARCHAR(MAX), @DATA, 1) + N';';
- EXEC(@SQL);
- END;
- IF (@TestPattern = 5)
- BEGIN
- EXEC sp_executesql
- N'EXEC dbo.[StoreBlockInDatabase] @tmpDigest, 0, @tmpData;',
- N'@tmpDigest VARBINARY(32), @tmpData VARBINARY(MAX)',
- @tmpDigest = @Digest,
- @tmpData = @DATA;
- END;
- IF (@TestPattern = 6)
- BEGIN
- EXEC sp_executesql
- N'EXEC dbo.[StoreBlockInDatabase2] @tmpDigest, 0, @tmpData;',
- N'@tmpDigest VARBINARY(32), @tmpData VARBINARY(MAX)',
- @tmpDigest = @Digest,
- @tmpData = @DATA;
- END;
- COMMIT TRAN; -- I think the JDBC code is doing this
- SET @RowCount += 1;
- END;
- INSERT INTO dbo.[TestResults] ([Scenario], [TestPattern], [RowsInserted], [TotalRows])
- OUTPUT INSERTED.*
- SELECT @Scenario, @TestPattern, @RowCount, COUNT(*)
- FROM dbo.[DATASTORE_DATA];
- SET @Iteration += 1;
- WAITFOR DELAY '00:00:00.500'; -- half-second delay
- END;
- SET @TestPattern += 1;
- END;
- GO
- --------------------------------------------------------------------------------
- --- END SETUP
- --------------------------------------------------------------------------------
- -- Exec test proc, apply Scenario 2 changes, then exec test proc again:
- EXEC #RunTests;
- ----------------------------------------
- -- Scenario = 2 (change collation to binary)
- ALTER TABLE [DATASTORE_DATA] DROP CONSTRAINT [DATASTORE_DATA_PK];
- ALTER TABLE [DATASTORE_DATA] ALTER COLUMN [ID] VARCHAR(64) COLLATE Latin1_General_BIN2 NOT NULL;
- ALTER TABLE [DATASTORE_DATA] ADD CONSTRAINT [DATASTORE_DATA_PK] PRIMARY KEY CLUSTERED ([ID] ASC);
- ALTER TABLE [DATASTORE_META] DROP CONSTRAINT [DATASTORE_META_PK];
- ALTER TABLE [DATASTORE_META] ALTER COLUMN [ID] VARCHAR(64) COLLATE Latin1_General_BIN2 NOT NULL;
- ALTER TABLE [DATASTORE_META] ADD CONSTRAINT [DATASTORE_META_PK] PRIMARY KEY CLUSTERED ([ID] ASC);
- ----------------------------------------
- EXEC #RunTests;
- /* -- Highlight and execute as necessary:
- SELECT * FROM dbo.[DATASTORE_DATA];
- SELECT * FROM dbo.[DATASTORE_META];
- DELETE FROM dbo.[TestResults] WHERE [TestResultsID] = xyz;
- SELECT * FROM dbo.[TestResults];
- */
- -- TestPattern 3 = close approximation of current code
- -- TestPattern 5 = proposed stored procedure approach
- SELECT [Scenario], [TestPattern],
- COUNT([RowsInserted]) AS [TestCount],
- MIN([RowsInserted]) AS [MinRows],
- AVG([RowsInserted]) AS [AvgRows],
- MAX([RowsInserted]) AS [MaxRows],
- SUM([RowsInserted]) AS [TotalRows]
- FROM dbo.[TestResults]
- GROUP BY [Scenario], [TestPattern]
- ORDER BY [Scenario], [TestPattern];
- /*
- Scenario TestPattern TestCount MinRows AvgRows MaxRows TotalRows
- 1 1 10 11605 13329 14583 133297
- 1 2 10 11409 14522 16547 145221
- 1 3 10 1681 2108 2322 21080
- 2 1 10 12755 16064 17108 160640
- 2 2 10 13959 15312 16927 153125
- 2 3 10 2144 2422 2696 24228
- 2 4 10 2238 3012 3802 30121
- 2 5 10 963 4876 6626 48768
- 2 6 10 907 4696 6532 46969
- */
- ----------------------------------------
- -- Scenario = 3 (keep binary collation, change PK to NONclustered)
- ALTER TABLE [DATASTORE_DATA] DROP CONSTRAINT [DATASTORE_DATA_PK];
- ALTER TABLE [DATASTORE_DATA] ALTER COLUMN [ID] VARCHAR(64) COLLATE Latin1_General_BIN2 NOT NULL;
- ALTER TABLE [DATASTORE_DATA] ADD CONSTRAINT [DATASTORE_DATA_PK] PRIMARY KEY NONCLUSTERED ([ID] ASC);
- ALTER TABLE [DATASTORE_META] DROP CONSTRAINT [DATASTORE_META_PK];
- ALTER TABLE [DATASTORE_META] ALTER COLUMN [ID] VARCHAR(64) COLLATE Latin1_General_BIN2 NOT NULL;
- ALTER TABLE [DATASTORE_META] ADD CONSTRAINT [DATASTORE_META_PK] PRIMARY KEY NONCLUSTERED ([ID] ASC);
- ----------------------------------------
- GO
- -- https://sqlquantumleap.com/2018/12/28/prevent-full-script-execution-understanding-and-using-parseonly-and-noexec/
- SET PARSEONLY OFF;
- GO
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement