Showing posts with label below. Show all posts
Showing posts with label below. Show all posts

Friday, March 30, 2012

Performance Tuning UPDATE Statement

Below is a simple UPDATE that I have to perform on a table that has
about 2.5 million rows (about 4 million in production) This query
runs for an enourmous amount of time (over 1 hour). Both the
ChangerRoleID and the ChangerID are indexed (not unique). Is there
any way to performance tune this?

Controlling the physical drive of the log file isn't possible at our
client sites (we don't have control) and the recovery model needs to
be set to "Full".

UPDATE CLIENTSHISTORY SET ChangerRoleID = ChangerID WHERE
ChangerRoleID IS NULL

Any Help would be greatly appreciated!On 4 Aug 2004 08:27:50 -0700, MAS wrote:

>Below is a simple UPDATE that I have to perform on a table that has
>about 2.5 million rows (about 4 million in production) This query
>runs for an enourmous amount of time (over 1 hour). Both the
>ChangerRoleID and the ChangerID are indexed (not unique). Is there
>any way to performance tune this?
>Controlling the physical drive of the log file isn't possible at our
>client sites (we don't have control) and the recovery model needs to
>be set to "Full".
>UPDATE CLIENTSHISTORY SET ChangerRoleID = ChangerID WHERE
>ChangerRoleID IS NULL
>Any Help would be greatly appreciated!

Hi MAS,

If you remove the non-unique index on ChangerRoleID before doing the
update and recreate it afterwards, you'll probably save some time. The
index could have been useful if only a few of all rows match the IS NULL
condition, but with over aan hour execution time, I think there are so
many matches that a full table scan will be quicker. Removing the index
before doing the update saves SQL Server the extra work of constantly
having to update the index to keep it in sync with the data. Of course,
this might affect other queries that execute during the update and would
have benefited from this index. The index on ChangerID will neither be
used nor cause extra work for this update.

Check if there's a trigger that gets fired by the update. If you can
safely disable that trigger during the update process, do so. Same for
constraints: are there any CHECK or REFERENCES (foreign key) constraints
defined for ChangerRoleID? If so, disable constraint checking (again, only
if it is safe, i.e. you have to be sure that this update won't cause
violation of the constraint *and* that no other person accessing the
database during the time constraint checking is disabled will be able to
cause violations of the constraint).

You state that the recovery model needs to be full; from that I conclude
that you can't lock other users out of the database during the update. Can
you at least take measures to prevent other users from using (updating,
but preferably reading as well) the CLIENTSHISTORY table?

Best, Hugo
--

(Remove _NO_ and _SPAM_ to get my e-mail address)|||[posted and mailed, please reply in news]

MAS (mas32677@.hotmail.com) writes:
> Below is a simple UPDATE that I have to perform on a table that has
> about 2.5 million rows (about 4 million in production) This query
> runs for an enourmous amount of time (over 1 hour). Both the
> ChangerRoleID and the ChangerID are indexed (not unique). Is there
> any way to performance tune this?
> Controlling the physical drive of the log file isn't possible at our
> client sites (we don't have control) and the recovery model needs to
> be set to "Full".
> UPDATE CLIENTSHISTORY SET ChangerRoleID = ChangerID WHERE
> ChangerRoleID IS NULL
> Any Help would be greatly appreciated!

To add to what Hugo said, if that index on ChangerRoleID is clustered,
and many rows have a NULL value, then you are in for a problem.

It may help to do it batches:

DECLARE @.batch_size int, @.rowc int
SELECT @.batch_size = 50000
SELECT @.rowc = @.batch_size
SET ROWCOUNT @.batch_size
WHILE @.rowc = @.batch_size
BEGIN
UPDATE CLIENTSHISTORY SET ChangerRoleID = ChangerID
WHERE ChangerRoleID IS NULL
AND ChangerID IS NOT NULL
SELECT @.rowc = @.@.rowcount
END
SET ROWCOUNT 0

--
Erland Sommarskog, SQL Server MVP, esquel@.sommarskog.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techin.../2000/books.aspsql

Monday, March 26, 2012

performance question

Why does Query1 below have a Scan with 21 Logical Reads for 31 records
returned (a small percentage of Logicalreads), when Query 2 has no Scan,
only returns 6 records, and has 14 Logical reads. (a higher percentage)
In other words, the more data, the fewer Logical reads but no Scan. The less
data, higher reads but a scan. What gives?
SQL2K sp3a
TIA, ChrisR
what query? what data types are the columns?
2004 and 2005 Microsoft MVP C#
Robbe Morris
http://www.masterado.net
Earn $$$ money answering .NET Framework
messageboard posts at EggHeadCafe.com.
http://www.eggheadcafe.com/forums/merit.asp
"ChrisR" <noemail@.bla.com> wrote in message
news:OLWXZnMiFHA.3672@.TK2MSFTNGP10.phx.gbl...
> Why does Query1 below have a Scan with 21 Logical Reads for 31 records
> returned (a small percentage of Logicalreads), when Query 2 has no Scan,
> only returns 6 records, and has 14 Logical reads. (a higher percentage)
> In other words, the more data, the fewer Logical reads but no Scan. The
> less data, higher reads but a scan. What gives?
> SQL2K sp3a
> TIA, ChrisR
>
|||The scan on a clustered or nonclustered index at the leaf level is pretty
simple since it goes from leaf page to leaf page in order. It can read
relatively few pages to get a lot of rows that way. A seek has to traverse
the B-Tree from root to leaf level for each row returned. Depending on the
size of the index tree it can read a minimum of 2 pages per row seeked.
Andrew J. Kelly SQL MVP
"ChrisR" <noemail@.bla.com> wrote in message
news:OLWXZnMiFHA.3672@.TK2MSFTNGP10.phx.gbl...
> Why does Query1 below have a Scan with 21 Logical Reads for 31 records
> returned (a small percentage of Logicalreads), when Query 2 has no Scan,
> only returns 6 records, and has 14 Logical reads. (a higher percentage)
> In other words, the more data, the fewer Logical reads but no Scan. The
> less data, higher reads but a scan. What gives?
> SQL2K sp3a
> TIA, ChrisR
>

Friday, March 23, 2012

performance question

Why does Query1 below have a Scan with 21 Logical Reads for 31 records
returned (a small percentage of Logicalreads), when Query 2 has no Scan,
only returns 6 records, and has 14 Logical reads. (a higher percentage)
In other words, the more data, the fewer Logical reads but no Scan. The less
data, higher reads but a scan. What gives?
SQL2K sp3a
TIA, ChrisRwhat query? what data types are the columns?
--
2004 and 2005 Microsoft MVP C#
Robbe Morris
http://www.masterado.net
Earn $$$ money answering .NET Framework
messageboard posts at EggHeadCafe.com.
http://www.eggheadcafe.com/forums/merit.asp
"ChrisR" <noemail@.bla.com> wrote in message
news:OLWXZnMiFHA.3672@.TK2MSFTNGP10.phx.gbl...
> Why does Query1 below have a Scan with 21 Logical Reads for 31 records
> returned (a small percentage of Logicalreads), when Query 2 has no Scan,
> only returns 6 records, and has 14 Logical reads. (a higher percentage)
> In other words, the more data, the fewer Logical reads but no Scan. The
> less data, higher reads but a scan. What gives?
> SQL2K sp3a
> TIA, ChrisR
>|||The scan on a clustered or nonclustered index at the leaf level is pretty
simple since it goes from leaf page to leaf page in order. It can read
relatively few pages to get a lot of rows that way. A seek has to traverse
the B-Tree from root to leaf level for each row returned. Depending on the
size of the index tree it can read a minimum of 2 pages per row seeked.
--
Andrew J. Kelly SQL MVP
"ChrisR" <noemail@.bla.com> wrote in message
news:OLWXZnMiFHA.3672@.TK2MSFTNGP10.phx.gbl...
> Why does Query1 below have a Scan with 21 Logical Reads for 31 records
> returned (a small percentage of Logicalreads), when Query 2 has no Scan,
> only returns 6 records, and has 14 Logical reads. (a higher percentage)
> In other words, the more data, the fewer Logical reads but no Scan. The
> less data, higher reads but a scan. What gives?
> SQL2K sp3a
> TIA, ChrisR
>sql

performance question

Why does Query1 below have a Scan with 21 Logical Reads for 31 records
returned (a small percentage of Logicalreads), when Query 2 has no Scan,
only returns 6 records, and has 14 Logical reads. (a higher percentage)
In other words, the more data, the fewer Logical reads but no Scan. The less
data, higher reads but a scan. What gives?
SQL2K sp3a
TIA, ChrisRwhat query? what data types are the columns?
2004 and 2005 Microsoft MVP C#
Robbe Morris
http://www.masterado.net
Earn $$$ money answering .NET Framework
messageboard posts at EggHeadCafe.com.
http://www.eggheadcafe.com/forums/merit.asp
"ChrisR" <noemail@.bla.com> wrote in message
news:OLWXZnMiFHA.3672@.TK2MSFTNGP10.phx.gbl...
> Why does Query1 below have a Scan with 21 Logical Reads for 31 records
> returned (a small percentage of Logicalreads), when Query 2 has no Scan,
> only returns 6 records, and has 14 Logical reads. (a higher percentage)
> In other words, the more data, the fewer Logical reads but no Scan. The
> less data, higher reads but a scan. What gives?
> SQL2K sp3a
> TIA, ChrisR
>|||The scan on a clustered or nonclustered index at the leaf level is pretty
simple since it goes from leaf page to leaf page in order. It can read
relatively few pages to get a lot of rows that way. A seek has to traverse
the B-Tree from root to leaf level for each row returned. Depending on the
size of the index tree it can read a minimum of 2 pages per row seeked.
Andrew J. Kelly SQL MVP
"ChrisR" <noemail@.bla.com> wrote in message
news:OLWXZnMiFHA.3672@.TK2MSFTNGP10.phx.gbl...
> Why does Query1 below have a Scan with 21 Logical Reads for 31 records
> returned (a small percentage of Logicalreads), when Query 2 has no Scan,
> only returns 6 records, and has 14 Logical reads. (a higher percentage)
> In other words, the more data, the fewer Logical reads but no Scan. The
> less data, higher reads but a scan. What gives?
> SQL2K sp3a
> TIA, ChrisR
>

Tuesday, March 20, 2012

Performance Problem

The query below is taking 3-4 seconds to run under a light load, which
seems to be a bit lengthy for the indexes that are in place and the
amount of data that exists in the tables. I have outlined everything
below, including all table definitions, indexes, and row counts. Any
help at all will be appreciated. It seems no matter how I think an
index will function it never seems to work properly.
==
BEGIN QUERY
==
SELECT tblC.catDesc AS Category_Name,
COUNT(DISTINCT tblS.set_ID) AS Set_Count,
tblC.cat_ID AS Category_ID,
COUNT(tblI.Img_ID) AS Image_Count,
MIN(tblI.Img_ID) AS Image_ID,
(
SELECT COUNT(tblI2.Img_ID)
FROM tblImage tblI2
LEFT JOIN tblSets tblS2 ON tblS2.set_ID = tblI2.set_ID
WHERE tblI2.d_t > @.d_t
AND tblI2.cat_ID = tblC.cat_ID
AND tblI2.display_status = 1
) AS New_Image_Count,
(
SELECT COUNT(DISTINCT tblI3.set_ID)
FROM tblImage tblI3
LEFT JOIN tblSets tblS3 ON tblS3.set_ID = tblI3.set_ID
WHERE tblI3.d_t > @.d_t
AND tblI3.cat_ID = tblC.cat_ID
) AS New_Set_Count
FROM tblCategories tblC
LEFT JOIN tblImage tblI ON tblC.cat_ID = tblI.cat_ID
LEFT JOIN tblSets tblS ON tblI.set_ID = tblS.set_ID
WHERE tblC.skin_ID = @.skin_ID
GROUP BY tblC.cat_id, tblC.catDesc
==
END QUERY
==
==
tblImage (approx. 71000 rows)
==
Definition:
Img_ID (int, Not Null) - PK
set_ID (int, Null)
cat_ID (int, Null)
d_t (datetime, Null)
display_status (int, Null)
Indexes:
1. Img_ID (clustered)
2. cat_id DESC, display_status DESC, d_t DESC
3. d_t DESC, display_status DESC, set_ID, cat_ID
4. set_ID DESC
==
END tblImage
==
==
tblCategories (approx. 35 rows)
==
Definition:
cat_ID (int, Not Null) - PK
catDesc (varchar(25), Null)
skin_ID (int, Null)
Indexes:
1. cat_ID (clustered)
2. skin_ID, cat_ID
==
END tblCategories
==
==
tblSets (approx. 1500 rows)
==
Definition:
set_ID (int, Not Null) - PK
setName (varchar(25), Null)
setKeywords (varchar(500), Null)
Indexes:
1. set_ID (clustered)
==
END tblSets
==If I understand the query correctly, (If set_ID is unique in tblSets) Then
the following might work and should be faster since it doesn't have the
subquerys...
Select C.catDesc Category_Name,
Count(Distinct S.set_ID) Set_Count,
C.cat_ID Category_ID,
Count(tblI.Img_ID) Image_Count,
Min(I.Img_ID) Image_ID,
Sum(Case When I.d_t = @.d_t
And display_status = 1
Then 1 End) New_Image_Count,
Sum(Case When I.d_t = @.d_t
Then 1 End) New_Set_Count
From tblCategories C
Left Join tblImage I
On I.cat_ID = C.cat_ID
Left Join tblSets S
On S.set_ID = I.set_ID
Where C.skin_ID = @.skin_ID
Group By C.cat_id, C.catDesc
"iTISTIC@.gmail.com" wrote:

> The query below is taking 3-4 seconds to run under a light load, which
> seems to be a bit lengthy for the indexes that are in place and the
> amount of data that exists in the tables. I have outlined everything
> below, including all table definitions, indexes, and row counts. Any
> help at all will be appreciated. It seems no matter how I think an
> index will function it never seems to work properly.
> ==
> BEGIN QUERY
> ==
> SELECT tblC.catDesc AS Category_Name,
> COUNT(DISTINCT tblS.set_ID) AS Set_Count,
> tblC.cat_ID AS Category_ID,
> COUNT(tblI.Img_ID) AS Image_Count,
> MIN(tblI.Img_ID) AS Image_ID,
> (
> SELECT COUNT(tblI2.Img_ID)
> FROM tblImage tblI2
> LEFT JOIN tblSets tblS2 ON tblS2.set_ID = tblI2.set_ID
> WHERE tblI2.d_t > @.d_t
> AND tblI2.cat_ID = tblC.cat_ID
> AND tblI2.display_status = 1
> ) AS New_Image_Count,
> (
> SELECT COUNT(DISTINCT tblI3.set_ID)
> FROM tblImage tblI3
> LEFT JOIN tblSets tblS3 ON tblS3.set_ID = tblI3.set_ID
> WHERE tblI3.d_t > @.d_t
> AND tblI3.cat_ID = tblC.cat_ID
> ) AS New_Set_Count
> FROM tblCategories tblC
> LEFT JOIN tblImage tblI ON tblC.cat_ID = tblI.cat_ID
> LEFT JOIN tblSets tblS ON tblI.set_ID = tblS.set_ID
> WHERE tblC.skin_ID = @.skin_ID
> GROUP BY tblC.cat_id, tblC.catDesc
> ==
> END QUERY
> ==
>
> ==
> tblImage (approx. 71000 rows)
> ==
> Definition:
> Img_ID (int, Not Null) - PK
> set_ID (int, Null)
> cat_ID (int, Null)
> d_t (datetime, Null)
> display_status (int, Null)
> Indexes:
> 1. Img_ID (clustered)
> 2. cat_id DESC, display_status DESC, d_t DESC
> 3. d_t DESC, display_status DESC, set_ID, cat_ID
> 4. set_ID DESC
> ==
> END tblImage
> ==
> ==
> tblCategories (approx. 35 rows)
> ==
> Definition:
> cat_ID (int, Not Null) - PK
> catDesc (varchar(25), Null)
> skin_ID (int, Null)
> Indexes:
> 1. cat_ID (clustered)
> 2. skin_ID, cat_ID
> ==
> END tblCategories
> ==
>
> ==
> tblSets (approx. 1500 rows)
> ==
> Definition:
> set_ID (int, Not Null) - PK
> setName (varchar(25), Null)
> setKeywords (varchar(500), Null)
> Indexes:
> 1. set_ID (clustered)
> ==
> END tblSets
> ==
>

Monday, March 12, 2012

Performance Problem

Hi,
Below is the query that causing problems

SELECT T.Id AS TaskId
FROM dbo.Task T (NOLOCK)
INNER JOIN dbo.WorkOrder WO (NOLOCK) ON T.WorkOrderId = WO.Id
INNER JOIN dbo.StateMaster (NOLOCK) ON StateMaster.Id = WO.StatusId
WHERE WO.AssignedTo = 1020
AND StateMaster.IsInDashboard = 1

1. WorkOrder table is master table which consists of 155986 rows.
2. Task table is the child table refering to workorder (Id) which is
having 516060 rows.
3. Statemaster is the master table consists of about 500 rows.

Totally the condition WO.AssigendTo = 1020 satisfies 1042 rows with
the condition StateMaster.IsInDashboard = 1 the result set
will be minimized to 30 rows.

For executing the above query it is taking 1.7 sec.

This is the execution Plan i got when i run this query

|--Nested Loops(Inner Join, OUTER REFERENCES:([WO].[Id]) WITH
PREFETCH)
|--Nested Loops(Inner Join, OUTER REFERENCES:([WO].[StatusId]))
| |--Bookmark Lookup(BOOKMARK:([Bmk1001]),
OBJECT:([Viper63].[dbo].[WorkOrder] AS [WO]) WITH PREFETCH)
| | |--Index
Seek(OBJECT:([Viper63].[dbo].[WorkOrder].[IX_WorkOrder] AS [WO]),
SEEK:([WO].[AssignedTo]=[@.ResourceId]) ORDERED FORWARD)
| |--Clustered Index
Seek(OBJECT:([Viper63].[dbo].[StateMaster].[PK_StateMaster]),
SEEK:([StateMaster].[Id]=[WO].[StatusId]),

WHERE:(Convert([StateMaster].[IsInDashboard])=1) ORDERED FORWARD)
|--Index
Seek(OBJECT:([Viper63].[dbo].[Task].[IX_Task_WorkOrderId] AS [T]),
SEEK:([T].[WorkOrderId]=[WO].[Id]) ORDERED FORWARD)

I am not understanding why it is doing bookmark lookup on workorder
table when i joined StatusId column with Id column in statemaster table
and checking the condition Statemaster.IsinDashboard = 1.

These are the indexes we have on these tables.

1. In Task table "Id" is the primary Key and it is having
non-clustered index on workorderid
2. In Workorder table "Id" is the primary Key and it is having
non-clustered index on statusid
3. In Statemaster table "Id" is the primary Key

Could anyone help me out why the bookmark lookup is happening, it is
taking about 95% of the query time.

Regards,
ramnadh.

*** Sent via Developersdex http://www.developersdex.com ***This question has been answered in microsoft.public.sqlserver.programming.
Please don't post the same question independently to multiple groups.

--
Hope this helps.

Dan Guzman
SQL Server MVP

"ramnadh nalluri" <ramnadh_nalluri@.semanticspace.com> wrote in message
news:hLlGf.1$gp2.651@.news.uswest.net...
> Hi,
> Below is the query that causing problems
> SELECT T.Id AS TaskId
> FROM dbo.Task T (NOLOCK)
> INNER JOIN dbo.WorkOrder WO (NOLOCK) ON T.WorkOrderId = WO.Id
> INNER JOIN dbo.StateMaster (NOLOCK) ON StateMaster.Id = WO.StatusId
> WHERE WO.AssignedTo = 1020
> AND StateMaster.IsInDashboard = 1
> 1. WorkOrder table is master table which consists of 155986 rows.
> 2. Task table is the child table refering to workorder (Id) which is
> having 516060 rows.
> 3. Statemaster is the master table consists of about 500 rows.
> Totally the condition WO.AssigendTo = 1020 satisfies 1042 rows with
> the condition StateMaster.IsInDashboard = 1 the result set
> will be minimized to 30 rows.
> For executing the above query it is taking 1.7 sec.
>
> This is the execution Plan i got when i run this query
> |--Nested Loops(Inner Join, OUTER REFERENCES:([WO].[Id]) WITH
> PREFETCH)
> |--Nested Loops(Inner Join, OUTER REFERENCES:([WO].[StatusId]))
> | |--Bookmark Lookup(BOOKMARK:([Bmk1001]),
> OBJECT:([Viper63].[dbo].[WorkOrder] AS [WO]) WITH PREFETCH)
> | | |--Index
> Seek(OBJECT:([Viper63].[dbo].[WorkOrder].[IX_WorkOrder] AS [WO]),
> SEEK:([WO].[AssignedTo]=[@.ResourceId]) ORDERED FORWARD)
> | |--Clustered Index
> Seek(OBJECT:([Viper63].[dbo].[StateMaster].[PK_StateMaster]),
> SEEK:([StateMaster].[Id]=[WO].[StatusId]),
> WHERE:(Convert([StateMaster].[IsInDashboard])=1) ORDERED FORWARD)
> |--Index
> Seek(OBJECT:([Viper63].[dbo].[Task].[IX_Task_WorkOrderId] AS [T]),
> SEEK:([T].[WorkOrderId]=[WO].[Id]) ORDERED FORWARD)
>
> I am not understanding why it is doing bookmark lookup on workorder
> table when i joined StatusId column with Id column in statemaster table
> and checking the condition Statemaster.IsinDashboard = 1.
> These are the indexes we have on these tables.
> 1. In Task table "Id" is the primary Key and it is having
> non-clustered index on workorderid
> 2. In Workorder table "Id" is the primary Key and it is having
> non-clustered index on statusid
> 3. In Statemaster table "Id" is the primary Key
> Could anyone help me out why the bookmark lookup is happening, it is
> taking about 95% of the query time.
> Regards,
> ramnadh.
> *** Sent via Developersdex http://www.developersdex.com ***