94

The query is a single select containing a lot of grouping levels and aggragate operations. With SET ARITHABORT ON is takes less than a second, otherwise it takes several minutes. We have seen this behavior on SQL Server 2000 and 2008.

6 Answers 6

75

A little dated, but for anyone ending up here with a similar problem...

I had the same problem. For me it turned out to be parameter sniffing, which at first I didn't understand enough to care about. I added a 'set arithabort on' which fixed the problem but then it came back. Then I read:

http://www.sommarskog.se/query-plan-mysteries.html

It cleared -everything- up. Because I was using Linq to SQL and had limited options to fix the issue, I ended up using a query plan guide (see end of link) to force the query plan I wanted.

1
  • 7
    More than six years later, the link given in this answer is still "required reading" ... and still current too, the latest revision being December '17.
    – takrl
    Jan 3, 2018 at 8:12
31

.NET applications connect with the option disabled by default, but it's enabled by default in Management Studio. The result is that the server actually caches 2 separate execution plans for most/all procedures. This affects how the server performs numerical calculations and as such you can get wildly different results depending on the procedure. This is really only one of 2 common ways a proc can get fed a terrible execution plan, the other being parameter sniffing.

Take a look at https://web.archive.org/web/20150315031719/http://sqladvice.com/blogs/gstark/archive/2008/02/12/Arithabort-Option-Effects-Stored-Procedure-Performance.aspx for a little more discussion on it.

6
  • 1
    I agree with half of this answer. Am very sceptical about the numerical calculation claim though! Jul 18, 2010 at 9:31
  • 2
    @Martin: I think I was unclear. I was just saying the ARITHABORT ON makes SQL Server will error out on any div/0 or arithmetic overflow error. When it is off it keeps going and for whatever reason can cause all kinds of horrible problems.
    – RandomBen
    Jul 19, 2010 at 13:27
  • 2
    @Ben - Yes sorry I didn't want to particularly attack your answer I was just pointing out that it would be very easy to change a SET option get a better plan and misdiagnose this as being the Option itself that is at fault. I'm not convinced the guy in your link hasn't done this. Jul 19, 2010 at 13:37
  • @Martin - Not a problem, I didn't think you were attacking me. The other discussion I linked could be a little unclear. I was just trying to give supporting evidence.
    – RandomBen
    Jul 19, 2010 at 14:08
  • @Martin In retrospect I believe that you are correct.
    – Jonathan Allen
    Jul 27, 2011 at 17:06
25

I would argue that this was almost certainly parameter sniffing.

It is often stated that SET OPTIONS can affect performance in this way but I have yet to see a single authoritative source for this claim except for the case where you are using indexed Views / persisted computed columns.

In this case (for SQL2005+ and unless your database is in SQL2000 compatibility mode). If you have both ARITHABORT and ANSI_WARNINGS OFF then you will find the index not being used so may have a scan rather than the desired seek (and some overhead as the persisted calculation result can not be used). ADO.NET seems to default to having ANSI_WARNINGS ON from a quick test I just did.

The claim in Ben's answer that "the way the server performs numerical calculations" can add minutes to a result that would otherwise take less than a second just doesn't seem credible to me. I think what tends to happen is that upon investigating a performance performance problem Profiler is used to identify the offending query. This is pasted into management studio and run and returns results instantly. The only apparent difference between connections is the ARITH_ABORT option.

A quick test in a management studio window shows that when SET ARITHABORT OFF is turned on and the query is run that the performance problem recurs so that is apparently case closed. Indeed this seems to be the troubleshooting methodology used in the Gregg Stark link.

However that ignores the fact that with that option set you can end up getting the exact same bad plan from the cache.

This plan reuse can happen even if you are logged in as a different user than the application connection uses.

I tested this by executing a test query first from a web application then from management studio with SET ARITHABORT OFF and could see the usecounts going up from the below query.

SELECT usecounts, cacheobjtype, objtype, text ,query_plan
FROM sys.dm_exec_cached_plans 
CROSS APPLY sys.dm_exec_sql_text(plan_handle) 
CROSS APPLY sys.dm_exec_query_plan(plan_handle) 

In order for this sharing pf plans to actually occur all plan cache keys must be the same. As well as arithabort itself some other examples are the executing users need the same default schema (if the query relies on implicit name resolution) and the connections need the same language set.

A fuller list of plan cache keys here

0
16

I know I'm late to this party, but for future visitors, Martin is exactly correct. We ran into this same issue--an SP was running very slowly for .NET clients, while it was blazing fast for SSMS. In exploring and resolving the issue, we did the systematic testing that Kenny Evitt asks about in his comment to Martin's question.

Using a variant of Martin's query, I looked for the SP in the procedure cache and found two of them. Looking at the plans, it was in fact the case that one had ARITHABORT ON and one had ARITHABORT OFF. The ARITHABORT OFF version had an index seek while the ARITHABORT ON version used an index scan for that same output. Given the parameters involved, the index seek would have required a lookup on tens of millions of records for the output.

I cleared the two procedures from the cache and had the .NET client run the SP again, using the same parameters (which featured a wide date range for a customer with lots of activity). The SP returned instantly. The cached plan used the same index scan that was previously featured in the ARITHABORT ON plan--but this time the plan was for ARITHABORT OFF. We ran the SP with the same parameters in SSMS, and again got results instantly. Now we saw that a second plan was cached, for ARITHABORT ON, with the index scan.

We then cleared the cache, ran the SP in SSMS with a narrow date range and got an instant result. We found that the resulting cached plan had an index seek, for the same output was previously handled with a scan (which was also a seek in the original plan with ARITHABORT OFF). Again from SSMS, we ran the SP, this time with the same wide date range, and saw the same terrible performance we had in the original .NET request.

In short, the disparity had nothing to do with the actual value of ARITHABORT--with it on or off, from either client, we could get acceptable or terrible performance: All that mattered was the parameter values used in compiling and caching the plan.

While MSDN indicates that ARITHABORT OFF itself can have a negative impact on query optimization, our testing confirms that Martin is correct--the cause was parameter sniffing and the resulting plan not being optimal for all ranges of parameters.

2
  • 1
    Wonder what that phrase Setting ARITHABORT to OFF can negatively impact query optimization leading to performance issues. means. Whether they are just talking about inability to use indexes on computed columns and views (if ANSI_WARNINGS is also off) or if it does indeed have some other effect. Jul 9, 2013 at 7:22
  • I'm not sure. I wonder if it's simply the case that someone at MSDN ran into a similar situation, set ARTIHABORT to ON, saw the performance improvement, and jumped to same conclusions others have. As far as indexed views and computed columns, I'm unclear. At one point it states that the SET options must have specific values if an INSERT, UPDATE, or DELETE operation modifies data values stored therein. Elsewhere they state that the optimizer will ignore indexes for "any query" that references said indexed view or computed column. Are both true, or is it really "any query modifying data"?
    – mdoyle
    Jul 9, 2013 at 19:41
4

Just had this problem. As people said here, the root cause is multiple query plans, one of which is sub-optimal. I just wanted to verify that ARITHABORT can indeed cause the problem by itself (as the query I was having problems with had no parameters, which takes parameter sniffing out of the equation).

1

This reminds me the exactly same issue I experienced in sql server 2008 days. In our case, we suddenly found one sql job suddenly slowed down (usually a few seconds, and now 9+ minutes), the job needs to access a linked server, we added set ARITHABORT on in the job's step, and it seemed the problem was solved for a few days and then returned.

We later opened a ticket with MS support, and initially they cannot found out either, and the ticket was escalated to a very senior PFE team, and two support PFEs tried to figure out this issue.

The final reason is that the user credential (to run the job step) cannot access the statistics of the underlying tables (on the linked server side), and thus the execution plan is not optimized.

In detail, the user does not have permission on DBCC SHOW_STATISTICS (though the user can SELECT from the table). According to MSDN, this permission rule is changed after sql 2012 SP1

Permissions for SQL Server and SQL Database

In order to view the statistics object, the user must own the table or the user must be a member of the sysadmin fixed server role, the db_owner fixed database role, or the db_ddladmin fixed database role.

SQL Server 2012 SP1 modifies the permission restrictions and allows users with SELECT permission to use this command. Note that the following requirements exist for SELECT permissions to be sufficient to run the command:

To verify this issue, we just need to run the profiler on the linked server side instance and turn on some events in "Errors and Warnings" section as shown below.

enter image description here

Hope this experience may help the community somehow.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.