Why is an ODBC query against MSSQL 2008SP2 100 times larger than the same query in Studio?

I have a really weird query involving combining in a complex look. I analyzed the output from the view, built some indexes and earned the query within a second when starting from MSSQL Management Studio. However, when starting from Perl via ODBC, the same request takes about 80 seconds to return.

I dropped almost 8 hours on it, and it continues to bother me. During this time, I ran the query from Perl and copied it verbatim to Studio, I wrapped it in a stored procedure (which makes it execute about 2.5 minutes from the BOTH clients!), I looked for ODBC and MSSQL search caches, I watched how the request is launched through Activity Monitor (it spends most of its time in the general waiting state SLEEP_TASK) and Profiler (the select statement receives one line that does not appear before it is executed), and I started reading about performance bottlenecks.

I did not notice this problem with any other requests from Perl and, unfortunately, we do not have a database administrator on the site. I am a programmer who has done several database administrators, but it seems to me that I am in the dark with this. My best guess is that Studio has some kind of query cache that the ODBC client cannot receive, but restarting Studio does not make the request the first execution longer, so it does not look like it just because every new ODBC connection starts from an empty cache.

Without going into view definitions, the basic query is very simple:

SELECT * FROM VIEW1 LEFT OUTER JOIN VIEW2 WHERE SECTION = ? AND ID = ? 

The delay disappears when I drop VIEW2, but I need data from this view. Three times I rewrote the view in an attempt to simplify and increase efficiency, but it looks like a dead end, since the request works fine from Studio. The query returns only one row, but even discards the identifier criteria and selecting all 56k rows for the entire section takes only 40 seconds from Studio. Any other ideas?

Edit 2/8: The related article by @Remus Rusanu was pretty clear, but I'm afraid this is not entirely applicable. Now it seems pretty obvious that this is not ODBC at all, but that when I hard-argument the arguments and parameterize them, I have different execution plans. I can reproduce this in SSMS:

 SELECT * FROM VIEW1 LEFT OUTER JOIN VIEW2 WHERE SECTION = 'a' AND ID = 'b' 

100 times faster than

 DECLARE @p1 VARCHAR(8), @p2 VARCHAR(3) SET @p1 = 'a' SET @p2 = 'b' SELECT * FROM VIEW1 LEFT OUTER JOIN VIEW2 WHERE SECTION = @p1 AND ID = @p2 

Unfortunately, I still do not understand why the first one should get an execution plan that takes two orders of magnitude less time than the parameterized version for any SECTION and ID values ​​that I can use for this. This may be a flaw in SQL Server, but it seems silly that the inputs are known in both places, but one takes much longer. If the SQL server recalculates the parameterized plan from scratch every time, as it should be for the different constant values ​​that I supply, it will be 100 times faster. None of the RECOMPILE options suggested by this article help.

I think @GSerg called it below. I have not yet proven that this does not happen with the window function used externally for presentation, but it describes the same thing and the time difference remains unclear.

If I don’t have enough time to work on this, I will try to adapt some article tips and enforce a permanent execution plan on a parameterized version, but there seems to be a lot of that there should be unnecessary problems.

+4
source share
3 answers

As Martin Smith explained , he has a problem with pushing a predicate in SQL Server, which has not been fully fixed.

As stated in the answers and comments in the related question, you can either

  • Wrap the request in something adding option(recompile)
  • Convert it to a table function.
  • Attach a plan with option (recompile)
+3
source

Everything you ever wanted to know on this subject: Slow application, fast in SSMS? Understanding Mysteries Performance .

SSMS does not have a "cache" that ODBC cannot access. It’s just that you get different execution plans in SSMS or ODBC, either due to sniffing parameters or due to data type priority rules. Read the article related to it, it has both the means to identify the problem and recommendations for resolving it.

+1
source

Compare the plans of the two queries and check the SET settings for each connection (you can do this by looking at sys.dm_exec_sessions). I bet you will see the difference in quoted_identifier, ansi_nulls or arithabort (or maybe all three). This usually leads to huge differences in terms of implementation. You must be able to manually set these parameters in your version of ODBC to match the settings used by Management Studio.

Some related questions - there may be other unclear circumstances in the game that you want to check:

SQL query is slower in .NET application, but instantly in SQL Server Management Studio

SQL Server Query Slow from PHP, but FAST from SQL Mgt Studio - WHY?

Request time from web application but works great with management studio

Quickly save SQL Server 2005 stored procedure in SSMS with VBA

+1
source

Source: https://habr.com/ru/post/1395460/


All Articles