|
Workspace Memory / Query Memory Tuning
(RESOURCE_SEMAPHORE / IO_COMPLETION / SLEEP_TASK)
SQL Server is configured to use a lot of memory, but my
query is slow and not using all the memory available and it is
spilling the sort or the hash match operation to tempdb, how can you tune the configuration and the query?
Memory allocating
queries request memory based on estimation (ideal memory) and
query memory (workspace memory) availability, when they don’t
get the right amount of memory they spill to tempdb and lead to
performance issues. Previous
articles discussed
ways to make the estimation better; this article discusses ways
to address query memory availability.
This and similar topics are covered in my
workshops. If you are interested in learning practical
techniques to improve your SQL server performance, register for
the upcoming 3 Day Level 400 Microsoft SQL Server 2012 and 2008 Performance Monitoring & Tuning Hands-on Workshop in Helsinki, Finland
during
February 27-March 01, 2013, click
here to register. These are hands-on
workshops with a maximum of 12 participants and not lectures.
For consulting engagements click
here.
You can find the ideal
amount of memory a query needs (when the query is executing)
using sys.dm_exec_query_memory_grants. Common memory allocating
queries are that perform Sort and do Hash Match operations like
Hash Join or Hash Aggregation or Hash Union.
select
* from
sys.dm_exec_query_memory_grants
go
Column ideal_memory_kb
indicates the ideal amount of memory the query needs. This is
based on estimation, this might be incorrect for various reasons
including out of date statistics, in some cases (more common
that you might think) under estimation of memory by the
optimizer even when the statistics are up to date (refer to
article
http://jahaines.blogspot.com/2010/03/performance-tuning-101-what-you-will.html)
and due to plan caching (refer to article
Plan Caching and Query Memory). Some might
recommend tweaking the index/column statistics in an
undocumented way to inflate the estimation for additional
memory, I suggest following the MSSQL Tip
http://www.mssqltips.com/sqlservertip/1955
and webcast
1 and 2 at
www.sqlworkshops.com/webcasts to understand the issue and
the recommendations.
To read additional articles I wrote
click
here.
The ideal amount of
memory a query needs is based on estimation. Requested memory is
based on ideal memory and maximum available workspace memory.
There is a possibility the estimation is correct (let’s say you
have up to date statistics and/or fixed the under estimation
issues by following the above articles) but the available
workspace memory is not enough and hence ideal amount is low.
The next question is: what is available workspace memory.
Available workspace memory, also known
as query memory, is the amount of memory available for common
memory allocating queries that perform Sort and do Hash Match
operations. This is automatically calculated based on your
system configuration. You can monitor the currently available
workspace memory and maximum workspace memory by executing the
command dbcc memorystatus and looking for ‘Available’ and
‘Current Max’ under ‘Query Memory Objects (default)’ and ‘Small
Query Memory Objects (default)’. Or using Performance Monitor
counters ‘Granted Workspace Memory (KB)’ and ‘Maximum Workspace
Memory (KB)’ under object Memory Manager. ‘Maximum Workspace
Memory (KB)’ is the sum of ‘Current Max’ of both ‘Query Memory
Objects (default)’ and ‘Small Query Memory Objects (default)’,
note ‘Current Max’ is in pages (* 8 = KB).
Here is a query to find the ‘Maximum
Workspace Memory (KB)’ using sys.dm_os_performance_counters,
‘Maximum Workspace Memory (KB)’ can be up to 75% of ‘Target
Server Memory (KB)’.
The best way to
learn is to practice. To create the below tables and reproduce
the behavior, join the mailing list by using this link:
www.sqlworkshops.com/ml
and I will send you the table creation script.
--Example provided by www.sqlworkshops.com
select
(select
cntr_value
from
sys.dm_os_performance_counters
where
object_name
like
'%Memory Manager%' and
counter_name like
'Maximum Workspace Memory (KB)%')
as
'Maximum Workspace Memory (KB)',
(select
cntr_value
from
sys.dm_os_performance_counters
where
object_name
like
'%Memory Manager%' and
counter_name like
'Target Server Memory (KB)%')
as
'Target Server Memory (KB)',
(select
cntr_value
from
sys.dm_os_performance_counters
where
object_name
like
'%Memory Manager%' and
counter_name like
'Maximum Workspace Memory (KB)%')
* 100.0
/
(select
cntr_value
from
sys.dm_os_performance_counters
where
object_name
like
'%Memory Manager%' and
counter_name like
'Target Server Memory (KB)%')
as Ratio
go
In my server, when Target Server Memory is
4096MB, Maximum Workspace Memory is 3077MB, which is about 75%
of Target Server Memory.
By default a query will not request
more than 25% of this Maximum Workspace Memory in SQL Server
2008 and above and this Memory Grant 25% can be changed using
Resource Governor Workload Group settings. With SQL Server 2005
and below, this is 20% and cannot be changed without the support
of Microsoft (with a combination of undocumented trace flag and
changes to the configuration parameters).
Why should you care about 25%? You
might have a customer executing a heavy reporting query in the
night and they want to use more than 25% of Maximum Workspace
Memory for that single query. Let’s assume the customer
configured 4096MB for their SQL Server instance (the Target
Server Memory might be less than the configured memory if there
is memory pressure on the server), let's say their workspace
memory is 3077MB (‘Query Memory Objects (default)’->‘Current
Max’ = 381175 pages = 3049400KB + ‘Small Query Memory Objects
(default)’ ->‘Current Max’ = 12800 pages = 102400KB; 3049400KB +
102400KB = 3077MB. And this customer’s query executing the
report is limited to a maximum of 3049400KB / 4 = 744MB.
Let’s say the customer’s query
executing the report needs 1,470MB of query memory (ideal
memory) in order not to spill the sort to tempdb, but the query
will request only 744MB. In case the customer can set the
‘request_max_memory_grant_percent’ (Memory Grant %) of the
Workload Group setting to 50%, then the query can request up to
1,488MB and in this case the query will request the ideal memory
it needs which is 1,470MB.
SQL Server has memory grant queues
based on cost, if queries need more memory and there is not
enough memory available in the queue, then the query will wait,
you can get additional details using the command dbcc
memorystatus. If a query requests huge amount of memory, but
doesn’t utilize it (due to over estimation), this memory will be
reserved and cannot be used by other queries, in some cases this
will lead to unnecessary memory grant waits. So one has to be
very careful not to overestimate (also described in the webcast
www.sqlworkshops.com/webcasts) too much memory as
it will affect concurrency. When the query waits for memory, the
wait type will be ‘RESOURCE_SEMAPHORE’.
Let's set 'max server memory (MB)' to 4GB.
exec
sp_configure
'show advanced options',
1
go
reconfigure go
exec
sp_configure
'max server memory (MB)',
4096
go
reconfigure go
The best way to
learn is to practice. To create the below tables and reproduce
the behavior, join the mailing list by using this link:
www.sqlworkshops.com/ml
and I will send you the table creation script.
Scenario 1:
This query will underestimate memory due
to optimizer issues and will also request less memory (744MB)
due to the 25% Resource Governor Workload Group Memory Grant
setting. The query will be slow spilling
the sort to tempdb.
When the sort spills to
tempdb the wait type will be ‘IO_COMPLETION’
but when the Hash Match operation spills to tempdb the wait type
will be ‘SLEEP_TASK’.
We are using option (maxdop 1) to
disable parallelism, to learn more about monitoring and tuning
parallel query execution, refer to the webcast
www.sqlworkshops.com/webcasts and article
Parallel Sort and Merge Join – Watch out for unpredictability
in performance.
set
statistics
time on
go
--Example provided by www.sqlworkshops.com
declare
@c1 int,
@c2 int,
@c3 char(2000)
declare
@i int
set
@i = 500000
select
@c1 = c1,
@c2 = c2,
@c3 = c3
from
tab7
where
c1 < @i
order
by c2
option
(maxdop
1)
go
Scenario 2:
This query will have better memory
estimation due to the option clause with optimize for hint, but
will still request less memory (744MB) due to the 25% Resource
Governor Workload Group Memory Grant setting.
The query will also be slow spilling the
sort to tempdb.
set
statistics
time on
go
--Example provided by www.sqlworkshops.com
declare
@c1 int,
@c2 int,
@c3 char(2000)
declare
@i int
set
@i = 500000
select
@c1 = c1,
@c2 = c2,
@c3 = c3
from
tab7
where
c1 < @i
order
by c2
option
(optimize
for (@i
= 600000),
maxdop
1)
--
Option optimize for is used to inflate memory request
-- without this the query will spill the sort to tempdb due
-- to query optimizer under estimation of memory.
-- One possibility is to inflate
the number of rows, -- the other possibility is to inflate
the row size
-- For
more information refer to webcasts 1 & 2 -- at
www.sqlworkshops.com/webcasts.
go
Scenario 3:
This query will have better memory estimation due to
the option clause with optimize for hint and will also request
enough memory (1,470MB) due to the 50% Resource Governor
Workload Group Memory Grant setting.
The query will be fast with no
spilling of sort to tempdb.
Please read the entire article and
answer the challenge posted at the end of this article before
changing the Resource Governor Workload Group Memory Grant
setting in your production server as there are major
disadvantages of changing the Resource Governor Workload Group
Memory Grant setting, don't do it without understanding the full
picture.
alter
workload
group [default]
with(request_max_memory_grant_percent=50)
go
alter
resource
governor
reconfigure
go
set
statistics
time on
go
--Example provided by www.sqlworkshops.com
declare
@c1 int,
@c2 int,
@c3 char(2000)
declare
@i int
set
@i = 500000
select
@c1 = c1,
@c2 = c2,
@c3 = c3
from
tab7
where
c1 < @i
order
by c2
option
(optimize
for (@i
= 600000),
maxdop
1)
--
Option optimize for is used to inflate memory request
-- without this the query will spill the sort to tempdb due
-- to query optimizer under estimation of memory.
-- One possibility is to inflate
the number of rows, -- the other possibility is to inflate
the row size
-- For
more information refer to webcasts 1 & 2 -- at
www.sqlworkshops.com/webcasts.
go
Scenario 4:
Let's execute 2 of this query concurrently
in 2 sessions, with 25% Resource Governor Workload Group Memory
Grant setting.
alter
workload
group [default]
with(request_max_memory_grant_percent=25)
go
alter
resource
governor
reconfigure
go
Session 1:
Let's execute this query in a loop and measure the performance
of the query executed in session 2. This query will have better
memory estimation due to the option clause with optimize for
hint, but will still request less memory (744MB) due to the 25%
Resource Governor Workload
Group Memory Grant setting.
The query will be spilling the sort to
tempdb.
while
1=1 begin --Example provided by
www.sqlworkshops.com
declare
@c1 int,
@c2 int,
@c3 char(2000)
declare
@i int
set
@i = 500000
select
@c1 = c1,
@c2 = c2,
@c3 = c3
from
tab7
where
c1 < @i
order
by c2
option
(optimize
for (@i
= 600000),
maxdop
1)
--
Option optimize for is used to inflate memory request
-- without this the query will spill the sort to tempdb due
-- to query optimizer under estimation of memory.
-- One possibility is to inflate the
number of rows, -- the other possibility is to inflate the
row size
-- For more information refer to webcasts 1 & 2 -- at
www.sqlworkshops.com/webcasts.
end
go
Session 2:
Let's execute this query few times. This query will have better
memory estimation due to the option clause with optimize for
hint, but will still request less memory (744MB) due to the 25%
Resource Governor Workload
Group Memory Grant setting.
The query will be slow spilling the sort
to tempdb. This query might take up to twice the amount
of time to complete compared to Scenario 2, because 2 queries
from 2 sessions are concurrently spilling to tempdb. There is no
wait for memory grants (no RESOURCE_SEMAPHORE waits).
set
statistics
time on
go
--Example provided by www.sqlworkshops.com
declare
@c1 int,
@c2 int,
@c3 char(2000)
declare
@i int
set
@i = 500000
select
@c1 = c1,
@c2 = c2,
@c3 = c3
from
tab7
where
c1 < @i
order
by c2
option
(optimize
for (@i
= 600000),
maxdop
1)
--
Option optimize for is used to inflate memory request
-- without this the query will spill the sort to tempdb due
-- to query optimizer under estimation of memory.
-- One possibility is to inflate the
number of rows, -- the other possibility is to inflate the
row size
-- For more information refer to webcasts 1 & 2 -- at
www.sqlworkshops.com/webcasts.
go
Scenario 5:
Let's execute 2 of this query concurrently
in 2 sessions, with 50% Resource Governor Workload Group Memory
Grant setting.
alter
workload
group [default]
with(request_max_memory_grant_percent=50)
go
alter
resource
governor
reconfigure
go
Session 1:
Let's execute this query in a loop and measure the performance
of the query executed in session 2.
This query will have better memory estimation due
to the option clause with optimize for hint and will also
request enough memory (1,470MB) due to the 50% Resource Governor
Workload Group Memory Grant setting.
The query will have no spilling
of sort to tempdb.
while
1=1 begin --Example provided by
www.sqlworkshops.com
declare
@c1 int,
@c2 int,
@c3 char(2000)
declare
@i int
set
@i = 500000
select
@c1 = c1,
@c2 = c2,
@c3 = c3
from
tab7
where
c1 < @i
order
by c2
option
(optimize
for (@i
= 600000),
maxdop
1)
--
Option optimize for is used to inflate memory request
-- without this the query will spill the sort to tempdb due
-- to query optimizer under estimation of memory.
-- One possibility is to inflate the
number of rows, -- the other possibility is to inflate the
row size
-- For more information refer to webcasts 1 & 2 -- at
www.sqlworkshops.com/webcasts.
end
go
Session 2:
Let's execute this query few times.
This query will have better memory estimation due
to the option clause with optimize for hint and will also
request enough memory (1,470MB) due to the 50% Resource Governor
Workload Group Memory Grant setting.
The query will be fast with no
spilling of sort to tempdb.
But this query might take up to twice the amount of time to
complete compared to Scenario 3, because 2 queries from 2
sessions are concurrently requesting nearly 50% of workspace
memory.
There is wait for memory grants (RESOURCE_SEMAPHORE waits),
SQL Server grants memory to one query at a time as the memory in
the grant queue is not enough to grant simultaneously the
requested memory to both queries.
set
statistics
time on
go
--Example provided by www.sqlworkshops.com
declare
@c1 int,
@c2 int,
@c3 char(2000)
declare
@i int
set
@i = 500000
select
@c1 = c1,
@c2 = c2,
@c3 = c3
from
tab7
where
c1 < @i
order
by c2
option
(optimize
for (@i
= 600000),
maxdop
1)
--
Option optimize for is used to inflate memory request
-- without this the query will spill the sort to tempdb due
-- to query optimizer under estimation of memory.
-- One possibility is to inflate the
number of rows, -- the other possibility is to inflate the
row size
-- For more information refer to webcasts 1 & 2 -- at
www.sqlworkshops.com/webcasts.
go
Overall performance of
scenario 5 is better than scenario 4 even though there was
memory grant waits. In this case waiting for memory is
far worse than spilling the sort to tempdb.
Scenario 6:
Let's execute two queries with less memory
requirement concurrently in two sessions (so memory can be
granted for both queries simultaneously from the same memory
grant queue), with 50% Resource Governor Workload Group Memory
Grant setting.
Session 1:
Let's execute this query in a loop and measure the performance
of the query executed in session 2.
This query will have better memory estimation due
to the option clause with optimize for hint and will also
request enough memory (1,102MB) due to the 50% Resource Governor
Workload Group Memory Grant setting.
The query will have no spilling
of sort to tempdb.
while
1=1
begin
--Example provided by www.sqlworkshops.com
declare
@c1 int,
@c2 int,
@c3 char(2000)
declare
@i int
set
@i = 400000
select
@c1 = c1,
@c2 = c2,
@c3 = c3
from
tab7
where
c1 < @i
order
by c2
option
(optimize
for (@i
= 450000),
maxdop
1)
--
Option optimize for is used to inflate memory request
-- without this the query will spill the sort to tempdb due
-- to query optimizer under estimation of memory.
-- One possibility is to inflate the
number of rows, -- the other possibility is to inflate the
row size
-- For more information refer to webcasts 1 & 2 -- at
www.sqlworkshops.com/webcasts.
end
go
Session 2:
Let's execute this query few times.
This query will have better memory estimation due
to the option clause with optimize for hint and will also
request enough memory (1,102MB) due to the 50% Resource Governor
Workload Group Memory Grant setting.
The query will be fast with no
spilling of sort to tempdb.
There will be no wait for memory
grants (RESOURCE_SEMAPHORE waits), SQL Server
grants memory to both queries simultaneously as the memory in
the grant queue is enough to grant the requested memory to both
queries.
set
statistics
time on
go
--Example provided by www.sqlworkshops.com
declare
@c1 int,
@c2 int,
@c3 char(2000)
declare
@i int
set
@i = 400000
select
@c1 = c1,
@c2 = c2,
@c3 = c3
from
tab7
where
c1 < @i
order
by c2
option
(optimize
for (@i
= 450000),
maxdop
1)
--
Option optimize for is used to inflate memory request
-- without this the query will spill the sort to tempdb due
-- to query optimizer under estimation of memory.
-- One possibility is to inflate the
number of rows, -- the other possibility is to inflate the
row size
-- For more information refer to webcasts 1 & 2 -- at
www.sqlworkshops.com/webcasts.
go
Challenge:
There are major disadvantages of
changing the Resource Governor Workload Group Memory Grant
setting, so don't make any changes without understanding the
full picture. I will cover this is the next article, meanwhile
if you can guess some reasons, write to me:
Contacts.
I explain some
of these concepts with detailed examples in my webcasts (www.sqlworkshops.com/webcasts),
I recommend you to watch them. The best way to learn is to
practice. To create the above tables and reproduce the behavior,
join the mailing list at
www.sqlworkshops.com/ml
and I will send you the relevant SQL Scripts.
Register for the upcoming 3 Day Level 400 Microsoft SQL Server 2012 and 2008 Performance Monitoring & Tuning
Hands-on Workshop in Helsinki, Finland
during
February 27-March 01, 2013, click
here to register. These are hands-on
workshops with a maximum of 12 participants and not lectures.
For consulting engagements click
here.
Disclaimer and copyright
information:
This article refers to organizations and
products that may be the trademarks or registered trademarks of
their various owners.
Copyright of this article
belongs to
R
Meyyappan
/ www.sqlworkshops.com.
You may freely use the ideas and concepts discussed in this
article with acknowledgement (www.sqlworkshops.com),
but you may not claim any of it as your own work.
This article is for informational purposes
only; you use any of the suggestions given here entirely at your
own risk.

Ramesh's consulting customers include Austria:
Allgemeines Krankenhaus Linz, BMD Systemhaus,
Bundesrechenzentrum, bwin, C07 IT Operations, CMC Markets,
derStandard, ERGO Insurance Service, Fabasoft Austria,
Greentube, IAEA (UN), Interwetten, INTERSPORT, Kapsch, Linz
AG, Mayr-Melnhof Karton, NÖM, ÖBB, OMV, Österreichische
Post, RACON West Software, Raiffeisen Bankengruppe,
Raiffeisen Informatik, S.Spitz, Salzburg AG, Siemens, TIWAG,
UC4, Vinzenz Gruppe, Wiener Zeitung, Wirtschaftskammer
Österreich; Bulgaria: MobilTel;
Czech Republic: Česká pojišťovna, ČSOB Bank, GTS
Novera, Telefónica O2, Vodafone; Denmark:
Danfoss, Egmont, NNIT; Finland: Cap Gemini,
Kemira, Pohjola; Germany: JAM Software, SAP
AG; Netherlands: De Nederlandsche Bank;
Norway: Acta, Aker Solutions, Det Norske
Veritas(DNV), Komplett; Russia: Mediatel;
Serbia: Tarkett; Slovakia:
Adastra Corporation, VÚB Banka; Slovenia:
Bankart, Iskratel, KDD, Krka, Mobitel, Pošta Slovenije,
Sava, SRC.SI; South Africa: De Beers,
Kumba, Sasol; Spain: CIE Automotive, Gas
Natural, ITP; Sweden: Sony Ericsson;
Switzerland: F. Hoffmann-La Roche, Philip
Morris International; UAE: Dubai Customs.
For past consulting engagement feedbacks click
here.
COPYRIGHT AND TRADEMARK NOTICES:
The copyright in all material provided on this site is held
by SQLWorkshops.com or by the original creator of the material.
Except as stated herein, none of the material may be copied,
reproduced, distributed, republished, downloaded, displayed,
posted or transmitted in any form or by any means, including,
but not limited to, electronic, mechanical, photocopying,
recording, or otherwise, without the prior written permission of
SQLWorkshops.com or the copyright owner. Permission is granted
to download the webcast on this Site for personal,
non-commercial use only, provided you do not modify the webcast
and that you retain all copyright and other proprietary notices
contained in the webcast. You also may not, without
SQLWorkshops.com permission, "mirror" any webcast contained on
this Site on any other server. This permission terminates
automatically if you breach any of these terms or conditions.
Upon termination, you must immediately destroy any downloaded
webcast. Any unauthorized use of any webcast contained on this
Site may violate copyright laws, trademark laws, the laws of
privacy and publicity, and communications regulations and
statutes.
Microsoft is a registered trademark of Microsoft Corporation in
the United States and/or other countries. SQL Server is a
trademark of Microsoft Corporation in the United States and/or
other countries. This webcast may refer to organizations and
products that may be the trademarks or registered trademarks of
their various owners.
You may freely use the ideas and concepts discussed in this
webcast, but you may not claim any of it as your own work. You
may quote freely, with acknowledgements to SQLWorkshops.com.
This article is for informational purposes only; you use any of
the suggestions given here entirely at your own risk.
|