您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

692 行
25 KiB

  1. -- This file is part of Hangfire.
  2. -- Copyright © 2013-2014 Sergey Odinokov.
  3. --
  4. -- Hangfire is free software: you can redistribute it and/or modify
  5. -- it under the terms of the GNU Lesser General Public License as
  6. -- published by the Free Software Foundation, either version 3
  7. -- of the License, or any later version.
  8. --
  9. -- Hangfire is distributed in the hope that it will be useful,
  10. -- but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. -- GNU Lesser General Public License for more details.
  13. --
  14. -- You should have received a copy of the GNU Lesser General Public
  15. -- License along with Hangfire. If not, see <http://www.gnu.org/licenses/>.
  16. SET NOCOUNT ON
  17. SET XACT_ABORT ON
  18. DECLARE @TARGET_SCHEMA_VERSION INT;
  19. DECLARE @DISABLE_HEAVY_MIGRATIONS BIT;
  20. SET @TARGET_SCHEMA_VERSION = 7;
  21. --SET @DISABLE_HEAVY_MIGRATIONS = 1;
  22. PRINT 'Installing Hangfire SQL objects...';
  23. BEGIN TRANSACTION;
  24. -- Acquire exclusive lock to prevent deadlocks caused by schema creation / version update
  25. DECLARE @SchemaLockResult INT;
  26. EXEC @SchemaLockResult = sp_getapplock @Resource = 'HangFire:SchemaLock', @LockMode = 'Exclusive'
  27. -- Create the database schema if it doesn't exists
  28. IF NOT EXISTS (SELECT [schema_id] FROM [sys].[schemas] WHERE [name] = 'HangFire')
  29. BEGIN
  30. EXEC (N'CREATE SCHEMA [HangFire]');
  31. PRINT 'Created database schema [HangFire]';
  32. END
  33. ELSE
  34. PRINT 'Database schema [HangFire] already exists';
  35. DECLARE @SCHEMA_ID int;
  36. SELECT @SCHEMA_ID = [schema_id] FROM [sys].[schemas] WHERE [name] = 'HangFire';
  37. -- Create the [HangFire].Schema table if not exists
  38. IF NOT EXISTS(SELECT [object_id] FROM [sys].[tables]
  39. WHERE [name] = 'Schema' AND [schema_id] = @SCHEMA_ID)
  40. BEGIN
  41. CREATE TABLE [HangFire].[Schema](
  42. [Version] [int] NOT NULL,
  43. CONSTRAINT [PK_HangFire_Schema] PRIMARY KEY CLUSTERED ([Version] ASC)
  44. );
  45. PRINT 'Created table [HangFire].[Schema]';
  46. END
  47. ELSE
  48. PRINT 'Table [HangFire].[Schema] already exists';
  49. DECLARE @CURRENT_SCHEMA_VERSION int;
  50. SELECT @CURRENT_SCHEMA_VERSION = [Version] FROM [HangFire].[Schema];
  51. PRINT 'Current Hangfire schema version: ' + CASE WHEN @CURRENT_SCHEMA_VERSION IS NULL THEN 'none' ELSE CONVERT(nvarchar, @CURRENT_SCHEMA_VERSION) END;
  52. IF @CURRENT_SCHEMA_VERSION IS NOT NULL AND @CURRENT_SCHEMA_VERSION > @TARGET_SCHEMA_VERSION
  53. BEGIN
  54. ROLLBACK TRANSACTION;
  55. PRINT 'Hangfire current database schema version ' + CAST(@CURRENT_SCHEMA_VERSION AS NVARCHAR) +
  56. ' is newer than the configured SqlServerStorage schema version ' + CAST(@TARGET_SCHEMA_VERSION AS NVARCHAR) +
  57. '. Will not apply any migrations.';
  58. RETURN;
  59. END
  60. -- Install [HangFire] schema objects
  61. IF @CURRENT_SCHEMA_VERSION IS NULL
  62. BEGIN
  63. IF @DISABLE_HEAVY_MIGRATIONS = 1
  64. BEGIN
  65. SET @DISABLE_HEAVY_MIGRATIONS = 0;
  66. PRINT 'Enabling HEAVY_MIGRATIONS, because we are installing objects from scratch';
  67. END
  68. PRINT 'Installing schema version 1';
  69. -- Create job tables
  70. CREATE TABLE [HangFire].[Job] (
  71. [Id] [int] IDENTITY(1,1) NOT NULL,
  72. [StateId] [int] NULL,
  73. [StateName] [nvarchar](20) NULL, -- To speed-up queries.
  74. [InvocationData] [nvarchar](max) NOT NULL,
  75. [Arguments] [nvarchar](max) NOT NULL,
  76. [CreatedAt] [datetime] NOT NULL,
  77. [ExpireAt] [datetime] NULL,
  78. CONSTRAINT [PK_HangFire_Job] PRIMARY KEY CLUSTERED ([Id] ASC)
  79. );
  80. PRINT 'Created table [HangFire].[Job]';
  81. CREATE NONCLUSTERED INDEX [IX_HangFire_Job_StateName] ON [HangFire].[Job] ([StateName] ASC);
  82. PRINT 'Created index [IX_HangFire_Job_StateName]';
  83. -- Job history table
  84. CREATE TABLE [HangFire].[State] (
  85. [Id] [int] IDENTITY(1,1) NOT NULL,
  86. [JobId] [int] NOT NULL,
  87. [Name] [nvarchar](20) NOT NULL,
  88. [Reason] [nvarchar](100) NULL,
  89. [CreatedAt] [datetime] NOT NULL,
  90. [Data] [nvarchar](max) NULL,
  91. CONSTRAINT [PK_HangFire_State] PRIMARY KEY CLUSTERED ([Id] ASC)
  92. );
  93. PRINT 'Created table [HangFire].[State]';
  94. ALTER TABLE [HangFire].[State] ADD CONSTRAINT [FK_HangFire_State_Job] FOREIGN KEY([JobId])
  95. REFERENCES [HangFire].[Job] ([Id])
  96. ON UPDATE CASCADE
  97. ON DELETE CASCADE;
  98. PRINT 'Created constraint [FK_HangFire_State_Job]';
  99. CREATE NONCLUSTERED INDEX [IX_HangFire_State_JobId] ON [HangFire].[State] ([JobId] ASC);
  100. PRINT 'Created index [IX_HangFire_State_JobId]';
  101. -- Job parameters table
  102. CREATE TABLE [HangFire].[JobParameter](
  103. [Id] [int] IDENTITY(1,1) NOT NULL,
  104. [JobId] [int] NOT NULL,
  105. [Name] [nvarchar](40) NOT NULL,
  106. [Value] [nvarchar](max) NULL,
  107. CONSTRAINT [PK_HangFire_JobParameter] PRIMARY KEY CLUSTERED ([Id] ASC)
  108. );
  109. PRINT 'Created table [HangFire].[JobParameter]';
  110. ALTER TABLE [HangFire].[JobParameter] ADD CONSTRAINT [FK_HangFire_JobParameter_Job] FOREIGN KEY([JobId])
  111. REFERENCES [HangFire].[Job] ([Id])
  112. ON UPDATE CASCADE
  113. ON DELETE CASCADE;
  114. PRINT 'Created constraint [FK_HangFire_JobParameter_Job]';
  115. CREATE NONCLUSTERED INDEX [IX_HangFire_JobParameter_JobIdAndName] ON [HangFire].[JobParameter] (
  116. [JobId] ASC,
  117. [Name] ASC
  118. );
  119. PRINT 'Created index [IX_HangFire_JobParameter_JobIdAndName]';
  120. -- Job queue table
  121. CREATE TABLE [HangFire].[JobQueue](
  122. [Id] [int] IDENTITY(1,1) NOT NULL,
  123. [JobId] [int] NOT NULL,
  124. [Queue] [nvarchar](20) NOT NULL,
  125. [FetchedAt] [datetime] NULL,
  126. CONSTRAINT [PK_HangFire_JobQueue] PRIMARY KEY CLUSTERED ([Id] ASC)
  127. );
  128. PRINT 'Created table [HangFire].[JobQueue]';
  129. CREATE NONCLUSTERED INDEX [IX_HangFire_JobQueue_JobIdAndQueue] ON [HangFire].[JobQueue] (
  130. [JobId] ASC,
  131. [Queue] ASC
  132. );
  133. PRINT 'Created index [IX_HangFire_JobQueue_JobIdAndQueue]';
  134. CREATE NONCLUSTERED INDEX [IX_HangFire_JobQueue_QueueAndFetchedAt] ON [HangFire].[JobQueue] (
  135. [Queue] ASC,
  136. [FetchedAt] ASC
  137. );
  138. PRINT 'Created index [IX_HangFire_JobQueue_QueueAndFetchedAt]';
  139. -- Servers table
  140. CREATE TABLE [HangFire].[Server](
  141. [Id] [nvarchar](50) NOT NULL,
  142. [Data] [nvarchar](max) NULL,
  143. [LastHeartbeat] [datetime] NULL,
  144. CONSTRAINT [PK_HangFire_Server] PRIMARY KEY CLUSTERED ([Id] ASC)
  145. );
  146. PRINT 'Created table [HangFire].[Server]';
  147. -- Extension tables
  148. CREATE TABLE [HangFire].[Hash](
  149. [Id] [int] IDENTITY(1,1) NOT NULL,
  150. [Key] [nvarchar](100) NOT NULL,
  151. [Name] [nvarchar](40) NOT NULL,
  152. [StringValue] [nvarchar](max) NULL,
  153. [IntValue] [int] NULL,
  154. [ExpireAt] [datetime] NULL,
  155. CONSTRAINT [PK_HangFire_Hash] PRIMARY KEY CLUSTERED ([Id] ASC)
  156. );
  157. PRINT 'Created table [HangFire].[Hash]';
  158. CREATE UNIQUE NONCLUSTERED INDEX [UX_HangFire_Hash_KeyAndName] ON [HangFire].[Hash] (
  159. [Key] ASC,
  160. [Name] ASC
  161. );
  162. PRINT 'Created index [UX_HangFire_Hash_KeyAndName]';
  163. CREATE TABLE [HangFire].[List](
  164. [Id] [int] IDENTITY(1,1) NOT NULL,
  165. [Key] [nvarchar](100) NOT NULL,
  166. [Value] [nvarchar](max) NULL,
  167. [ExpireAt] [datetime] NULL,
  168. CONSTRAINT [PK_HangFire_List] PRIMARY KEY CLUSTERED ([Id] ASC)
  169. );
  170. PRINT 'Created table [HangFire].[List]';
  171. CREATE TABLE [HangFire].[Set](
  172. [Id] [int] IDENTITY(1,1) NOT NULL,
  173. [Key] [nvarchar](100) NOT NULL,
  174. [Score] [float] NOT NULL,
  175. [Value] [nvarchar](256) NOT NULL,
  176. [ExpireAt] [datetime] NULL,
  177. CONSTRAINT [PK_HangFire_Set] PRIMARY KEY CLUSTERED ([Id] ASC)
  178. );
  179. PRINT 'Created table [HangFire].[Set]';
  180. CREATE UNIQUE NONCLUSTERED INDEX [UX_HangFire_Set_KeyAndValue] ON [HangFire].[Set] (
  181. [Key] ASC,
  182. [Value] ASC
  183. );
  184. PRINT 'Created index [UX_HangFire_Set_KeyAndValue]';
  185. CREATE TABLE [HangFire].[Value](
  186. [Id] [int] IDENTITY(1,1) NOT NULL,
  187. [Key] [nvarchar](100) NOT NULL,
  188. [StringValue] [nvarchar](max) NULL,
  189. [IntValue] [int] NULL,
  190. [ExpireAt] [datetime] NULL,
  191. CONSTRAINT [PK_HangFire_Value] PRIMARY KEY CLUSTERED (
  192. [Id] ASC
  193. )
  194. );
  195. PRINT 'Created table [HangFire].[Value]';
  196. CREATE UNIQUE NONCLUSTERED INDEX [UX_HangFire_Value_Key] ON [HangFire].[Value] (
  197. [Key] ASC
  198. );
  199. PRINT 'Created index [UX_HangFire_Value_Key]';
  200. CREATE TABLE [HangFire].[Counter](
  201. [Id] [int] IDENTITY(1,1) NOT NULL,
  202. [Key] [nvarchar](100) NOT NULL,
  203. [Value] [tinyint] NOT NULL,
  204. [ExpireAt] [datetime] NULL,
  205. CONSTRAINT [PK_HangFire_Counter] PRIMARY KEY CLUSTERED ([Id] ASC)
  206. );
  207. PRINT 'Created table [HangFire].[Counter]';
  208. CREATE NONCLUSTERED INDEX [IX_HangFire_Counter_Key] ON [HangFire].[Counter] ([Key] ASC)
  209. INCLUDE ([Value]);
  210. PRINT 'Created index [IX_HangFire_Counter_Key]';
  211. SET @CURRENT_SCHEMA_VERSION = 1;
  212. END
  213. IF @CURRENT_SCHEMA_VERSION = 1
  214. BEGIN
  215. PRINT 'Installing schema version 2';
  216. -- https://github.com/odinserj/HangFire/issues/83
  217. DROP INDEX [IX_HangFire_Counter_Key] ON [HangFire].[Counter];
  218. ALTER TABLE [HangFire].[Counter] ALTER COLUMN [Value] SMALLINT NOT NULL;
  219. CREATE NONCLUSTERED INDEX [IX_HangFire_Counter_Key] ON [HangFire].[Counter] ([Key] ASC)
  220. INCLUDE ([Value]);
  221. PRINT 'Index [IX_HangFire_Counter_Key] re-created';
  222. DROP TABLE [HangFire].[Value];
  223. DROP TABLE [HangFire].[Hash];
  224. PRINT 'Dropped tables [HangFire].[Value] and [HangFire].[Hash]'
  225. DELETE FROM [HangFire].[Server] WHERE [LastHeartbeat] IS NULL;
  226. ALTER TABLE [HangFire].[Server] ALTER COLUMN [LastHeartbeat] DATETIME NOT NULL;
  227. SET @CURRENT_SCHEMA_VERSION = 2;
  228. END
  229. IF @CURRENT_SCHEMA_VERSION = 2
  230. BEGIN
  231. PRINT 'Installing schema version 3';
  232. DROP INDEX [IX_HangFire_JobQueue_JobIdAndQueue] ON [HangFire].[JobQueue];
  233. PRINT 'Dropped index [IX_HangFire_JobQueue_JobIdAndQueue]';
  234. CREATE TABLE [HangFire].[Hash](
  235. [Id] [int] IDENTITY(1,1) NOT NULL,
  236. [Key] [nvarchar](100) NOT NULL,
  237. [Field] [nvarchar](100) NOT NULL,
  238. [Value] [nvarchar](max) NULL,
  239. [ExpireAt] [datetime2](7) NULL,
  240. CONSTRAINT [PK_HangFire_Hash] PRIMARY KEY CLUSTERED ([Id] ASC)
  241. );
  242. PRINT 'Created table [HangFire].[Hash]';
  243. CREATE UNIQUE NONCLUSTERED INDEX [UX_HangFire_Hash_Key_Field] ON [HangFire].[Hash] (
  244. [Key] ASC,
  245. [Field] ASC
  246. );
  247. PRINT 'Created index [UX_HangFire_Hash_Key_Field]';
  248. SET @CURRENT_SCHEMA_VERSION = 3;
  249. END
  250. IF @CURRENT_SCHEMA_VERSION = 3
  251. BEGIN
  252. PRINT 'Installing schema version 4';
  253. CREATE TABLE [HangFire].[AggregatedCounter] (
  254. [Id] [int] IDENTITY(1,1) NOT NULL,
  255. [Key] [nvarchar](100) NOT NULL,
  256. [Value] [bigint] NOT NULL,
  257. [ExpireAt] [datetime] NULL,
  258. CONSTRAINT [PK_HangFire_CounterAggregated] PRIMARY KEY CLUSTERED ([Id] ASC)
  259. );
  260. PRINT 'Created table [HangFire].[AggregatedCounter]';
  261. CREATE UNIQUE NONCLUSTERED INDEX [UX_HangFire_CounterAggregated_Key] ON [HangFire].[AggregatedCounter] (
  262. [Key] ASC
  263. ) INCLUDE ([Value]);
  264. PRINT 'Created index [UX_HangFire_CounterAggregated_Key]';
  265. CREATE NONCLUSTERED INDEX [IX_HangFire_Hash_ExpireAt] ON [HangFire].[Hash] ([ExpireAt])
  266. INCLUDE ([Id]);
  267. CREATE NONCLUSTERED INDEX [IX_HangFire_Job_ExpireAt] ON [HangFire].[Job] ([ExpireAt])
  268. INCLUDE ([Id]);
  269. CREATE NONCLUSTERED INDEX [IX_HangFire_List_ExpireAt] ON [HangFire].[List] ([ExpireAt])
  270. INCLUDE ([Id]);
  271. CREATE NONCLUSTERED INDEX [IX_HangFire_Set_ExpireAt] ON [HangFire].[Set] ([ExpireAt])
  272. INCLUDE ([Id]);
  273. PRINT 'Created indexes for [ExpireAt] columns';
  274. CREATE NONCLUSTERED INDEX [IX_HangFire_Hash_Key] ON [HangFire].[Hash] ([Key] ASC)
  275. INCLUDE ([ExpireAt]);
  276. PRINT 'Created index [IX_HangFire_Hash_Key]';
  277. CREATE NONCLUSTERED INDEX [IX_HangFire_List_Key] ON [HangFire].[List] ([Key] ASC)
  278. INCLUDE ([ExpireAt], [Value]);
  279. PRINT 'Created index [IX_HangFire_List_Key]';
  280. CREATE NONCLUSTERED INDEX [IX_HangFire_Set_Key] ON [HangFire].[Set] ([Key] ASC)
  281. INCLUDE ([ExpireAt], [Value]);
  282. PRINT 'Created index [IX_HangFire_Set_Key]';
  283. SET @CURRENT_SCHEMA_VERSION = 4;
  284. END
  285. IF @CURRENT_SCHEMA_VERSION = 4
  286. BEGIN
  287. PRINT 'Installing schema version 5';
  288. DROP INDEX [IX_HangFire_JobQueue_QueueAndFetchedAt] ON [HangFire].[JobQueue];
  289. PRINT 'Dropped index [IX_HangFire_JobQueue_QueueAndFetchedAt] to modify the [HangFire].[JobQueue].[Queue] column';
  290. ALTER TABLE [HangFire].[JobQueue] ALTER COLUMN [Queue] NVARCHAR (50) NOT NULL;
  291. PRINT 'Modified [HangFire].[JobQueue].[Queue] length to 50';
  292. CREATE NONCLUSTERED INDEX [IX_HangFire_JobQueue_QueueAndFetchedAt] ON [HangFire].[JobQueue] (
  293. [Queue] ASC,
  294. [FetchedAt] ASC
  295. );
  296. PRINT 'Re-created index [IX_HangFire_JobQueue_QueueAndFetchedAt]';
  297. ALTER TABLE [HangFire].[Server] DROP CONSTRAINT [PK_HangFire_Server]
  298. PRINT 'Dropped constraint [PK_HangFire_Server] to modify the [HangFire].[Server].[Id] column';
  299. ALTER TABLE [HangFire].[Server] ALTER COLUMN [Id] NVARCHAR (100) NOT NULL;
  300. PRINT 'Modified [HangFire].[Server].[Id] length to 100';
  301. ALTER TABLE [HangFire].[Server] ADD CONSTRAINT [PK_HangFire_Server] PRIMARY KEY CLUSTERED
  302. (
  303. [Id] ASC
  304. );
  305. PRINT 'Re-created constraint [PK_HangFire_Server]';
  306. SET @CURRENT_SCHEMA_VERSION = 5;
  307. END
  308. IF @CURRENT_SCHEMA_VERSION = 5 AND @DISABLE_HEAVY_MIGRATIONS = 1
  309. BEGIN
  310. PRINT 'Migration process STOPPED at schema version ' + CAST(@CURRENT_SCHEMA_VERSION AS NVARCHAR) +
  311. '. WILL NOT upgrade to schema version ' + CAST(@TARGET_SCHEMA_VERSION AS NVARCHAR) +
  312. ', because @DISABLE_HEAVY_MIGRATIONS option is set.';
  313. END
  314. ELSE IF @CURRENT_SCHEMA_VERSION = 5
  315. BEGIN
  316. PRINT 'Installing schema version 6';
  317. -- First, we will drop all the secondary indexes on the HangFire.Set table, because we will
  318. -- modify that table, and unknown indexes may be added there (see https://github.com/HangfireIO/Hangfire/issues/844).
  319. -- So, we'll drop all of them, and then re-create the required index with a well-known name.
  320. DECLARE @dropIndexSql NVARCHAR(MAX) = N'';
  321. SELECT @dropIndexSql += N'DROP INDEX ' + QUOTENAME(SCHEMA_NAME(o.[schema_id])) + '.' + QUOTENAME(o.name) + '.' + QUOTENAME(i.name) + ';'
  322. FROM sys.indexes AS i
  323. INNER JOIN sys.tables AS o
  324. ON i.[object_id] = o.[object_id]
  325. WHERE i.is_primary_key = 0
  326. AND i.index_id <> 0
  327. AND o.is_ms_shipped = 0
  328. AND SCHEMA_NAME(o.[schema_id]) = 'HangFire'
  329. AND o.name = 'Set';
  330. EXEC sp_executesql @dropIndexSql;
  331. PRINT 'Dropped all secondary indexes on the [Set] table';
  332. -- Next, we'll remove the unnecessary indexes. They were unnecessary in the previous schema,
  333. -- and are unnecessary in the new schema as well. We'll not re-create them.
  334. DROP INDEX [IX_HangFire_Hash_Key] ON [HangFire].[Hash];
  335. PRINT 'Dropped unnecessary index [IX_HangFire_Hash_Key]';
  336. -- Next, all the indexes that cover expiration will be filtered, to include only non-null values. This
  337. -- will prevent unnecessary index modifications – we are seeking these indexes only for non-null
  338. -- expiration time. Also, they include the Id column by a mistake. So we'll re-create them later in the
  339. -- migration.
  340. DROP INDEX [IX_HangFire_Hash_ExpireAt] ON [HangFire].[Hash];
  341. PRINT 'Dropped index [IX_HangFire_Hash_ExpireAt]';
  342. DROP INDEX [IX_HangFire_Job_ExpireAt] ON [HangFire].[Job];
  343. PRINT 'Dropped index [IX_HangFire_Job_ExpireAt]';
  344. DROP INDEX [IX_HangFire_List_ExpireAt] ON [HangFire].[List];
  345. PRINT 'Dropped index [IX_HangFire_List_ExpireAt]';
  346. -- IX_HangFire_Job_StateName index can also be optimized, since we are querying it only with a
  347. -- non-null state name. This will decrease the number of operations, when creating a background job.
  348. -- It will be recreated later in the migration.
  349. DROP INDEX [IX_HangFire_Job_StateName] ON [HangFire].Job;
  350. PRINT 'Dropped index [IX_HangFire_Job_StateName]';
  351. -- Dropping foreign key constraints based on the JobId column, because we need to modify the underlying
  352. -- column type of the clustered index to BIGINT. We'll recreate them later in the migration.
  353. ALTER TABLE [HangFire].[JobParameter] DROP CONSTRAINT [FK_HangFire_JobParameter_Job];
  354. PRINT 'Dropped constraint [FK_HangFire_JobParameter_Job]';
  355. ALTER TABLE [HangFire].[State] DROP CONSTRAINT [FK_HangFire_State_Job];
  356. PRINT 'Dropped constraint [FK_HangFire_State_Job]';
  357. -- We are going to create composite clustered indexes that are more natural for the following tables,
  358. -- so the following indexes will be unnecessary. Natural sorting will keep related data close to each
  359. -- other, and simplify the index modifications by the cost of fragmentation and additional page splits.
  360. DROP INDEX [UX_HangFire_CounterAggregated_Key] ON [HangFire].[AggregatedCounter];
  361. PRINT 'Dropped index [UX_HangFire_CounterAggregated_Key]';
  362. DROP INDEX [IX_HangFire_Counter_Key] ON [HangFire].[Counter];
  363. PRINT 'Dropped index [IX_HangFire_Counter_Key]';
  364. DROP INDEX [IX_HangFire_JobParameter_JobIdAndName] ON [HangFire].[JobParameter];
  365. PRINT 'Dropped index [IX_HangFire_JobParameter_JobIdAndName]';
  366. DROP INDEX [IX_HangFire_JobQueue_QueueAndFetchedAt] ON [HangFire].[JobQueue];
  367. PRINT 'Dropped index [IX_HangFire_JobQueue_QueueAndFetchedAt]';
  368. DROP INDEX [UX_HangFire_Hash_Key_Field] ON [HangFire].[Hash];
  369. PRINT 'Dropped index [UX_HangFire_Hash_Key_Field]';
  370. DROP INDEX [IX_HangFire_List_Key] ON [HangFire].[List];
  371. PRINT 'Dropped index [IX_HangFire_List_Key]';
  372. DROP INDEX [IX_HangFire_State_JobId] ON [HangFire].[State];
  373. PRINT 'Dropped index [IX_HangFire_State_JobId]';
  374. -- Then, we need to drop the primary key constraints, to modify id columns to the BIGINT type. Some of them
  375. -- will be re-created later in the migration. But some of them would be removed forever, because their
  376. -- uniqueness property sometimes unnecessary.
  377. ALTER TABLE [HangFire].[AggregatedCounter] DROP CONSTRAINT [PK_HangFire_CounterAggregated];
  378. PRINT 'Dropped constraint [PK_HangFire_CounterAggregated]';
  379. ALTER TABLE [HangFire].[Counter] DROP CONSTRAINT [PK_HangFire_Counter];
  380. PRINT 'Dropped constraint [PK_HangFire_Counter]';
  381. ALTER TABLE [HangFire].[Hash] DROP CONSTRAINT [PK_HangFire_Hash];
  382. PRINT 'Dropped constraint [PK_HangFire_Hash]';
  383. ALTER TABLE [HangFire].[Job] DROP CONSTRAINT [PK_HangFire_Job];
  384. PRINT 'Dropped constraint [PK_HangFire_Job]';
  385. ALTER TABLE [HangFire].[JobParameter] DROP CONSTRAINT [PK_HangFire_JobParameter];
  386. PRINT 'Dropped constraint [PK_HangFire_JobParameter]';
  387. ALTER TABLE [HangFire].[JobQueue] DROP CONSTRAINT [PK_HangFire_JobQueue];
  388. PRINT 'Dropped constraint [PK_HangFire_JobQueue]';
  389. ALTER TABLE [HangFire].[List] DROP CONSTRAINT [PK_HangFire_List];
  390. PRINT 'Dropped constraint [PK_HangFire_List]';
  391. ALTER TABLE [HangFire].[Set] DROP CONSTRAINT [PK_HangFire_Set];
  392. PRINT 'Dropped constraint [PK_HangFire_Set]';
  393. ALTER TABLE [HangFire].[State] DROP CONSTRAINT [PK_HangFire_State];
  394. PRINT 'Dropped constraint [PK_HangFire_State]';
  395. -- We are removing identity columns of the following tables completely, their clustered
  396. -- index will be based on natural values. So, instead of modifying them to BIGINT, we
  397. -- are dropping them.
  398. ALTER TABLE [HangFire].[AggregatedCounter] DROP COLUMN [Id];
  399. PRINT 'Dropped [AggregatedCounter].[Id] column, we will cluster on [Key] column with uniqufier';
  400. ALTER TABLE [HangFire].[Counter] DROP COLUMN [Id];
  401. PRINT 'Dropped [Counter].[Id] column, we will cluster on [Key] column';
  402. ALTER TABLE [HangFire].[Hash] DROP COLUMN [Id];
  403. PRINT 'Dropped [Hash].[Id] column, we will cluster on [Key]/[Field] columns';
  404. ALTER TABLE [HangFire].[Set] DROP COLUMN [Id];
  405. PRINT 'Dropped [Set].[Id] column, we will cluster on [Key]/[Value] columns';
  406. ALTER TABLE [HangFire].[JobParameter] DROP COLUMN [Id];
  407. PRINT 'Dropped [JobParameter].[Id] column, we will cluster on [JobId]/[Name] columns';
  408. -- Then we need to modify all the remaining Id columns to be of type BIGINT.
  409. ALTER TABLE [HangFire].[List] ALTER COLUMN [Id] BIGINT NOT NULL;
  410. PRINT 'Modified [List].[Id] type to BIGINT';
  411. ALTER TABLE [HangFire].[Job] ALTER COLUMN [Id] BIGINT NOT NULL;
  412. PRINT 'Modified [Job].[Id] type to BIGINT';
  413. ALTER TABLE [HangFire].[Job] ALTER COLUMN [StateId] BIGINT NULL;
  414. PRINT 'Modified [Job].[StateId] type to BIGINT';
  415. ALTER TABLE [HangFire].[JobParameter] ALTER COLUMN [JobId] BIGINT NOT NULL;
  416. PRINT 'Modified [JobParameter].[JobId] type to BIGINT';
  417. ALTER TABLE [HangFire].[JobQueue] ALTER COLUMN [JobId] BIGINT NOT NULL;
  418. PRINT 'Modified [JobQueue].[JobId] type to BIGINT';
  419. ALTER TABLE [HangFire].[State] ALTER COLUMN [Id] BIGINT NOT NULL;
  420. PRINT 'Modified [State].[Id] type to BIGINT';
  421. ALTER TABLE [HangFire].[State] ALTER COLUMN [JobId] BIGINT NOT NULL;
  422. PRINT 'Modified [State].[JobId] type to BIGINT';
  423. ALTER TABLE [HangFire].[Counter] ALTER COLUMN [Value] INT NOT NULL;
  424. PRINT 'Modified [Counter].[Value] type to INT';
  425. -- Adding back all the Primary Key constraints or clustered indexes where PKs aren't appropriate.
  426. ALTER TABLE [HangFire].[AggregatedCounter] ADD CONSTRAINT [PK_HangFire_CounterAggregated] PRIMARY KEY CLUSTERED (
  427. [Key] ASC
  428. );
  429. PRINT 'Re-created constraint [PK_HangFire_CounterAggregated]';
  430. CREATE CLUSTERED INDEX [CX_HangFire_Counter] ON [HangFire].[Counter] ([Key]);
  431. PRINT 'Created clustered index [CX_HangFire_Counter]';
  432. ALTER TABLE [HangFire].[Hash] ADD CONSTRAINT [PK_HangFire_Hash] PRIMARY KEY CLUSTERED (
  433. [Key] ASC,
  434. [Field] ASC
  435. );
  436. PRINT 'Re-created constraint [PK_HangFire_Hash]';
  437. ALTER TABLE [HangFire].[Job] ADD CONSTRAINT [PK_HangFire_Job] PRIMARY KEY CLUSTERED ([Id] ASC);
  438. PRINT 'Re-created constraint [PK_HangFire_Job]';
  439. ALTER TABLE [HangFire].[JobParameter] ADD CONSTRAINT [PK_HangFire_JobParameter] PRIMARY KEY CLUSTERED (
  440. [JobId] ASC,
  441. [Name] ASC
  442. );
  443. PRINT 'Re-created constraint [PK_HangFire_JobParameter]';
  444. ALTER TABLE [HangFire].[JobQueue] ADD CONSTRAINT [PK_HangFire_JobQueue] PRIMARY KEY CLUSTERED (
  445. [Queue] ASC,
  446. [Id] ASC
  447. );
  448. PRINT 'Re-created constraint [PK_HangFire_JobQueue]';
  449. ALTER TABLE [HangFire].[List] ADD CONSTRAINT [PK_HangFire_List] PRIMARY KEY CLUSTERED (
  450. [Key] ASC,
  451. [Id] ASC
  452. );
  453. PRINT 'Re-created constraint [PK_HangFire_List]';
  454. ALTER TABLE [HangFire].[Set] ADD CONSTRAINT [PK_HangFire_Set] PRIMARY KEY CLUSTERED (
  455. [Key] ASC,
  456. [Value] ASC
  457. );
  458. PRINT 'Re-created constraint [PK_HangFire_Set]';
  459. ALTER TABLE [HangFire].[State] ADD CONSTRAINT [PK_HangFire_State] PRIMARY KEY CLUSTERED (
  460. [JobId] ASC,
  461. [Id]
  462. );
  463. PRINT 'Re-created constraint [PK_HangFire_State]';
  464. -- Creating secondary, nonclustered indexes
  465. CREATE NONCLUSTERED INDEX [IX_HangFire_Job_StateName] ON [HangFire].[Job] ([StateName])
  466. WHERE [StateName] IS NOT NULL;
  467. PRINT 'Re-created index [IX_HangFire_Job_StateName]';
  468. CREATE NONCLUSTERED INDEX [IX_HangFire_Set_Score] ON [HangFire].[Set] ([Score])
  469. WHERE [Score] IS NOT NULL;
  470. PRINT 'Created index [IX_HangFire_Set_Score]';
  471. CREATE NONCLUSTERED INDEX [IX_HangFire_Server_LastHeartbeat] ON [HangFire].[Server] ([LastHeartbeat]);
  472. PRINT 'Created index [IX_HangFire_Server_LastHeartbeat]';
  473. -- Creating filtered indexes for ExpireAt columns
  474. CREATE NONCLUSTERED INDEX [IX_HangFire_AggregatedCounter_ExpireAt] ON [HangFire].[AggregatedCounter] ([ExpireAt])
  475. WHERE [ExpireAt] IS NOT NULL;
  476. PRINT 'Created index [IX_HangFire_AggregatedCounter_ExpireAt]';
  477. CREATE NONCLUSTERED INDEX [IX_HangFire_Hash_ExpireAt] ON [HangFire].[Hash] ([ExpireAt])
  478. WHERE [ExpireAt] IS NOT NULL;
  479. PRINT 'Re-created index [IX_HangFire_Hash_ExpireAt]';
  480. CREATE NONCLUSTERED INDEX [IX_HangFire_Job_ExpireAt] ON [HangFire].[Job] ([ExpireAt])
  481. INCLUDE ([StateName])
  482. WHERE [ExpireAt] IS NOT NULL;
  483. PRINT 'Re-created index [IX_HangFire_Job_ExpireAt]';
  484. CREATE NONCLUSTERED INDEX [IX_HangFire_List_ExpireAt] ON [HangFire].[List] ([ExpireAt])
  485. WHERE [ExpireAt] IS NOT NULL;
  486. PRINT 'Re-created index [IX_HangFire_List_ExpireAt]';
  487. CREATE NONCLUSTERED INDEX [IX_HangFire_Set_ExpireAt] ON [HangFire].[Set] ([ExpireAt])
  488. WHERE [ExpireAt] IS NOT NULL;
  489. PRINT 'Re-created index [IX_HangFire_Set_ExpireAt]';
  490. -- Restoring foreign keys
  491. ALTER TABLE [HangFire].[State] ADD CONSTRAINT [FK_HangFire_State_Job] FOREIGN KEY([JobId])
  492. REFERENCES [HangFire].[Job] ([Id])
  493. ON UPDATE CASCADE
  494. ON DELETE CASCADE;
  495. PRINT 'Re-created constraint [FK_HangFire_State_Job]';
  496. ALTER TABLE [HangFire].[JobParameter] ADD CONSTRAINT [FK_HangFire_JobParameter_Job] FOREIGN KEY([JobId])
  497. REFERENCES [HangFire].[Job] ([Id])
  498. ON UPDATE CASCADE
  499. ON DELETE CASCADE;
  500. PRINT 'Re-created constraint [FK_HangFire_JobParameter_Job]';
  501. SET @CURRENT_SCHEMA_VERSION = 6;
  502. END
  503. IF @CURRENT_SCHEMA_VERSION = 6
  504. BEGIN
  505. PRINT 'Installing schema version 7';
  506. DROP INDEX [IX_HangFire_Set_Score] ON [HangFire].[Set];
  507. PRINT 'Dropped index [IX_HangFire_Set_Score]';
  508. CREATE NONCLUSTERED INDEX [IX_HangFire_Set_Score] ON [HangFire].[Set] ([Key], [Score]);
  509. PRINT 'Created index [IX_HangFire_Set_Score] with the proper composite key';
  510. SET @CURRENT_SCHEMA_VERSION = 7;
  511. END
  512. /*IF @CURRENT_SCHEMA_VERSION = 7
  513. BEGIN
  514. PRINT 'Installing schema version 8';
  515. Insert migration here
  516. SET @CURRENT_SCHEMA_VERSION = 8;
  517. END*/
  518. UPDATE [HangFire].[Schema] SET [Version] = @CURRENT_SCHEMA_VERSION
  519. IF @@ROWCOUNT = 0
  520. INSERT INTO [HangFire].[Schema] ([Version]) VALUES (@CURRENT_SCHEMA_VERSION)
  521. PRINT 'Hangfire database schema installed';
  522. COMMIT TRANSACTION;
  523. PRINT 'Hangfire SQL objects installed';