Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/apache-flex/4.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 server 如何在SQLServer中提高不同查询的性能_Sql Server_Query Performance - Fatal编程技术网

Sql server 如何在SQLServer中提高不同查询的性能

Sql server 如何在SQLServer中提高不同查询的性能,sql-server,query-performance,Sql Server,Query Performance,我有一个查询,目前324条记录只需要10秒,但有任何方法可以提高性能。Ps我对Sql server非常陌生 尝试: 我在SP中使用了SET-NOCOUNT ON,因为我读到它提高了性能,甚至在每个表中都使用了别名。请告诉我可以做些什么来提高它的性能 DECLARE @vRequestedBy VARCHAR(2000) = CASE WHEN @RequestedBy <> '' THEN @RequestedBy END, @vJobType NVARCHAR(2000)

我有一个查询,目前324条记录只需要10秒,但有任何方法可以提高性能。Ps我对Sql server非常陌生

尝试: 我在SP中使用了SET-NOCOUNT ON,因为我读到它提高了性能,甚至在每个表中都使用了别名。请告诉我可以做些什么来提高它的性能

DECLARE @vRequestedBy VARCHAR(2000) = CASE WHEN @RequestedBy <> '' THEN @RequestedBy END,  
   @vJobType NVARCHAR(2000) = CASE WHEN @JobType <> '' THEN @JobType END;  
SELECT  distinct ts.JobID,   
  dbo.TSP_CAT_Category.Category,   
  ts.JobType,   
  dbo.TSP_TSR_JobStatus.JobStatus,   
  dbo.wsm_Contact.Name "ContactName",   
  ts.Created,   
  wb.Name AS BuildingName,   
  ts.Contact,   
 ts.CreatedBy,   
  ts.ContactEmail,   
  dbo.wsm_Contact.TradingAs,  
  --wsm_Contact_User.UserId "RequestedByUserId",  
  c2.Name "RequestedByUser",  
  dbo.wsm_Contact.ContactID  
  FROM   
   dbo.TSP_TSR_Job ts  
  LEFT OUTER JOIN   
   dbo.wsm_Ref_Buildings wb ON ts.BuildingID = wb.BuildingId   
  LEFT OUTER JOIN   
   dbo.wsm_Contact ON ts.TenancyID = dbo.wsm_Contact.ContactID   
  LEFT OUTER JOIN   
   dbo.TSP_TSR_JobStatus ON ts.JobStatusID = dbo.TSP_TSR_JobStatus.JobStatusID   
  LEFT OUTER JOIN   
   dbo.TSP_CAT_Category ON ts.CategoryID = dbo.TSP_CAT_Category.CategoryID  
  LEFT OUTER JOIN   
   dbo.wsm_Contact_User ON UserID = ts.ContactEmail COLLATE SQL_Latin1_General_CP1_CI_AS  
  LEFT OUTER JOIN   
   wsm_Contact c2 ON c2.ContactID = wsm_Contact_User.ContactID  

  WHERE     
   -- JobId criteria  
    (@JobID = 0 OR JobID = @JobId)  

   AND (@TenancyId = '0' OR TenancyId in (select Item from Split_fn(@TenancyID,',')))  

   AND (@TradingAs = '0' OR wsm_Contact.ContactID in (select Item from Split_fn(@TradingAs,',') ))  
   --RequestedBy    
   AND (@vRequestedBy IS NULL OR @vRequestedBy = '0' OR ts.ContactEmail in (Select distinct Email from dbo.wsm_Contact WHere Email in (select Item from Split_fn(@vRequestedBy,',')) ))  
   -- Job Category  
   AND (@CategoryId = '0' OR ts.CategoryID in (select Item from Split_fn(@CategoryId,',') ))  
   -- Contact Id (always filter on this, enough security?!)    
   AND ts.BuildingID IN (SELECT distinct b.BuildingId    
            FROM   
             wsm_ContactSite s   
            INNER JOIN   
             wsm_Contact c ON c.ContactID = s.ContactID  
            INNER JOIN   
             wsm_Ref_Buildings b ON b.SiteId = s.SiteID  
            WHERE   
             c.ContactID = @ContactUserId)  

   AND wsm_Contact.FloorID  IN     (SELECT t.FloorID   
              FROM wsm_Contact_Tenancy t  
             WHERE t.ContactID = @ContactUserId)  

   AND wsm_Contact.OCCPSTAT NOT IN ('I', 'P')  

   AND (@vJobType IS NULL OR ts.JobType in (select Item from Split_fn(@vJobType,',')))  
   AND (ts.Created between @CreatedFrom and DATEADD(DD,1,@CreatedTo))  
   ORDER BY   
    JobID

您可以在查询中为wsm_联系人、TSP_TSR_作业状态、TSP_CAT_类别、wsm_联系人_用户和用户的Alise设置别名

为wsm_Ref_建筑添加聚集索引 把每一个都变成存在 添加选项重新编译,因为您确实需要所有这些ORs 将Split_fn body替换为internet上的代码。此类代码的示例更多,并且附带SQL SERVER函数, 使用SCHEMABINDING选项确保Split_fn是确定性的 试着把所有的缺点都去掉 修复所有关于索引和缺少统计信息(如TSP_CAT_Category表)的警告(至少其中任何一个) 粘贴新的实际执行计划而不是预计执行计划 也许有一天会把所有的PK从字符串转换成整数 IN子查询中的distinct只做无意义的额外排序,对查询逻辑或输出没有影响。最顶端的不同修复了或仍然没有做任何设计糟糕的查询:重复行(如果有)是由错误定义的联接产生的,必须修复,例如外部应用选择顶端1

upd

例如:

->>


Ivan Starostin有一套很好的建议,我不会在这里重复,但是我想请你考虑一下为什么你觉得首先要用不同的方法。 select distinct为查询增加了时间和精力,对于具有多个列的宽查询,尤其是当查询涉及多个联接表时,它不是一种很好的方法。虽然将表连接在一起是司空见惯且必要的,但不要忘记连接通常具有将行数相乘的效果。因此,如果有太多的行,在完全依赖select distinct作为灵丹妙药之前,请重新考虑连接

例如,这是否需要区分

SELECT
    ts.JobID
  , ts.Contact
  , ts.ContactEmail
  , ts.Created
  , ts.CreatedBy
  , ts.JobType
FROM dbo.TSP_TSR_Job ts
WHERE (ts.Created BETWEEN @CreatedFrom AND DATEADD(DD, 1, @CreatedTo))
AND (@JobID = 0 OR ts.JobID = @JobId)
AND (@TenancyId = '0' OR ts.TenancyId IN (
    SELECT
        Item
    FROM Split_fn(@TenancyID, ',')
    )
)
如果我认为不需要distinct,那么将其用作子查询,然后添加其余的表。您还可以合并类别和状态的查找表,而无需添加更多行,例如

SELECT
    ts.JobID
  , ts.Contact
  , ts.ContactEmail
  , ts.Created
  , ts.CreatedBy
  , ts.JobType
  , dbo.TSP_CAT_Category.Category
  , dbo.TSP_TSR_JobStatus.JobStatus
FROM dbo.TSP_TSR_Job ts
LEFT OUTER JOIN dbo.TSP_TSR_JobStatus    ON ts.JobStatusID = dbo.TSP_TSR_JobStatus.JobStatusID
LEFT OUTER JOIN dbo.TSP_CAT_Category     ON ts.CategoryID = dbo.TSP_CAT_Category.CategoryID
WHERE (ts.Created BETWEEN @CreatedFrom AND DATEADD(DD, 1, @CreatedTo))
AND (@JobID = 0 OR ts.JobID = @JobId)
AND (@TenancyId = '0' OR ts.TenancyId IN (
    SELECT
        Item
    FROM Split_fn(@TenancyID, ',')
    )
)
-- Job Category  
AND (@CategoryId = '0'
OR ts.CategoryID IN (
    SELECT
        Item
    FROM Split_fn(@CategoryId, ',')
)
)
AND (@vJobType IS NULL
OR ts.JobType IN (
    SELECT
        Item
    FROM Split_fn(@vJobType, ',')
)
)

如果不需要distinct,则将其作为子查询派生表或公共表表达式使用,然后尝试逐个添加每个附加联接,即添加联接和相关where子句筛选器,并添加此表的选定列。然后,如果在额外连接之后,您开始在结果中看到不需要的重复,那么您就知道重复来自何处。您可能需要对该表采用完全不同的方法来解决此问题,例如,加入一个子查询,该子查询使用行号仅获取最近的联系人。

您的查询非常大,我不确定是否有人能够从堆栈溢出页面整定整个内容。您可能想开始阅读索引和调优之类的内容。首先:您能提供执行计划吗?第二:工作台在哪里发挥作用?是否涉及访问工作表的视图?您的查询至少没有包含任何工作表。第三:ts.ContactEmail整理SQL\u拉丁语1\u常规\u CP1\u CI\u AS可能会执行得非常糟糕,因为这可能涉及转换过程。请确保所有数据具有相同的排序规则。@JosefBiehler也可能是参数嗅探问题。您能显示存储产品的声明吗?您读过以下内容吗:我应该使用什么来代替DistinctEnablencyId EXISTS从拆分中选择项_fn@TenancyID,,,'获取错误指定了一个非布尔类型的表达式,其中需要表达式。该表达式不是有效的语法,并且用法不存在。在答案中添加了示例@nikhiljain
WHERE EXISTS (select 1 from Split_fn(@CategoryId,',') s WHERE s.Item = ts.CategoryID)
SELECT
    ts.JobID
  , ts.Contact
  , ts.ContactEmail
  , ts.Created
  , ts.CreatedBy
  , ts.JobType
FROM dbo.TSP_TSR_Job ts
WHERE (ts.Created BETWEEN @CreatedFrom AND DATEADD(DD, 1, @CreatedTo))
AND (@JobID = 0 OR ts.JobID = @JobId)
AND (@TenancyId = '0' OR ts.TenancyId IN (
    SELECT
        Item
    FROM Split_fn(@TenancyID, ',')
    )
)
SELECT
    ts.JobID
  , ts.Contact
  , ts.ContactEmail
  , ts.Created
  , ts.CreatedBy
  , ts.JobType
  , dbo.TSP_CAT_Category.Category
  , dbo.TSP_TSR_JobStatus.JobStatus
FROM dbo.TSP_TSR_Job ts
LEFT OUTER JOIN dbo.TSP_TSR_JobStatus    ON ts.JobStatusID = dbo.TSP_TSR_JobStatus.JobStatusID
LEFT OUTER JOIN dbo.TSP_CAT_Category     ON ts.CategoryID = dbo.TSP_CAT_Category.CategoryID
WHERE (ts.Created BETWEEN @CreatedFrom AND DATEADD(DD, 1, @CreatedTo))
AND (@JobID = 0 OR ts.JobID = @JobId)
AND (@TenancyId = '0' OR ts.TenancyId IN (
    SELECT
        Item
    FROM Split_fn(@TenancyID, ',')
    )
)
-- Job Category  
AND (@CategoryId = '0'
OR ts.CategoryID IN (
    SELECT
        Item
    FROM Split_fn(@CategoryId, ',')
)
)
AND (@vJobType IS NULL
OR ts.JobType IN (
    SELECT
        Item
    FROM Split_fn(@vJobType, ',')
)
)