BorderLayoutBoxedLayoutOpenLayoutMaximum textMedium textSmall text


Register
Friday, September 10, 2010
 Â
MyStreamMinimize
Print  

CXPACKET, MAXDOP and your OLTP system

Posted by Jason on Thursday, June 26, 2008 to SQL Server 2005, query optimizer, SQL performance tuning, tsql, DMVs
9685 Views | 6 Comments | Article Rating

So you are experiencing CXPACKET wait types? If you run a google search, you will quickly find out you are experiencing the dreaded SQL Server parallelism problem and you must reduce MAXDOP to 1. While that is possible, I say most likely not. I say that, most of the time, SQL is doing the best it can with what it has to work with. That is the query, the data and the schema.

Microsoft has come a long way since version <= 7.0 when it comes to parallelism. If your OLTP queries follow best practices and are well indexed, they probably will never generate a parallel plan. This is because they are fast and access a small amount of rows. If they are missing indexes or SQL overestimates cardinality, SQL might decide to do scans, sorts, hashes, spools etc. These iterators, among others, can go parallel to reduce execution time at the cost of system resources. These iterators are not bad and they do have their place. It just isn’t on OLTP type of queries most of the time.

So dropping the MAXDOP on an OLTP system to 1 probably won’t hurt much because most of the time there is an IO bottleneck. If the CXPACKET wait types are a symptoms of poor indexing and row count estimation, it won’t help either. Whole books have been written on indexing, query tuning and there is a nice whitepaper on stats best practices to avoid estimation problems so I am not going to go into that. I will give you some pointers on quickly identifying whether the CXPACKET is a symptom or the cause.

So your boss and boss's boss run over to your desk yelling about the customer complaints of slowness with SQL. You run this query or something similar:

select r.cpu_time 
, r.logical_reads
, r.session_id 
into #temp
from sys.dm_exec_sessions as s 
inner join sys.dm_exec_requests as r 
on s.session_id =r.session_id --and s.last_request_start_time=r.start_time
where is_user_process = 1 
 
waitfor delay '00:00:01'
 
select substring(h.text, (r.statement_start_offset/2)+1 , ((case r.statement_end_offset when -1 
then datalength(h.text)  else r.statement_end_offset end - r.statement_start_offset)/2) + 1) as text
, r.cpu_time-t.cpu_time as CPUDiff 
, r.logical_reads-t.logical_reads as ReadDiff
, p.query_plan
, r.wait_type
, r.wait_time
, r.last_wait_type
, r.wait_resource
, r.command
, r.database_id
, r.blocking_session_id
, r.granted_query_memory
, r.session_id
, r.reads
, r.writes
, r.row_count
, s.[host_name]
, s.program_name
, s.login_name
from sys.dm_exec_sessions as s 
inner join sys.dm_exec_requests as r 
on s.session_id =r.session_id and s.last_request_start_time=r.start_time
full outer join #temp as t on t.session_id=s.session_id
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) h
cross apply sys.dm_exec_query_plan(r.plan_handle) p
order by 3 desc
 
drop table #temp
 

You notice that you have several rows with CXPACKET wait types. With this query, you click the xml show plan link and:
1.    search the xml for missing indexes.
2.    Save as a .sqlplan and reopen in SSMS
3.    Compare estimated and actual rows in the iterators on the right side of the plan. Poor estimates may bubble to the left as well.
4.    If there are no missing indexes, estimates and actual are fairly close, reducing MAXDOP may help if it is not a huge report or query.

5. If there are missing index or bad estimations, fix it! :)


Of course, these are not rules set in stone. Just a style in the art of database administration. Just don't blame it on a "parallelism bug" because it is a poor musician that blames his instrument.

One thing to note, if you do turn down MAXDOP server-wide, turn in on at the query level(enterprise edition) on your index operation because they are optimized for it.
Alter index all on tblBlah rebuild with (maxdop=32);

email it! |   |   |   |  | 
Permalink     6 Comments  

Rate this Post:
COMMENTS:

I understand all the advice about statistics and estimated vs actual reads, but I'm confused about your query with the ReadDiff and CPUDiff on the same session. What's the theory behind that?

posted @ Thursday, June 26, 2008 9:53 PM by Sideout


The readdiff and CPUDiff really don't matter in the context of this conversation. That is just the query I use to see what is going on right now.

I take a snapshot, wait a second and then do a diff because the CPU and IO columns are cumulative so the session with the highest number is not necessarily the one pegging out the system right now. The diff allows me to see that.

posted @ Friday, June 27, 2008 9:35 AM by Jason


Do you have simular codes for sql 2000?

posted @ Wednesday, July 02, 2008 7:14 PM by Ann Han


Great idea Jason. Hadn't thought about the time split (sadly) to see those most active in that time. Pretty cool and a nice tool to have in the box!

posted @ Monday, March 02, 2009 3:02 PM by DavidB


Comments from the following blog entry: http://noggle.com/?p=37

posted @ Tuesday, September 01, 2009 11:11 AM


>
One thing to note, if you do turn down MAXDOP server-wide, turn in on at the query level(enterprise edition) on your index operation because they are optimized for it. Alter index all on tblBlah rebuild with (maxdop=32);
<

This is incorrect for SQL2005 (may be true in 2008 but I don't have that information)

From BOL for SQL2005 under "Query Hint":
MAXDOP number
Overrides the max degree of parallelism configuration option of sp_configure only for the query specifying this option. The MAXDOP query hint has no effect if it exceeds the value configured with sp_configure. All semantic rules used with the max degree of parallelism configuration option are applicable when you use the MAXDOP query hint. For more information, see max degree of parallelism Option.

posted @ Friday, September 11, 2009 12:51 PM by mstjn


Name (required)

Email (required)

Website


Simple BBCode can be used like [url=http://example.com]Example[/url] and [B]

Copyright 2006 by Statistics IO, My SQL Server Blog