One of our developers are trying to run the below query on a development server, which involves pulling data from a linked server, production. The query ran for more than 14 hours before it was stopped.
I looked at the execution plan in SQL Sentry Plan Explorer - please find the execution plan below.
How can this query be tuned for better performance? Are there any glaring errors in the query? Are there any pointers, blogs posts that will help me improve this query?
Both the servers involved are SQL Server 2005
SELECT A.SETID
,A.CUST_ID
,A.CNTCT_SEQ_NUM
,A.NAME1
,A.TITLE
,C.DESCR
FROM PS_CUST_CONTACT A
,[linksrv].[prodDB].dbo.PS_BO_ROLE Z
,[linksrv].[prodDB].dbo.PS_RD_PERSON B
,[linksrv].[prodDB].dbo.PS_BO_ROLE_TYPE C
WHERE Z.BO_ID = B.BO_ID
AND Z.ROLE_TYPE_ID = C.ROLE_TYPE_ID
AND Z.ROLE_END_DT >= GETDATE()
AND A.EFFDT = (
SELECT MAX(EFFDT)
FROM PS_CUST_CONTACT CUST_CONTACT
WHERE CUST_CONTACT.SETID = A.SETID
AND CUST_CONTACT.CUST_ID = A.CUST_ID
AND CUST_CONTACT.CNTCT_SEQ_NUM = A.CNTCT_SEQ_NUM
AND CUST_CONTACT.EFFDT <= { FN CURDATE() }
)
AND A.EFF_STATUS = 'A'
AND B.PERSON_ID IN (
SELECT A1.PERSON_ID
FROM PS_CONTACT A1
,PS_CONTACT_CUST B1
WHERE A1.EFFDT = (
SELECT MAX(A_ED.EFFDT)
FROM PS_CONTACT A_ED
WHERE A1.SETID = A_ED.SETID
AND A1.CONTACT_ID = A_ED.CONTACT_ID
AND A_ED.EFFDT <= SUBSTRING(CONVERT(CHAR, GETDATE(), 121), 1, 10)
)
AND A1.SETID = B1.SETID
AND A1.CONTACT_ID = B1.CONTACT_ID
AND B1.EFFDT = (
SELECT MAX(B_ED.EFFDT)
FROM PS_CONTACT_CUST B_ED
WHERE B1.SETID = B_ED.SETID
AND B1.CONTACT_ID = B_ED.CONTACT_ID
AND B_ED.EFFDT <= A.EFFDT
)
AND A.CNTCT_SEQ_NUM = B1.CNTCT_SEQ_NUM
AND A.SETID = B1.CUSTOMER_SETID
AND A.CUST_ID = B1.CUST_ID
)

Aand the other tables involved.