Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL长时间运行查询/最大化服务器资源,如RAM/CPU_Sql_Sql Server_Database_Common Table Expression_Sqlperformance - Fatal编程技术网

SQL长时间运行查询/最大化服务器资源,如RAM/CPU

SQL长时间运行查询/最大化服务器资源,如RAM/CPU,sql,sql-server,database,common-table-expression,sqlperformance,Sql,Sql Server,Database,Common Table Expression,Sqlperformance,我最初发布了以下帖子 我的问题是我的查询的可搜索性,在前面的线程中已经解决了这个问题,但简言之,我使用了很多ISNULL函数,这些函数绕过了索引扫描,我现在遇到了更多的问题 我的SQL server设置如下所示: 并行性的成本阈值 五, 最大平行度 0 我的查询仍然需要2:13才能运行,并导致CPU/内存峰值,我有一个功能强大的服务器,例如64GB RAM,因此资源不是问题。请参阅下面的查询: WITH CTE AS ( SELECT R.Id AS ResultId,

我最初发布了以下帖子

我的问题是我的查询的可搜索性,在前面的线程中已经解决了这个问题,但简言之,我使用了很多ISNULL函数,这些函数绕过了索引扫描,我现在遇到了更多的问题

我的SQL server设置如下所示:

并行性的成本阈值 五,

最大平行度 0

我的查询仍然需要2:13才能运行,并导致CPU/内存峰值,我有一个功能强大的服务器,例如64GB RAM,因此资源不是问题。请参阅下面的查询:

WITH CTE AS 
(
    SELECT R.Id AS ResultId,
        r.JobId,
        r.CandidateId,
        R.Email,
        CAST(0 AS BIT) AS EmailSent,
        NULL AS EmailSentDate,
        'PICKUP' AS EmailStatus,
        GETDATE() AS CreateDate,
        C.Id AS UserId,
        C.Email AS UserEmail,
        NULL AS Subject
    FROM RESULTS R
    INNER JOIN JOB J ON R.JobId = J.Id
    INNER JOIN Consultant C ON J.UserId = C.Id
    WHERE 
        J.DCApproved = 1
        AND (J.Closed = 0 OR J.Closed IS NULL)
        AND (R.Email <> '' OR R.Email IS NOT NULL)
        AND (R.EmailSent = 0 OR R.EmailSent IS NULL)
        AND R.EmailSentDate IS NULL -- email has not been sent
        AND (R.EmailStatus = '' OR R.EmailStatus IS NULL)
        AND (R.IsEmailSubscribe = 'True' OR R.IsEmailSubscribe IS NULL)
        -- not already been emailed for this job
        AND NOT EXISTS (
            SELECT SMTP.Email
            FROM SMTP_Production SMTP
            WHERE SMTP.JobId = R.JobId AND SMTP.CandidateId = R.CandidateId
        )
        -- not unsubscribed
        AND NOT EXISTS (        
            SELECT u.Id FROM Unsubscribe u
            WHERE (u.EmailAddress = R.Email OR (u.EmailAddress IS NULL AND R.Email IS NULL)) 
        )
        AND NOT EXISTS (
            SELECT SMTP.Id FROM SMTP_Production SMTP
            WHERE SMTP.EmailStatus = 'PICKUP' AND SMTP.CandidateId = R.CandidateId
        )   
        AND C.Id NOT IN (
            -- LIST OF IDS
        )
        AND J.Id NOT IN (
            -- LIST OF IDS
        )
        AND J.ClientId NOT IN 
        (
            -- LIST OF IDS
        )
)

SELECT 
    CTE.ResultId,
    CTE.JobId,
    CTE.CandidateId,
    CTE.Email,
    CTE.EmailSent,
    CTE.EmailSentDate,
    CTE.EmailStatus,
    CTE.CreateDate,
    CTE.UserId,
    CTE.UserEmail,
    NULL
FROM CTE
  INNER JOIN 
    (
        SELECT *, row_number() over(partition by CTE.Email, CTE.CandidateId order by CTE.EmailSentDate desc) as rn
        FROM CTE

    ) DCTE ON CTE.ResultId = DCTE.ResultId AND DCTE.rn = 1

我有一些减少执行时间的建议:

如果主记录的电子邮件为空,则无需运行子查询: 因此,与其说这句话,不如说:

AND NOT EXISTS (        
            SELECT u.Id FROM Unsubscribe u
            WHERE (u.EmailAddress = R.Email OR (u.EmailAddress IS NULL AND R.Email IS NULL)) 
        )
 AND (NOT EXISTS (        
            SELECT u.Id FROM Unsubscribe u
            WHERE u.EmailAddress = R.Email ) 
        ) or  R.Email IS NULL) -- you dont need to check is it is null 
使用以下语句:

AND NOT EXISTS (        
            SELECT u.Id FROM Unsubscribe u
            WHERE (u.EmailAddress = R.Email OR (u.EmailAddress IS NULL AND R.Email IS NULL)) 
        )
 AND (NOT EXISTS (        
            SELECT u.Id FROM Unsubscribe u
            WHERE u.EmailAddress = R.Email ) 
        ) or  R.Email IS NULL) -- you dont need to check is it is null 
我建议您尽量减少或表示法,请尝试使用union而不是or。您可以在以下链接中找到一些示例:

据我所知,您可以使用JOBID筛选SMTP_生产记录,如果您可以这样做: 而不是这句话

 AND NOT EXISTS (
            SELECT SMTP.Id FROM SMTP_Production SMTP
            WHERE SMTP.EmailStatus = 'PICKUP' AND SMTP.CandidateId = R.CandidateId -- can we add SMTP.JobId = R.JobId
        ) 
你可以在下面使用

 AND NOT EXISTS (
            SELECT SMTP.Id FROM SMTP_Production SMTP
            WHERE SMTP.EmailStatus = 'PICKUP' AND SMTP.CandidateId = R.CandidateId and SMTP.JobId = R.JobId 
        ) 
查询的最终版本可能如下所示:

WITH CTE AS 
(
    SELECT R.Id AS ResultId,
        r.JobId,
        r.CandidateId,
        R.Email,
        CAST(0 AS BIT) AS EmailSent,
        NULL AS EmailSentDate,
        'PICKUP' AS EmailStatus,
        GETDATE() AS CreateDate,
        C.Id AS UserId,
        C.Email AS UserEmail,
        NULL AS Subject
    FROM RESULTS R
    INNER JOIN JOB J ON R.JobId = J.Id
    INNER JOIN Consultant C ON J.UserId = C.Id
    WHERE 
        J.DCApproved = 1
        AND (J.Closed <> 1)
        AND (R.Email <> '' OR R.Email IS NOT NULL)
        AND (R.EmailSent <> 1)
        AND R.EmailSentDate IS NULL -- email has not been sent
        AND (R.EmailStatus = '' OR R.EmailStatus IS NULL)
        AND (R.IsEmailSubscribe <> 'False')
        -- not already been emailed for this job
        AND NOT EXISTS (
            SELECT SMTP.Email
            FROM SMTP_Production SMTP
            WHERE SMTP.JobId = R.JobId AND SMTP.CandidateId = R.CandidateId
        )
        -- not unsubscribed
          AND ((NOT EXISTS (        
            SELECT u.Id FROM Unsubscribe u
            WHERE u.EmailAddress = R.Email ) 
        ) or  R.Email IS NULL) )
         AND NOT EXISTS (
            SELECT SMTP.Id FROM SMTP_Production SMTP
            WHERE SMTP.EmailStatus = 'PICKUP' AND SMTP.CandidateId = R.CandidateId and SMTP.JobId = R.JobId 
        ) 
        AND C.Id NOT IN (
            -- LIST OF IDS
        )
        AND J.Id NOT IN (
            -- LIST OF IDS
        )
        AND J.ClientId NOT IN 
        (
            -- LIST OF IDS
        )
)

SELECT 
    CTE.ResultId,
    CTE.JobId,
    CTE.CandidateId,
    CTE.Email,
    CTE.EmailSent,
    CTE.EmailSentDate,
    CTE.EmailStatus,
    CTE.CreateDate,
    CTE.UserId,
    CTE.UserEmail,
    NULL
FROM CTE
  INNER JOIN 
    (
        SELECT *, row_number() over(partition by CTE.Email, CTE.CandidateId order by CTE.EmailSentDate desc) as rn
        FROM CTE

    ) DCTE ON CTE.ResultId = DCTE.ResultId AND DCTE.rn = 1

不看执行计划,我喜欢3-可以为一个完全不同的计划在查询中排名靠前。2应该是不相关的查询优化器-可能会怀疑这是否没有优化。1也可能很好。这是真的,最好的方法是使用联合,而不是“或”我正在将此添加到我的答案中。谢谢你,我将尝试这些并报告回来,再次感谢。由于业务规则,我无法执行第3条建议,但添加此项确实会产生不错的影响,我执行了更改1,它有一个小的改进,感谢再次使用计算列建立关系总是很慢。您是否可以考虑将具有RoWo编号列的CTE表写入临时表中,并在查询中使用此临时表?