views:

289

answers:

0

I was reading other post related to a problem I'm facing (http://stackoverflow.com/questions/1477690/what-is-the-benefit-of-having-varbinary-field-in-a-separate-1-1-table) looking for an aswer but I cant find one since a have a different scenario.

I've read splitting varbinary(max) data into another table would no get performance improvements but... what happens if I have triggers on my tables?

I'm having serious performance problems updating a table with a varbinary(max). This table has also other columns such as an identity (PK) and a status column. Updates on the not-varbinary columns take more time than I expect.

This table has a trigger which checks for any change on the status column and executes some code if the status changes from one value to another specific.

In order to get the changes, the trigger first joins the inserted and deleted columns, if the status hasn´t changed to the desired value, it just finishes.

Now, my point is... is it right if I assume that every time I update a bunch of records of this table SQL Server gets ALL the data from the table, including the varbinary(max) data (which in an average it has 15K per record) just to be able to check if a tinyint column has changed? My guess is since MSSQL doesn't know what's the code in the trigger, it will get all the data.

Does this reasoning make sense? Is this a situation where splitting data into 2 tables makes the difference? This is SQL 2005.

New! Here is the part of the trigger code where it checks for changes in status:

insert into @deleted ( IdTLogDetail )
select del.IdTLogDetail
  from inserted     ins
 Inner Join deleted del
    with (rowlock) on ins.IdTLogDetail = del.IdTLogDetail
 where ins.IdTLogDetailStatus = @StatusDetailEliminado 

select @liRegDeleted = @@rowcount

insert into @inserted ( IdTLogDetail )
select ins.IdTLogDetail
  from inserted     ins
 Inner Join deleted del
    with (rowlock) on ins.IdTLogDetail = del.IdTLogDetail
 where del.IdTLogDetailStatus = @StatusDetailEliminado and ins.IdTLogDetailStatus<>@StatusDetailDepurando


select @liRegInserted = @@rowcount

if @liRegDeleted  = 0 and @liRegInserted = 0
 goto salir

and this is the ddl for the table:

CREATE TABLE [dbo].[SGVdTLogDetail](
    [IdTLogDetail] [bigint] IDENTITY(1,1) NOT NULL,
    [IdTLogHeader] [int] NOT NULL,
    [HashCode] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [TxNumber] [int] NOT NULL,
    [TxCode] [varchar](4) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [TxData] [varbinary](max) NOT NULL,
    [StreamPosition] [bigint] NOT NULL,
    [SendTs] [datetime] NOT NULL,
    [ReceivedTs] [datetime] NOT NULL,
    [ProcessedTs] [datetime] NULL,
    [IdSGVdProcessInfo] [bigint] NULL,
    [IdTLogDetailStatus] [tinyint] NOT NULL,
    [DepurationProcessId] [uniqueidentifier] NULL,
 CONSTRAINT [PK_TLogDetail] PRIMARY KEY CLUSTERED 
(
    [IdTLogDetail] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[SGVdTLogDetail]  WITH NOCHECK ADD  CONSTRAINT [FK_SGVdTLogDetail_SGVdProcessInfo] FOREIGN KEY([IdSGVdProcessInfo])
REFERENCES [dbo].[SGVdProcessInfo] ([IdSGVdProcessInfo])
GO
ALTER TABLE [dbo].[SGVdTLogDetail] CHECK CONSTRAINT [FK_SGVdTLogDetail_SGVdProcessInfo]
GO
ALTER TABLE [dbo].[SGVdTLogDetail]  WITH CHECK ADD  CONSTRAINT [FK_SGVdTLogDetail_SGVdTLogHeader] FOREIGN KEY([IdTLogHeader])
REFERENCES [dbo].[SGVdTLogHeader] ([IdTLogHeader])
GO
ALTER TABLE [dbo].[SGVdTLogDetail] CHECK CONSTRAINT [FK_SGVdTLogDetail_SGVdTLogHeader]
GO
ALTER TABLE [dbo].[SGVdTLogDetail]  WITH CHECK ADD  CONSTRAINT [FK_SGVdTLogDetail_SGVsTLogDetailStatus] FOREIGN KEY([IdTLogDetailStatus])
REFERENCES [dbo].[SGVsTLogDetailStatus] ([IdTLogDetailStatus])
GO
ALTER TABLE [dbo].[SGVdTLogDetail] CHECK CONSTRAINT [FK_SGVdTLogDetail_SGVsTLogDetailStatus]

I'm looking forward to hearing your answers...

Diego