I'll answer here as well. It has to do with the internals of how IDENTITY
and SEQUENCE
work.
With IDENTITY
, SQL Server pre-caches values into memory so that they are readily available. See Martin Smith's answer for the details. As values are used, a background process generates more values. As you can imagine this pool can run out pretty quickly, leaving the application at the mercy of the background process that is generating the values.
With SEQUENCE
, SQL Server allows you to define how large the cache should be. While SQL Server doesn't actually keep the values in the cache, it only keeps the current value and the top end value, this will greatly reduce the amount of IO that is needed to create values.
Don't set the cache too high, as this will reduce the number of numbers which can be used: if SQL Server were to crash, any values specified in the current cache range which weren't used would be lost.
As for row insertion, just specify a default value for the column, like so:
DEFAULT (NEXT VALUE FOR Audit.EventCounter),
What is up with FROM part JOIN model ON 1=1
? This the same as FROM part, model
, which is a cartesian join and will result in a very large number of rows. Is that join supposed to be like that?
You will likely help us help you if you provide details about the tables involved. Please "script" the definition of the tables, along with any indexes defined on those tables.
This sounds like a classic case of parameter sniffing resulting in good plan/bad plan choices for various scenarios in your data.
You may be able to get more reliable performance by making SQL Server cache different plans for different scenarios by using sp_executesql
, as in the following example:
CREATE PROCEDURE [dbo].[create_grid_materials2]
(
@partlistid bigint
, @pid bigint
, @masterid bigint
)
AS
BEGIN
begin
DECLARE @cmd NVARCHAR(MAX);
SET @cmd = '
INSERT INTO material (partid, personid, modelID)
SELECT
partid = part.id
, personid = @pid
, modelid = model.id
FROM part
INNER JOIN model ON 1=1
WHERE (
model.masterid = ' + CONVERT(NVARCHAR(50), @masterid) + '
AND model.modelSetID IS NULL
AND part.partlistid = ' + CONVERT(NVARCHAR(50), @partlistid) + '
AND (
part.partType = 100
or part.partType=120
or part.partType = 130
)
)
AND NOT EXISTS (
SELECT 1
FROM material AS a1
WHERE a1.partid = part.id
AND a1.personid=@pid
AND a1.modelid=model.id
)';
DECLARE @Params VARCHAR(200);
SET @Params = '@pid INT';
EXEC sys.sp_executesql @cmd
, @Params
, @pid = @pid;
end
End
The above code will cause a new plan to be generated for each combination of @partlistid
, and @masterid
.
The presumption here is some combinations of those two variables lead to a very small number of rows, whereas some combinations lead to a very large number of rows.
Forcing a plan for each combination allows SQL Server to generate more efficient plans for each. I've explicitly not included @pid
since you probably want to try it with a fairly small number of combinations first; adding a third variable to the mix will make for an exponentially larger number of possible plans.
Best Answer
Assign it as the default property for the column
Future readers, a Sequence can have a gap if the service stops unexpectedly, the value of the entities in CACHE can be lost. Here, they are specifying
no cache
to mitigate that with the tradeoff of slower performance for the sequence object.CREATE SEQUENCE reference