SQL view takes long time to finish, but the same internal query executes in 1 second - sql

I am facing a weird experience with a query which is for handling data from ADO. Here is the view
ALTER view [dbo].[v_Missing_Pepics] as
select ProjectName Title,PM.ProjectCode,LifeCycle,dbo.fn_kip_ado_status_mapping(LifeCycle,PM.ProjectCode) KipStatus,TeamCode,ISNULL((select top 1 value from string_split(TA.AreaPath,'\') where LTRIM(value) like 'Domain%'),'Automation') Domain,DM.DomainName KipDomain,TeamName
from [dbo].[v_ProjectMaster_Latest] PM
left outer join areapath_mapping TA on TA.KeyedInTeamCode=PM.TeamCode
left join v_portfolio_epics PE on PE.ProjectCode=PM.ProjectCode
inner join domain_master DM on DM.DomainCode=PM.DomainCode
where ProjectActive = 'yes' and LifeCycle not in ('In Close-Down', 'Completed','Withdrawn')
and PE.ProjectCode is null and DM.DomainName not in ('Data Power') and PM.ProjectCode not like 'EXP%'
GO
When I try to execute the query like this
Select * from v_Missing_Pepics
It took more than 80sec to finish. But when I copy the query alone (Within the view), it executes in just 1 second.
I don't understand why??
I am working in Azure SQL.

Try
sp_recompile 'v_Missing_Pepics'
And see if that resolves the performance problems with the view.

Related

Why does a query joining several views take 10x as long as running the views individually?

I need some help optimising a query which is looks simple of the face of it, but is blowing up my DB.
The objective is to produce an output file to update a website, but creating a single view (View_1) which combines the central index table (list_1) with the results of several other views (View_2_1 through View_2_8). My stored procedure is design to run View_1, select the records which need to be updated and drop them into a static table where they can picked up by an automated process (which only needs to run 1 line of code and will be well within the timeout limit).
After adding all suggested missing indexes to target tables, when I
run View 2_1 through View 2_8 individually they take between 3” and
39” to resolve.
When I run the code for View 1 in isolation it takes
21 mins.
When I ran the stored procedure to run view 1 this morning, it
took over an hour!
Can anyone see anything obvious in the below that may be adding to the query cost?
View 1 code:
Edit: Select distinct appears to be the issue here. Objective is to pick up a unique row for every unique value in the "article" column. Those values should only appear once in each table and view.
select distinct article, publisher, /*[list required columns 1 -40 from each table and view, correcting null values to ‘-’ where required.]*/
from list_1 as l1
left join list_2 as l2 on
l1.publisher=l2.publisher
left join view_2_1 as v21 on
l1.article=v21.article
left join view_2_2 as v22
l1.article=v22.article
left join view_2_3 as v23
l1.article=v23.article
left join view_2_4 as v24
l1.article=v24.article
left join view_2_5 as v25
l1.article=v25.article
left join view_2_6 as v26
l1.article=v26.article
left join view_2_7 as v27
l1.article=v27.article
left join view_2_8 as v28
l1.article=v28.article
The stored procedure is
drop table if exists todays_export_articles;
select *
into todays_export_articles
from import_procedure /* ie code above */
/* Select latest and discard invalid records */
where [type]='article' and [status]='pending' and important_column_1 is not null and important_column_2 is not null and important_column_3 is not null;
update list_1
set [status]='published'
from todays_export_articles as ta inner join list_1 as l1
on ta.article=l1.article

How to change query status from suspended to runnable?

I have a query that needs to update 2 million records but there is no space in the disk, so the query is suspended right now. After that, I free up some space, but the query is still in suspended. So how should I change the status to Runnable or is there any way to tell sql server that you have enough space right now, and you can run the query.
After that, I free up some space, but the query is still in suspended.is there any way to tell sql server that you have enough space right now, and you can run the query.
SQLSERVER will change the query status from suspended to runnable automatically,it is not managed by you..
Your job here is to check ,why the query is suspended..Below dmvs can help
select session_id,blocking_session_id,wait_resource,wait_time,
last_wait_type from sys.dm_exec_requests
where session_id=<< your session id>>
There are many reasons why a query gets suspended..some of them include locking/blocking,rollback,getting data from disk..
You will have to check the status as per above dmv and see what is the reason and troubleshoot accordingly..
Below is some sample piece of code which can help you in understanding what suspended means
create table t1
(
id int
)
insert into t1
select row_number() over (order by (select null))
from
sys.objects c
cross join
sys.objects c1
now in one tab of ssms:
run below query
begin tran
update t1
set id=id+1
Open another tab and run below query
select * from t1
Now open another tab and run below query
select session_id,blocking_session_id,wait_resource,wait_time,
last_wait_type,status from sys.dm_exec_requests
where session_id=<< your session id of select >>
or run below query
select session_id,blocking_session_id,wait_resource,wait_time,
last_wait_type,status from sys.dm_exec_requests
where blocking_session_id>0
You can see status as suspended due to blocking,once you clear the blocking(by committing transaction) , you will see sql server automatically resumes suspended query in this case

SQL Server 2012 query blocked with LCK_M_IS

I'm struggling to understand how the following two queries could be blocking each other.
Running query (could be almost anything though):
insert bulk [Import].[WorkTable] ...
I'm trying to run the following SELECT query at the same time:
SELECT *
FROM ( SELECT * FROM #indexPart ip
JOIN sys.indexes i (NOLOCK)
ON i.object_id = ip.ObjectId
and i.name = ip.IndexName) i
CROSS
APPLY sys.dm_db_index_physical_Stats(db_id(), i.object_id,i.index_id,NULL,'LIMITED') ps
WHERE i.is_disabled = 0
The second query is blocked by the first query and shows a LCK_M_IS as wait info. Import information is that the temporary table #indexPart contains one record of an index on a completely different table. My expectation is that the cross apply tries to run the stats on that one index which has nothing to do with the other query running.
Thanks
EDIT (NEW):
After several more tests I think I found the culprit but again can't explain it.
Bulk Insert Session has an X lock on table [Import].[WorkTable]
The query above is checking for an Index on table [Import].[AnyOtherTable] BUT is requesting an IS lock on [Import].[WorkTable]. I've verified again and again that the query above (when running the stuff without cross apply) is only returning an index on table [Import].[AnyOtherTable].
Now here comes the magic, changing the CROSS APPLY to an OUTER APPLY runs through just fine without any locking issues.
I hope someone can explain this to me ...
The problem could be at the where clause you used. It should be within the inline table. The following change could make a difference.
FROM ( SELECT * FROM #indexPart ip
JOIN sys.indexes i (NOLOCK)
ON i.object_id = ip.ObjectId
and i.name = ip.IndexName
WHERE i.is_disabled = 0) i
If you do like so, this may reduce the number of records passed onto the cross apply statement.

long running sp

The following sp:
I have a stored procedure which runs anywhere from 1/2 minute to 4 hours (during nightly processing):
update tableA
set tableA.Other_Flag_50 = isnull(Staging.other_flag_50, 0)
from tableA
inner join (
select acct_nbr,
appl_code,
Other_Flag_50
from tableB
) Staging on tableA.lnhist_acct_nbr = Staging.acct_nbr
and tableA.lnhist_appl_code = Staging.appl_code
I ran Blocking reports in Profiler for 2 nights in a row, first at 10 minutes interval then at 5 minutes. The stored procedure never shows up as being blocked (but it blocks other queries).
Any ideas on optimizing this? Would creating a view with the join help? (acct_nbr, appl_code, Other_Flag_50 from tableB) Thanks!!
Have you tried doing the INNER JOIN directly to tableB?
UPDATE tableA
SET tableA.Other_Flag_50=isnull(tableB.other_flag_50,0)
FROM tableA
INNER JOIN tableB
ON tableA.lnhist_acct_nbr = tableB.acct_nbr
AND tableA.lnhist_appl_code = tableB.appl_code
Try using rowlock to prevent locking a whole table.
update tableA with (rowlock)
...
EDIT
Not sure about other RDBMS but the answer I provided works for SQL Server

SQL Alias vs dbo.prefix - query performance

Assuming you're using MS SQL Server:
Which of these queries will execute the fastest, and WHY?
I'm going to guess the last, as I'm thinking that Aliases are only resolved to their tables once?
SELECT Account.AccountName,
AccountStatus.AccountState
FROM
dbo.Account
INNER JOIN dbo.AccountStatus ON Account.AccountStatusID = AccountStatus.AccountStatusID
GO
SELECT dbo.Account.AccountName,
dbo.AccountStatus.AccountState
FROM
dbo.Account
INNER JOIN dbo.AccountStatus ON dbo.Account.AccountStatusID = dbo.AccountStatus.AccountStatusID
GO
SELECT A.AccountName,
AST.AccountState
FROM
dbo.Account AS A
INNER JOIN dbo.AccountStatus AS AST ON A.AccountStatusID = AST.AccountStatusID
GO
They will be exactly the same in execution terms
The compile time differences won't be measurable
The 3rd form is the most readable
The 2nd form bloats the query
The 1st form bloats the query and is the most confusing