I have a SQL Server database designed like this :
TableParameter
Id (int, PRIMARY KEY, IDENTITY)
Name1 (string)
Name2 (string, can be null)
Name3 (string, can be null)
Name4 (string, can be null)
TableValue
Iteration (int)
IdTableParameter (int, FOREIGN KEY)
Type (string)
Value (decimal)
So, as you've just understood, TableValue
is linked to TableParameter
.
TableParameter
is like a multidimensionnal dictionary.
TableParameter
is supposed to have a lot of rows (more than 300,000 rows)
From my c# client program, I have to fill this database after each Compute()
function :
for (int iteration = 0; iteration < 5000; iteration++)
{
Compute();
FillResultsInDatabase();
}
In FillResultsInDatabase()
method, I have to :
- Check if the label of my parameter already exists in
TableParameter
. If it doesn't exist, i have to insert a new one. - I have to insert the value in the
TableValue
Step 1 takes a long time ! I load all the table TableParameter
in a IEnumerable property and then, for each parameter I make a
.FirstOfDefault( x => x.Name1 == item.Name1 &&
x.Name2 == item.Name2 &&
x.Name3 == item.Name3 &&
x.Name4 == item.Name4 );
in order to detect if it already exists (and after to get the id).
Performance are very bad like this !
I've tried to make selection with WHERE
word in order to avoid loading every row of TableParameter
but performance are worse !
How can I improve the performance of step 1 ?
For Step 2, performance are still bad with classic INSERT
. I am going to try SqlBulkCopy
.
How can I improve the performance of step 2 ?
EDITED
I've tried with Store Procedure :
CREATE PROCEDURE GetIdParameter
@Id int OUTPUT,
@Name1 nvarchar(50) = null,
@Name2 nvarchar(50) = null,
@Name3 nvarchar(50) = null
AS
SELECT TOP 1 @Id = Id FROM TableParameter
WHERE
TableParameter.Name1 = @Name1
AND
(@Name2 IS NULL OR TableParameter.Name2= @Name2)
AND
(@Name3 IS NULL OR TableParameter.Name3 = @Name3)
GO
CREATE PROCEDURE CreateValue
@Iteration int,
@Type nvarchar(50),
@Value decimal(32, 18),
@Name1 nvarchar(50) = null,
@Name2 nvarchar(50) = null,
@Name3 nvarchar(50) = null
AS
DECLARE @IdParameter int
EXEC GetIdParameter @IdParameter OUTPUT,
@Name1, @Name2, @Name3
IF @IdParameter IS NULL
BEGIN
INSERT TablePArameter (Name1, Name2, Name3)
VALUES
(@Name1, @Name2, @Name3)
SELECT @IdParameter= SCOPE_IDENTITY()
END
INSERT TableValue (Iteration, IdParamter, Type, Value)
VALUES
(@Iteration, @IdParameter, @Type, @Value)
GO
I still have the same performance... :-( (not acceptable)