DQL: enable (return_top 10) performance impact - dql

I had this query that originally caused massive timeouts:
select d.r_object_id
from isc_fiche d, dmr_con c
where any c.parent_id = d.r_object_id
group by d.r_object_id
having count(*) > 2
yet when I add the enable (return_top 10) to the end then the performance issues seem a thing off the past. Apparently (according to colleagues) that statement could have a perfomance-improving effect.
Could someone clarify this for me?
Full query with 'way' better performance:
select d.r_object_id
from isc_fiche d, dmr_con c
where any c.parent_id = d.r_object_id
group by d.r_object_id
having count(*) > 2
enable(return_top 10)

enable (return_top 10) modifies the executed SQL statement, it adds a limiting clause to it, like ROWNUM <= 10 in Oracle. It depends on the underlying RDBMS, so I guess it's not ROWNUM <= 10 if you use EMC Documentum with Microsoft SQL Server.
You can run DQLs on the web interface of ECM Documentum (if I remember correctly it's called Webtop). There is a checkbox on the DQL run page which shows the generated SQL. You should check there what's the difference between the two DQL query.

Related

Which approach is better and why? Select statements or functions in PL/SQL?

Which approach is better and why? Select statements or functions in PL/SQL?
I came across some articles on PL/SQL where it was mentioned that select statements should be replaced by the functions.
Whether this really improves the performance?
When writing PL/SQL, every call to a select statement is a context switch. Context switches are expensive, which is why PL/SQL has the forall statement and other structures that allow you to execute PL/SQL without having to call SQL. Use SQL when you are retrieving data from an object, use PL/SQL when you don't need to fetch from a table.
e.g.
use
l_val := trim(l_val);
rather than
select trim(l_val) into l_val from dual;
Both yield the same answer, but the first is much less expensive than the second.
Minimizing context switches will make your code much more efficient:
bad:
For eachrec in ( select a, b from table1) loop
update table2 set c = eachrec.a where d = eachrec.b;
end loop;
better:
update table2 set c = (select a from table1 where d = b)
where exists(select null from table1 where d = b);
The second method is better because there is only a single context switch, rather than a context switch for each record being updated.
Can someone help me with the update statement? I know there is a way of writing it without doing the "select". Our databases are from vendors who don't believe in primary keys, so I have never got into the habit of using updates on joins.
In general, prefer SQL. SQL can be portable across databases. Pl/SQL is Oracle only, so it is not portable. I consider stored procedures to be technical debt for that reason.

MS ACCESS application get crashing after applying filter to certain queries

Currently I am developing an Access 2013 based Application for tracking evaluation information of the school students. The database contains only 3 simple tables:
tblSubjects = Contains different subject information
tblStudents = Contains student's personal information
tblMarks = Contains subject wise evaluation marks for each student
and few other queries based on these 3 tables. Now I have a (bit ugly) sql query like following:
SELECT tblStudents.*,
(SELECT COUNT(*) FROM qryPapers WHERE qryPapers.STUDID=tblStudents.STUDID) AS PAPER_COUNT,
(SELECT SUM(MR_TOTAL) FROM qryPapers WHERE qryPapers.STUDID=tblStudents.STUDID) AS ALL_TOTAL,
(SELECT MIN(MR_TOTAL) FROM qryPapers WHERE qryPapers.STUDID=tblStudents.STUDID AND qryPapers.PAPER_TYPE LIKE 'E?') AS MIN_ELEC,
(SELECT COUNT(*) FROM qryPapers WHERE qryPapers.STUDID=tblStudents.STUDID AND qryPapers.PAPER_TYPE LIKE 'A?') AS LANG_PS,
(SELECT COUNT(*) FROM qryPapers WHERE qryPapers.STUDID=tblStudents.STUDID AND qryPapers.PAPER_TYPE LIKE 'E?') AS ELCT_PS,
IIf([PAPER_COUNT]>5,ALL_TOTAL-MIN_ELEC,ALL_TOTAL) AS [GT],
IIf([LANG_PS]=2 And [ELCT_PS]>=3,'PASS','FAIL') AS STATUS
FROM tblStudents;
The Problem is, whenever I try to run a filter on the STATUS field of this query (Like When STATUS='PASS') the entire ACCESS is first STOPES RESPONDING! and then SHUTS DOWN and RESTARTS.
I have no idea what is going on here. I have seen far more complex queries running perfectly well, but not this one. Any help will be appreciated.
I've experienced this a lot in Access. I don't know the cause of the problem but I just export the query to Excel or create a table based on the query to apply filtering.

Strange result in DB2. Divergences queries

A strange thing, that I don't know the cause, is happenning when trying to collect results from a db2 database.
The query is the following:
SELECT
COUNT(*)
FROM
MYSCHEMA.TABLE1 T1
WHERE
NOT EXISTS (
SELECT
*
FROM
MYSCHEMA.TABLE2 T2
WHERE
T2.PRIMARY_KEY_PART_1 = T1.PRIMARY_KEY_PART_2
AND T2.PRIMARY_KEY_PART_2 = T1.PRIMARY_KEY_PART_2
)
It is a very simple one.
The strange thing is, this same query, if I change COUNT(*) to * I will get 8 results and using COUNT(*) I will get only 2. The process was repeated some more times and the strange result is still continuing.
At this example, TABLE2 is a parent table of the TABLE1 where the primary key of the TABLE1 is PRIMARY_KEY_PART_1 and PRIMARY_KEY_PART_2, and the primary key of the TABLE2 is PRIMARY_KEY_PART_1, PRIMARY_KEY_PART_2 and PRIMARY_KEY_PART_3.
There's no foreign key between them (because they were legacy ones) and they have a huge amount of data.
The DB2 query SELECT VERSIONNUMBER FROM SYSIBM.SYSVERSIONS returns:
7020400
8020400
9010600
And the client used is SquirrelSQL 3.6 (without the rows limit marked).
So, what is the explanation to this strange result?
Without the details (including, at least, the exact Db2 version and DDL for both tables and their indexes) it can be just anything, and even with that details only IBM support will be really able to say, what is the actual reason.
Generally this looks like damaged data (e.g. differences in index vs table data).
Worth to open the support case with IBM.

Queries taking too long on ASP.Net application but fine on SQL Server Management studio [duplicate]

I have been having this problem for a couple of weeks now. The problem is that the query takes 4-5 minutes to run on the website and at most 2 or 3 seconds to run in ssms. Also I found that after I make a change to this query like adding the customerId variable it will start running quickly on the web page but by the next day it is slow again. The query in question is this one:
DECLARE #customerID INT
SET #customerID = #CustID
DECLARE #MyTable table(
Iden int NOT NULL IDENTITY(1,1),
ProductID int)
INSERT INTO #MyTable(ProductID)
SELECT P.ProductID FROM Product P WITH (NOLOCK)
left join Compunix_ProductMMY cpmmy with (nolock) on p.ProductID = cpmmy.ProductID
left join Compunix_CustomerMMY ccmmy with (nolock) on ccmmy.mmyid = cpmmy.mmyid
WHERE P.Deleted=0 AND P.Published=1 and (ccmmy.customerid = #customerID OR cpmmy.productid IS NULL)
SELECT c.Name, c.SeName, c.CategoryID
FROM Category c WITH (NOLOCK)
JOIN ProductCategory PC With (NOLOCK) ON C.CategoryID = PC.CategoryID
JOIN #MyTable MT ON PC.ProductID=MT.ProductID
WHERE C.Published = 1
GROUP BY c.Name, c.SeName, c.CategoryID
ORDER BY c.Name
I have the same query running on 2 other site which work just fine. The only difference between the sites is that they are run on different databases and the slow site has a bit more than double the products (54000 products) on it compared to the other 2. All three sites and their databases are hosted on the same machine.
Chances are that you are hitting on a problem with parameter sniffing.
I suggest reading Slow in the Application, Fast in SSMS? by Erland Sommarskog to get a full understanding of the issue (long article but very good).
Take a look at sys.dm_exec_sessions for your ASP.Net application and for your SSMS session. I will hazard a guess that at least one of your SET settings is different. This can contribute to different plans (ultimately this gets attributed to parameter sniffing) and the app side usually ends up worse off.
See these other questions for a lot more details:
Stored procedure slow when called from web, fast from Management Studio
Procedure times out from ADO.NET but not in SSMS
Query times out when executed from web, but super-fast when executed from SSMS
ADO .NET vs. SQL Server Management Studio - ADO performs worse
I had same issue, in my case it was related to MARS, so I removed MultipleActiveResultSets=True; from connection string and now running time btween SSMS and asp.net are almost same (0.2s comparing to 4.5s before)
Note: MARS = Multiple Active Result Sets. If you set this property on a connection string, you can run multiple queries on the same connection in an interleaved fashion. It's mainly intended to permit you to submit UPDATE statements as you are iterating through a result set.
Doing following steps at the same time worked for me.
Try stored procedure recompiling
Clear the plan cache
Updating stats on the DB
For what its worth, very occasionally we run into the same problem; may be once a year. You can spend a good week reading and digesting all of those wonderful resources mentioned in the other answers, or you can do what we do; stop and start SQL Server.
It works a treat.
We have noticed that this problem generally occurs after various schema/sp/view mods that may not be directly related to the problem at hand.
Table Variables and temp tables make a big difference in the query execution
I am not sure why you are using the table variable you can try this code and see if that solves your slowness mystery
DECLARE #customerID INT
SET #customerID = #CustID
SELECT c.Name, c.SeName, c.CategoryID
FROM Category c WITH (NOLOCK)
JOIN ProductCategory PC With (NOLOCK) ON C.CategoryID = PC.CategoryID
JOIN (SELECT P.ProductID FROM Product P WITH (NOLOCK)
left join Compunix_ProductMMY cpmmy with (nolock) on p.ProductID = cpmmy.ProductID
left join Compunix_CustomerMMY ccmmy with (nolock) on ccmmy.mmyid = cpmmy.mmyid
WHERE P.Deleted=0 AND P.Published=1 and (ccmmy.customerid = #customerID OR cpmmy.productid IS NULL)
) MT ON PC.ProductID=MT.ProductID
WHERE C.Published = 1
GROUP BY c.Name, c.SeName, c.CategoryID
ORDER BY c.Name
Are you using any ORM? If you are using NHibernate, you can enable db tracing in NHibernate and see what could be the issue. Following are some of the scenarios that I observed in such scenarios:
implicit conversion which leads to bad plan choice (nvarchar being used instead of varchar). You can observe the NHibernate parameter mapping in its logs.
Lack of index.
NHibernate uses log4net and you just need to add an appender as mentioned here.

Poor SP performance from ASP.NET

I have a stored procedure that handles sorting, filtering and paging (using Row_Number) and some funky trickery :) The SP is running against a table with ~140k rows.
The whole thing works great and for at least the first few dozen pages is super quick.
However, if I try to navigate to higher pages (e.g. head to the last page of 10k) the whole thing comes to a grinding halt and results in a SQL timeout error.
If I run the same query, using the same parms inside studio manager query window, the response is instant irrespective of the page number I pass in.
At the moment it's test code that is simply binding to a ASP:Datagrid in .NET 3.5
The SP looks like this:
BEGIN
WITH Keys
AS (
SELECT
TOP (#PageNumber * #PageSize) ROW_NUMBER() OVER (ORDER BY JobNumber DESC) as rn
,P1.jobNumber
,P1.CustID
,P1.DateIn
,P1.DateDue
,P1.DateOut
FROM vw_Jobs_List P1
WHERE
(#CustomerID = 0 OR CustID = #CustomerID) AND
(JobNumber LIKE '%'+#FilterExpression+'%'
OR OrderNumber LIKE '%'+#FilterExpression+'%'
OR [Description] LIKE '%'+#FilterExpression+'%'
OR Client LIKE '%'+#FilterExpression+'%')
ORDER BY P1.JobNumber DESC ),SelectedKeys
AS (
SELECT
TOP (#PageSize)SK.rn
,SK.JobNumber
,SK.CustID
,SK.DateIn
,SK.DateDue
,SK.DateOut
FROM Keys SK
WHERE SK.rn > ((#PageNumber-1) * #PageSize)
ORDER BY SK.JobNumber DESC)
SELECT
SK.rn
,J.JobNumber
,J.Description
,J.Client
,SK.CustID
,OrderNumber
,CAST(DateAdd(d, -2, CAST(isnull(SK.DateIn,0) AS DateTime)) AS nvarchar) AS DateIn
,CAST(DateAdd(d, -2, CAST(isnull(SK.DateDue,0) AS DateTime)) AS nvarchar) AS DateDue
,CAST(DateAdd(d, -2, CAST(isnull(SK.DateOut,0) AS DateTime)) AS nvarchar) AS DateOut
,Del_Method
,Ticket#
,InvoiceEmailed
,InvoicePrinted
,InvoiceExported
,InvoiceComplete
,JobStatus
FROM SelectedKeys SK
JOIN vw_Jobs_List J ON j.JobNumber=SK.JobNumber
ORDER BY SK.JobNumber DESC
END
And it's called via
sp_jobs (PageNumber,PageSize,FilterExpression,OrderBy,CustomerID)
e.g.
sp_Jobs '13702','10','','JobNumberDESC','0'
Can anyone shed any light on what might be the cause of the dramatic difference in performance between SQL query window and an asp.net page executing a dataset?
Check out the "WITH RECOMPILE" option
http://www.techrepublic.com/article/understanding-sql-servers-with-recompile-option/5662581
I have run into similar problems where the execution plan on stored procedures will work great for a while, but then get a new plan because the options changed. So, it will be "optimized" for one case and then perform "table scans" for another option. Here is what I have tried in the past:
Re-execute the stored procedure to calculate a new execution plan and then keep an eye on it.
Break up the stored procedure into separate stored procedures of each option such that it can be optimized and then the overall stored procedure simply calls each "optimized" stored procedure.
Bring in the records into an object and then perform all of the "funky trickery" in code and then it gives you the option to "cache" the results.
Obviously option #2 and #3 is better than option #1. I am honestly finding option #3 is becoming the best bet in most cases.
I just had another option 4. You could instead of performing your "inner selects" in one query, you could put the results of your inner selects into temporary tables and then JOIN on those results. I would still push for option #3 if possible, but I understand that sometimes you just need to keep working the stored procedure until it "works".
Good luck.

Resources