Home All Groups Group Topic Archive Search About

Exclude query from transaction

Author
7 Jul 2005 7:06 PM
MedioYMedio
I'm experimenting performance problems in a process that manage 1M rows and
updates several times some columns.

The issue is that the whole process is under a transaction (must be) but
there are some queries within the transaction that i don't need to keep
logged, meaning that if the transaction fails, it isn't importante the state
of those queries.

As i'm trying to improve performance, my question is:

Can i exclude a query from a transaction on purpose?

Example:
begin transaction
  exec sp_logged_one
  exec sp_logged_one

  exec sp_not_logged_one    -- this sp should not be included in the
transaction
  exec sp_not_logged_two    -- this sp should not be included in the
transaction

  exec sp_logged_nine
  exec sp_logged_ten
commit transaction

if i exclude the meaningless sps from the transaction i'm sure i will
improve the performance.

(i've read some "solutions" that opens another process to avoid transaction
inclusion buy i would prefer a more "elegant" solution like a hint, etc.)

Regards,

Author
7 Jul 2005 10:50 PM
ML
Is there no possibility of executing those procedures *before* you begin the
transaction?

It seems this procedure of yours is a busy one. It does many things. Is
breaking them up into several transactions also not possible?


ML
Author
8 Jul 2005 4:38 PM
MedioYMedio
This is the catch. I can't rearrange the execution order and i can't either
break it into smaller transaction since i need the transaction to include
both first and last blocks of updates...

Regards,

Show quote
"ML" wrote:

> Is there no possibility of executing those procedures *before* you begin the
> transaction?
>
> It seems this procedure of yours is a busy one. It does many things. Is
> breaking them up into several transactions also not possible?
>
>
> ML
Author
8 Jul 2005 2:03 AM
Brian Selzer
My suggestion is to combine the SPs into a single one.  Use optimistic
concurrency with roversioning if you can (If you have a rowversion column on
each table, you can simply store the maximum rowversion for the affected
rows in each table used to calculate the results and any table that is the
target of the update to guarantee consistency.)  Perform all reads during
the calculation phase using WITH(NOLOCK) and cache the results in table
variables.  Once all of the time-consuming actions have been completed,
you're ready to start updating, so start a transaction, re-read the maximum
rowversion for each set of affected rows from each table used to calculate
the results WITH(REPEATABLEREAD) to determine whether some other user
changed a row and to ensure that no other user can change the values once
you start updating.  Re-read the maximum rowversion for each  from the rows
in the tables that you're going to update WITH(UPDLOCK) to ensure that no
other user can change one of the rows that you're going to update.  If none
of the rowversions have changed, then that means that the calculations are
correct and you can perform the updates.  If on the other hand, any
rowversion is different, roll back the transaction to release the locks and
start over.  While it is possible for a collision to occur, their frequency
is usually low, so the overall performance hit is negligible.  The benefit
of this approach is that at the end, only set-based operations are performed
to update base tables--one for each type of update for each table, DELETE,
UPDATE, INSERT, in that order.  This minimizes the interval during which the
rows are locked, which maximizes concurrency.  It also means that triggers
only fire once.  You may find that even with a collision, this approach
operates much faster than holding the locks throughout all of the
subordinate procedures.

If you don't have rowversion columns on your tables and you can't add one,
your only option is to read out the affected rows into table variables,
perform the calculations using the table variables as the source (DON'T
UPDATE THEM!)  Perform the calculations as above caching the results in
separate set of results table variables.  When you're ready to update
compare the rows in the table variables that were read out to perform the
calculations and the rows that are expected to be updated with the rows in
the base tables to find out if someone changed a row while you were
calculating.  Again REPEATABLEREAD, and UPDLOCK as above.

Show quote
"MedioYMedio" <MedioYMe***@discussions.microsoft.com> wrote in message
news:4D3565A7-E117-4849-8EC6-843180FD43C0@microsoft.com...
> I'm experimenting performance problems in a process that manage 1M rows
and
> updates several times some columns.
>
> The issue is that the whole process is under a transaction (must be) but
> there are some queries within the transaction that i don't need to keep
> logged, meaning that if the transaction fails, it isn't importante the
state
> of those queries.
>
> As i'm trying to improve performance, my question is:
>
> Can i exclude a query from a transaction on purpose?
>
> Example:
> begin transaction
>   exec sp_logged_one
>   exec sp_logged_one
>
>   exec sp_not_logged_one    -- this sp should not be included in the
> transaction
>   exec sp_not_logged_two    -- this sp should not be included in the
> transaction
>
>   exec sp_logged_nine
>   exec sp_logged_ten
> commit transaction
>
> if i exclude the meaningless sps from the transaction i'm sure i will
> improve the performance.
>
> (i've read some "solutions" that opens another process to avoid
transaction
> inclusion buy i would prefer a more "elegant" solution like a hint, etc.)
>
> Regards,
Author
8 Jul 2005 4:41 PM
MedioYMedio
First of all, i appreciate your quick and complete response.
I'm still trying to understand your solution, but with a first sight i can
tell that the overhead produced by this rearrangement won't be acceptable.

The concurrency is not a problem, this process will rule the server while
executing. The problem is the atomicy of the transaction and, of course,
performance.

Regards,

Show quote
"Brian Selzer" wrote:

> My suggestion is to combine the SPs into a single one.  Use optimistic
> concurrency with roversioning if you can (If you have a rowversion column on
> each table, you can simply store the maximum rowversion for the affected
> rows in each table used to calculate the results and any table that is the
> target of the update to guarantee consistency.)  Perform all reads during
> the calculation phase using WITH(NOLOCK) and cache the results in table
> variables.  Once all of the time-consuming actions have been completed,
> you're ready to start updating, so start a transaction, re-read the maximum
> rowversion for each set of affected rows from each table used to calculate
> the results WITH(REPEATABLEREAD) to determine whether some other user
> changed a row and to ensure that no other user can change the values once
> you start updating.  Re-read the maximum rowversion for each  from the rows
> in the tables that you're going to update WITH(UPDLOCK) to ensure that no
> other user can change one of the rows that you're going to update.  If none
> of the rowversions have changed, then that means that the calculations are
> correct and you can perform the updates.  If on the other hand, any
> rowversion is different, roll back the transaction to release the locks and
> start over.  While it is possible for a collision to occur, their frequency
> is usually low, so the overall performance hit is negligible.  The benefit
> of this approach is that at the end, only set-based operations are performed
> to update base tables--one for each type of update for each table, DELETE,
> UPDATE, INSERT, in that order.  This minimizes the interval during which the
> rows are locked, which maximizes concurrency.  It also means that triggers
> only fire once.  You may find that even with a collision, this approach
> operates much faster than holding the locks throughout all of the
> subordinate procedures.
>
> If you don't have rowversion columns on your tables and you can't add one,
> your only option is to read out the affected rows into table variables,
> perform the calculations using the table variables as the source (DON'T
> UPDATE THEM!)  Perform the calculations as above caching the results in
> separate set of results table variables.  When you're ready to update
> compare the rows in the table variables that were read out to perform the
> calculations and the rows that are expected to be updated with the rows in
> the base tables to find out if someone changed a row while you were
> calculating.  Again REPEATABLEREAD, and UPDLOCK as above.
>
> "MedioYMedio" <MedioYMe***@discussions.microsoft.com> wrote in message
> news:4D3565A7-E117-4849-8EC6-843180FD43C0@microsoft.com...
> > I'm experimenting performance problems in a process that manage 1M rows
> and
> > updates several times some columns.
> >
> > The issue is that the whole process is under a transaction (must be) but
> > there are some queries within the transaction that i don't need to keep
> > logged, meaning that if the transaction fails, it isn't importante the
> state
> > of those queries.
> >
> > As i'm trying to improve performance, my question is:
> >
> > Can i exclude a query from a transaction on purpose?
> >
> > Example:
> > begin transaction
> >   exec sp_logged_one
> >   exec sp_logged_one
> >
> >   exec sp_not_logged_one    -- this sp should not be included in the
> > transaction
> >   exec sp_not_logged_two    -- this sp should not be included in the
> > transaction
> >
> >   exec sp_logged_nine
> >   exec sp_logged_ten
> > commit transaction
> >
> > if i exclude the meaningless sps from the transaction i'm sure i will
> > improve the performance.
> >
> > (i've read some "solutions" that opens another process to avoid
> transaction
> > inclusion buy i would prefer a more "elegant" solution like a hint, etc.)
> >
> > Regards,
>
>
>
Author
9 Jul 2005 1:04 AM
Brian Selzer
You could find that the overhead might be offset by the faster reads and
calculations.  You won't know until you try.

I tuned a system that was designed to process 14,000 transactions per hour
so that it could process over 200,000 transactions per hour.  Optimistic
concurrency with rowversioning.  Close attention to execution plans:
eliminating reads and writes within cursors,  eliminating correlated
subqueries by flattening them out into joins by using a set of cursors.
Waiting 'til the last possible moment to start a transaction--sometimes
jumping through hoops to make it possible.  Each of these bought me
measurable performance improvement.

Show quote
"MedioYMedio" <MedioYMe***@discussions.microsoft.com> wrote in message
news:2985F2A2-AED7-4C54-ABDF-4894C01A9E42@microsoft.com...
> First of all, i appreciate your quick and complete response.
> I'm still trying to understand your solution, but with a first sight i can
> tell that the overhead produced by this rearrangement won't be acceptable.
>
> The concurrency is not a problem, this process will rule the server while
> executing. The problem is the atomicy of the transaction and, of course,
> performance.
>
> Regards,
>
> "Brian Selzer" wrote:
>
> > My suggestion is to combine the SPs into a single one.  Use optimistic
> > concurrency with roversioning if you can (If you have a rowversion
column on
> > each table, you can simply store the maximum rowversion for the affected
> > rows in each table used to calculate the results and any table that is
the
> > target of the update to guarantee consistency.)  Perform all reads
during
> > the calculation phase using WITH(NOLOCK) and cache the results in table
> > variables.  Once all of the time-consuming actions have been completed,
> > you're ready to start updating, so start a transaction, re-read the
maximum
> > rowversion for each set of affected rows from each table used to
calculate
> > the results WITH(REPEATABLEREAD) to determine whether some other user
> > changed a row and to ensure that no other user can change the values
once
> > you start updating.  Re-read the maximum rowversion for each  from the
rows
> > in the tables that you're going to update WITH(UPDLOCK) to ensure that
no
> > other user can change one of the rows that you're going to update.  If
none
> > of the rowversions have changed, then that means that the calculations
are
> > correct and you can perform the updates.  If on the other hand, any
> > rowversion is different, roll back the transaction to release the locks
and
> > start over.  While it is possible for a collision to occur, their
frequency
> > is usually low, so the overall performance hit is negligible.  The
benefit
> > of this approach is that at the end, only set-based operations are
performed
> > to update base tables--one for each type of update for each table,
DELETE,
> > UPDATE, INSERT, in that order.  This minimizes the interval during which
the
> > rows are locked, which maximizes concurrency.  It also means that
triggers
> > only fire once.  You may find that even with a collision, this approach
> > operates much faster than holding the locks throughout all of the
> > subordinate procedures.
> >
> > If you don't have rowversion columns on your tables and you can't add
one,
> > your only option is to read out the affected rows into table variables,
> > perform the calculations using the table variables as the source (DON'T
> > UPDATE THEM!)  Perform the calculations as above caching the results in
> > separate set of results table variables.  When you're ready to update
> > compare the rows in the table variables that were read out to perform
the
> > calculations and the rows that are expected to be updated with the rows
in
> > the base tables to find out if someone changed a row while you were
> > calculating.  Again REPEATABLEREAD, and UPDLOCK as above.
> >
> > "MedioYMedio" <MedioYMe***@discussions.microsoft.com> wrote in message
> > news:4D3565A7-E117-4849-8EC6-843180FD43C0@microsoft.com...
> > > I'm experimenting performance problems in a process that manage 1M
rows
> > and
> > > updates several times some columns.
> > >
> > > The issue is that the whole process is under a transaction (must be)
but
> > > there are some queries within the transaction that i don't need to
keep
> > > logged, meaning that if the transaction fails, it isn't importante the
> > state
> > > of those queries.
> > >
> > > As i'm trying to improve performance, my question is:
> > >
> > > Can i exclude a query from a transaction on purpose?
> > >
> > > Example:
> > > begin transaction
> > >   exec sp_logged_one
> > >   exec sp_logged_one
> > >
> > >   exec sp_not_logged_one    -- this sp should not be included in the
> > > transaction
> > >   exec sp_not_logged_two    -- this sp should not be included in the
> > > transaction
> > >
> > >   exec sp_logged_nine
> > >   exec sp_logged_ten
> > > commit transaction
> > >
> > > if i exclude the meaningless sps from the transaction i'm sure i will
> > > improve the performance.
> > >
> > > (i've read some "solutions" that opens another process to avoid
> > transaction
> > > inclusion buy i would prefer a more "elegant" solution like a hint,
etc.)
> > >
> > > Regards,
> >
> >
> >
Author
9 Jul 2005 2:18 AM
MedioYMedio
Perfect!, i'll try your suggestions.

I'm still amazed that there isn't a way to explicitly exclude a query
execution within a transaction. Seemed to me that it was a trivial (?) issue.

Thanks again,
Regards,

Show quote
"Brian Selzer" wrote:

> You could find that the overhead might be offset by the faster reads and
> calculations.  You won't know until you try.
>
> I tuned a system that was designed to process 14,000 transactions per hour
> so that it could process over 200,000 transactions per hour.  Optimistic
> concurrency with rowversioning.  Close attention to execution plans:
> eliminating reads and writes within cursors,  eliminating correlated
> subqueries by flattening them out into joins by using a set of cursors.
> Waiting 'til the last possible moment to start a transaction--sometimes
> jumping through hoops to make it possible.  Each of these bought me
> measurable performance improvement.
>
> "MedioYMedio" <MedioYMe***@discussions.microsoft.com> wrote in message
> news:2985F2A2-AED7-4C54-ABDF-4894C01A9E42@microsoft.com...
> > First of all, i appreciate your quick and complete response.
> > I'm still trying to understand your solution, but with a first sight i can
> > tell that the overhead produced by this rearrangement won't be acceptable.
> >
> > The concurrency is not a problem, this process will rule the server while
> > executing. The problem is the atomicy of the transaction and, of course,
> > performance.
> >
> > Regards,
> >
> > "Brian Selzer" wrote:
> >
> > > My suggestion is to combine the SPs into a single one.  Use optimistic
> > > concurrency with roversioning if you can (If you have a rowversion
> column on
> > > each table, you can simply store the maximum rowversion for the affected
> > > rows in each table used to calculate the results and any table that is
> the
> > > target of the update to guarantee consistency.)  Perform all reads
> during
> > > the calculation phase using WITH(NOLOCK) and cache the results in table
> > > variables.  Once all of the time-consuming actions have been completed,
> > > you're ready to start updating, so start a transaction, re-read the
> maximum
> > > rowversion for each set of affected rows from each table used to
> calculate
> > > the results WITH(REPEATABLEREAD) to determine whether some other user
> > > changed a row and to ensure that no other user can change the values
> once
> > > you start updating.  Re-read the maximum rowversion for each  from the
> rows
> > > in the tables that you're going to update WITH(UPDLOCK) to ensure that
> no
> > > other user can change one of the rows that you're going to update.  If
> none
> > > of the rowversions have changed, then that means that the calculations
> are
> > > correct and you can perform the updates.  If on the other hand, any
> > > rowversion is different, roll back the transaction to release the locks
> and
> > > start over.  While it is possible for a collision to occur, their
> frequency
> > > is usually low, so the overall performance hit is negligible.  The
> benefit
> > > of this approach is that at the end, only set-based operations are
> performed
> > > to update base tables--one for each type of update for each table,
> DELETE,
> > > UPDATE, INSERT, in that order.  This minimizes the interval during which
> the
> > > rows are locked, which maximizes concurrency.  It also means that
> triggers
> > > only fire once.  You may find that even with a collision, this approach
> > > operates much faster than holding the locks throughout all of the
> > > subordinate procedures.
> > >
> > > If you don't have rowversion columns on your tables and you can't add
> one,
> > > your only option is to read out the affected rows into table variables,
> > > perform the calculations using the table variables as the source (DON'T
> > > UPDATE THEM!)  Perform the calculations as above caching the results in
> > > separate set of results table variables.  When you're ready to update
> > > compare the rows in the table variables that were read out to perform
> the
> > > calculations and the rows that are expected to be updated with the rows
> in
> > > the base tables to find out if someone changed a row while you were
> > > calculating.  Again REPEATABLEREAD, and UPDLOCK as above.
> > >
> > > "MedioYMedio" <MedioYMe***@discussions.microsoft.com> wrote in message
> > > news:4D3565A7-E117-4849-8EC6-843180FD43C0@microsoft.com...
> > > > I'm experimenting performance problems in a process that manage 1M
> rows
> > > and
> > > > updates several times some columns.
> > > >
> > > > The issue is that the whole process is under a transaction (must be)
> but
> > > > there are some queries within the transaction that i don't need to
> keep
> > > > logged, meaning that if the transaction fails, it isn't importante the
> > > state
> > > > of those queries.
> > > >
> > > > As i'm trying to improve performance, my question is:
> > > >
> > > > Can i exclude a query from a transaction on purpose?
> > > >
> > > > Example:
> > > > begin transaction
> > > >   exec sp_logged_one
> > > >   exec sp_logged_one
> > > >
> > > >   exec sp_not_logged_one    -- this sp should not be included in the
> > > > transaction
> > > >   exec sp_not_logged_two    -- this sp should not be included in the
> > > > transaction
> > > >
> > > >   exec sp_logged_nine
> > > >   exec sp_logged_ten
> > > > commit transaction
> > > >
> > > > if i exclude the meaningless sps from the transaction i'm sure i will
> > > > improve the performance.
> > > >
> > > > (i've read some "solutions" that opens another process to avoid
> > > transaction
> > > > inclusion buy i would prefer a more "elegant" solution like a hint,
> etc.)
> > > >
> > > > Regards,
> > >
> > >
> > >
>
>
>

AddThis Social Bookmark Button