Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
lappin
Posting Yak Master
182 Posts |
Posted - 2011-05-18 : 12:03:06
|
| Hi, I have a merge statement which runs OK for INSERT and UPDATE, but I want to add DELETE - but this causes the proc to hang. My proc receives a single day as a date parameter and passes it into a UDF which it uses as a source table. There is a clustered index on the date field DT in the target table with has over 10 million rows.Here is simplified version:Merge into dbo.MyTable as TargetUsing ( Select distinct ID ,DT ,value,[dept],dept_name,[Cost],Location ,range ,'1' as Type from ( SELECT f.ID ,DT,value,[dept],dept_name,[Cost],Location ,range , Type FROM [dbo].[MyFunction] ( @ThisDate) f ) Used ) As SourceON Target.ID=Source.IDand Target.DT=Source.DTand Target.[dept]=Source.[dept]and Target.Location=Source.Locationand Target.range=Source.rangewhen matched then update set Target.[value]=Source.[value],Target.[dept_name]=Source.[dept_name],Target.[Cost]=Source.[Cost],Target.Type='1'when not matched theninsert ([ID] ,[DT] ,[value] ,[dept] ,[dept_name] ,[Cost] ,[Location] ,[range] ,[Type]) values (Source.[ID] , Source.[DT] , Source.[value] , Source.[dept] , Source.[dept_name] , Source.[Cost] , Source.[Location] , Source.[range] , '1') --these last lines make the procedure hang when not matched by source AND convert(date,target.DT) = @ThisDate AND Target.Type='1' THEN DELETE; |
|
|
X002548
Not Just a Number
15586 Posts |
|
|
X002548
Not Just a Number
15586 Posts |
Posted - 2011-05-18 : 14:10:44
|
wow....from bol with some minor changes..maybe this example will helpCREATE TABLE #Target(EmployeeID int, EmployeeName varchar(10), CONSTRAINT Target_PK PRIMARY KEY(EmployeeID));CREATE TABLE #Source(EmployeeID int, EmployeeName varchar(10), CONSTRAINT Source_PK PRIMARY KEY(EmployeeID));GOINSERT #Target(EmployeeID, EmployeeName) VALUES(100, 'Mary'); --DeleteINSERT #Target(EmployeeID, EmployeeName) VALUES(101, 'Sara'); --SameINSERT #Target(EmployeeID, EmployeeName) VALUES(102, 'Stefano'); --ChangeGOINSERT #Source(EmployeeID, EmployeeName) VALUES(101, 'Sara'); --SameINSERT #Source(EmployeeID, EmployeeName) Values(102, 'Stilleto'); --ChangeINSERT #Source(EmployeeID, EmployeeName) Values(103, 'Bob'); --New INSERT #Source(EmployeeID, EmployeeName) Values(104, 'Steve'); --NewGOSELECT * FROM #TargetSELECT * FROM #SourceGO BEGIN TRAN;MERGE #Target AS TUSING #Source AS SON (T.EmployeeID = S.EmployeeID) WHEN NOT MATCHED BY TARGET THEN INSERT(EmployeeID, EmployeeName) VALUES(S.EmployeeID, S.EmployeeName)WHEN MATCHED THEN UPDATE SET T.EmployeeName = S.EmployeeNameWHEN NOT MATCHED BY SOURCE THEN DELETE OUTPUT $action, inserted.*, deleted.*;SELECT * FROM #TargetSELECT * FROM #SourceROLLBACK TRAN;GOSELECT * FROM #TargetSELECT * FROM #SourceGODROP TABLE #Target, #SourceGO Brett8-)Hint: Want your questions answered fast? Follow the direction in this linkhttp://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspxWant to help yourself?http://msdn.microsoft.com/en-us/library/ms130214.aspxhttp://weblogs.sqlteam.com/brettk/http://brettkaiser.blogspot.com/ |
 |
|
|
lappin
Posting Yak Master
182 Posts |
Posted - 2011-05-19 : 04:22:45
|
| Without the delete it does run much faster. The UDF performs some calculations / joins / lookups on the source data and applies these to the target. But it is for a subset of the target data so I cannot just use: WHEN NOT MATCHED BY SOURCE THEN DELETE, because it wipes every other run from the target table. For an example date the UDF returns around 400 rows and the UPDATE / INSERT runs in a few seconds, but adding the DELETE seems to be causing a table scan, even though there is a clustered index on the date field. |
 |
|
|
lappin
Posting Yak Master
182 Posts |
Posted - 2011-05-19 : 06:57:44
|
| My work around was: create a new column "modifieddate" and populate it inside INSERT and UPDATE. Then inside proc if no errors find rows which match the subset criteria but the modifieddate <> today, and delete these rows. This now runs in a few seconds againIf someone knows a better way let me know. |
 |
|
|
X002548
Not Just a Number
15586 Posts |
|
|
lappin
Posting Yak Master
182 Posts |
Posted - 2011-05-20 : 07:21:15
|
| The UDF does a lot of calculations, joins etc. The whole process is part of a data warehouse where data is taken from normalised tables into a large de-normalised table to give fast access to data. As mentioned earlier the merge is very fast (in my case when used only for INSERT and update). My work around includes DELETE functionality outside MERGE. |
 |
|
|
|
|
|
|
|