I can't get Oracle execution plan in prod database - database

I'm connecting to a production database with a read-only separate account (no DBA privileges), and I can't get the execution plan for a query. When I try:
explain plan for
select * from my_table where id = 10;
select plan_table_output from
table(dbms_xplan.display('plan_table',null,'typical'));
I get different plans for unrelated queries every time. I guess there are so many queries per second that the plan gets immediately replaced by other ones.
Then, I tried adding a "statement ID":
explain plan set statement_id = 'st1' for
select * from my_table where id = 10;
select plan_table_output from
table(dbms_xplan.display('plan_table','st1','typical'));
but I get the error:
Error: cannot fetch plan for statement_id 'st1'
What's the easiest and consistent way of retrieving an execution plan in a highly concurrent db?

This is late but I found this via an internet search on the error. First issue is the explain itself fails because is invalid. With a short query like the above you would see the error but on a longer query where you script the explains and query you might miss the error messages. Second, set serveroutput being on or your disabling it between the explain and results query will block getting the results. Hope this helps somebody.

Related

How do I test whether a Python SQL query worked if it's not supposed to return anything?

I read an excellent post here about error handling. Error handling in Python-MySQL
And there are a thousand similar questions from people with problems where their query isn't returning anything - but that's because it's supposed to.
I have a slightly different problem.
I have a SQL Query which is designed to transform creating a new table.
SELECT *
INTO MyDataBase.MySchema.NewTable
FROM
(SELECT
ID,
Count(*) AS ProductCount
FROM
MyDataBase.MySchema.MyTable
GROUP BY
ID
) ProductCount
If I run the query in SSMS it works perfectly and SSMS simply tells me
(1901 rows affected)
Completion time: 2021-12-07T09:28:32.2541722+13:00
But after I deliberatly mis-edit the code, and try running the query from a pyhon script just gives me a vague result with no indicaton that the script didn;t actually work.
row = curs.fetchone()
pyodbc.ProgrammingError: No results. Previous SQL was not a query.
So... How do I check that the tranform, the SQL query, ran successfully, even if it's not supposed to return any results... from python?
I know it didn't.
fetchone() is to return rows if there are outputs. You don't need it in your case.
Any DDL statements you can run by just using cursor.execute('drop table..'). There is no way to know for sure if it worked actually, but if it didn't error out then it was successful. You can have additional checks to be sure based on scenario.
Also don't forget to do a cursor.commit() in the end, else it won't commit all your statements.

How to track which query in the corresponding stored procedure is executing

Our team has assigned a new task to me to look into the performance of a huge stored procedure. When I observe in the development environment with the proper data I have noticed that the procedure takes a considerable time to execute. In my scenario it took around 45 minutes. There are multiple INSERT/DELETE/UPDATE queries are used in the stored procedure. But I am unable to get which query is causing the issue. The data volume which is used in the queries are also pretty less.
How can I pinpoint to the exact query in the stored procedure
which is getting executed?
My Server version is SQL Server 2008 R2.
There are couple of ways to find out the query which is executing as part of a stored procedure. Learn more about DMVs and SQL Profiler. Both will give you an oversight to pinpoint the queries that are being used in a stored procedure.
In SQL Profiler, use the SP:StmtCompleted or SP:StmtStarting to include the statements inside the query. But I would advice not to go with the Profiler as it affects the system memory as well. Also it may give you unwanted additional information as well.
The best way is to use DMV (Dynamic Management Views). If you know the process id (SPID) use the below query to find out the query
The first query will give you the details about the stored procedures and the second will give you the exact query which is currently executing. Replace the SPID in the below query with the corresponding SPID of your process.
SELECT requests.session_id,
requests.status,
requests.command,
requests.statement_start_offset,
requests.statement_end_offset,
requests.total_elapsed_time,
details.text
FROM sys.dm_exec_requests requests
CROSS APPLY sys.dm_exec_sql_text (requests.sql_handle) details
WHERE requests.session_id = SPID
ORDER BY total_elapsed_time DESC
SELECT SUBSTRING(detail.text,
requests.statement_start_offset / 2,
(requests.statement_end_offset - requests.statement_start_offset) / 2)
FROM sys.dm_exec_requests requests
CROSS APPLY sys.dm_exec_sql_text (requests.sql_handle) detail
WHERE requests.session_id = SPID
Once you have done identifying the queries which is causing slowness, you can use Actual execution plan to identify the issues in the query.
Try this and please comment whether it is working for you.

NHibernate.Exceptions.GenericADOException Timeout from code but not from DB

I have an NHibernate Query (which is populating an EXTJS grid)
It's firing 2 queries off to the database, one to get the record count (for paging purposes) and the other to get the top N rows to fill the grid with.
From code, I'm consistently getting an exception on the Select count(*) statement.
NHibernate.Exceptions.GenericADOException:
Failed to execute multi criteria[SQL:
SELECT count(*) as y0_ FROM RecordView this_ inner join ProcessesView
process1_ on this_.ProcessId=process1_.Id inner join BusinessModelsView
businessmo3_ on process1_.BusinessModelId=businessmo3_.Id inner join BatchesView
batch2_ on this_.BatchId=batch2_.Id WHERE this_.ProcessId = ?;
] ---> System.Data.SqlClient.SqlException: Timeout expired.
The timeout period elapsed prior to completion of the operation or the server
is not responding.
However if I take that exact query and drop it into an SSMS window, and run it, it executes in a <1 second.
Is NHibernate doing anything "funny" under the hood here. Are there execution plan/cache issues. I'm at a complete loss as to why this is occurring.
Whenever I encountered this error, the reason was locking (never performance). There was two sessions opened (accidently). Both started transaction and one of them locked the table.
The problem could be some not disposed session, or "unintended" singleton... holding opened session.
This answer is not as straigth forward as I wish, but I am sure about the direction. Because I experienced the same (and was guilty)
BTW: as Oskar Berggren found out from you, 30 secods timeout would be related to the <property name="command_timeout">30</property>. I am sure, if you will provide 60, 120 ... it will be not enough because of lock
Your two queries are not handled in the same way by SQL SERVER
your NH query has been compiled on its first execution, based on table statistics and on the first value of the parameter. The generated query plan will then be used for all subsequent calls, witout considering the parameter value
your SQL query (where, I guess, you replace the ? with an actual value) gets a different compilation for each value, based on statistics, and on the value.
Your first NH compilation might have produced a query plan, effective for the first value, but not in the general case.
First, I would suggest that :
you count on a projection (say on the main table id), as it is slightly more effective than count(*), allowing the DB to work only on indexes when possible
you check that you don't miss any index necessary to your query
you check that all your table statistics are up to date
If this does not improve execution time, this post offers some options (recompile might be the good one) :
Query executed from Nhibernate is slow, but from ADO.NET is fast

SQL server query processor ran out of internal resources

Query:
update mytable
set mycol = null
where id in (
583048,
583049,
... (50000 more)
)
Message:
The query processor ran out of internal resources and could not
produce a query plan. This is a rare event and only expected for
extremely complex queries or queries that reference a very large
number of tables or partitions. Please simplify the query. If you
believe you have received this message in error, contact Customer
Support Services for more information.
My query is very simple,
how should I write it so it works ok?
Insert the list of values into a #temp table then use in on that.
As explained in this answer a large number of IN values can cause it to run out of stack as they get expanded to OR
See also related connect item
If you find this error in SQL Server 2016 or later then try to change the database compatibility level to a lower version 120 or 110, etc. (link)

how can I test performance in Sql Server Mgmt Studio without outputting data?

Using SQL Server Management Studio.
How can I test the performance of a large select (say 600k rows) without the results window impacting my test? All things being equal it doesn't really matter, since the two queries will both be outputting to the same place. But I'd like to speed up my testing cycles and I'm thinking that the output settings of SQL Server Management Studio are getting in my way. Output to text is what I'm using currently, but I'm hoping for a better alternative.
I think this is impacting my numbers because the database is on my local box.
Edit: Had a question about doing WHERE 1=0 here (thinking that the join would happen but no output), but I tested it and it didn't work -- not a valid indicator of query performance.
You could do SET ROWCOUNT 1 before your query. I'm not sure it's exactly what you want but it will avoid having to wait for lots of data to be returned and therefore give you accurate calculation costs.
However, if you add Client Statistics to your query, one of the numbers is Wait time on server replies which will give you the server calculation time not including the time it takes to transfer the data over the network.
You can SET STATISTICS TIME ON to get a measurement of the time on server. And you can use the Query/Include Client Statistics (Shift+Alt+S) on SSMS to get detail information about the client time usage. Note that SQL queries don't run and then return the result to the client when finished, but instead they run as they return results and even suspend execution if the communication channel is full.
The only context under which a query completely ignores sending the result packets back to the client is activation. But then the time to return the output to the client should be also considered when you measure your performance. Are you sure your own client will be any faster than SSMS?
SET ROWCOUNT 1 will stop processing after the first row is returned which means unless the plan happens to have a blocking operator the results will be useless.
Taking a trivial example
SELECT * FROM TableX
The cost of this query in practice will heavily depend on the number of rows in TableX.
Using SET ROWCOUNT 1 won't show any of that. Irrespective of whether TableX has 1 row or 1 billion rows it will stop executing after the first row is returned.
I often assign the SELECT results to variables to be able to look at things like logical reads without being slowed down by SSMS displaying the results.
SET STATISTICS IO ON
DECLARE #name nvarchar(35),
#type nchar(3)
SELECT #name = name,
#type = type
FROM master..spt_values
There is a related Connect Item request Provide "Discard results at server" option in SSMS and/or TSQL
The best thing you can do is to check the Query Execution Plan (press Ctrl+L) for the actual query. That will give you the best guesstimate for performance available.
I'd think that the where clause of WHERE 1=0 is definitely happening on the SQL Server side, and not Management Studio. No results would be returned.
Is you DB engine on the same machine that you're running the Mgmt Studio on?
You could :
Output to Text or
Output to File.
Close the Query Results pane.
That'd just move the cycles spent on drawing the grid in Mgmt Studio. Perhaps the Resuls to Text would be more performant on the whole. Hiding the pane would save the cycles on Mgmt Studio on having to draw the data. It's still being returned to the Mgmt Studio, so it really isn't saving a lot of cycles.
How can you test performance of your query if you don't output the results? Speeding up the testing is pointless if the testing doesn't tell you anything about how the query is going to perform. Do you really want to find out this dog of a query takes ten minutes to return data after you push it to prod?
And of course its going to take some time to return 600,000 records. It will in your user interface as well, it will probably take longer than in your query window because the info has to go across the network.
There is a lot of more correct answers of answers but I assume real question here is the one I just asked myself when I stumbled upon this question:
I have a query A and a query B on the same test data. Which is faster? And I want to check quick and dirty. For me the answer is - temp tables (overhead of creating temp table here is easy to ignore). This is to be done on perf/testing/dev server only!
Query A:
DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS (to clear statistics
SELECT * INTO #temp1 FROM ...
Query B
DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS
SELECT * INTO #temp2 FROM ...

Resources