【问题标题】:SQL Join taking too much time to runSQL Join 运行时间过长
【发布时间】:2016-06-25 04:41:49
【问题描述】:

下面显示的这个查询需要将近 2 个小时才能运行,我想减少这个查询的执行时间。任何帮助都会对我很有帮助。

目前:

If Exists (Select 1                                
           From PRODUCTS prd                                
           Join STORE_RANGE_GRP_MATCH srg On prd.Store_Range_Grp_Id = srg.Orig_Store_Range_Grp_ID          
                                          And srg.Match_Flag = 'Y'
                                          And prd.Range_Event_Id = srg.LAR_Range_Event_Id
           Where srg.Range_Event_Id Not IN (Select distinct Range_Event_Id
                                            From Last_Authorised_Range)
          )       

我尝试用Not ExistsLeft join 替换Not IN 子句,但运行时执行没有运气。

我用过的:

If Exists(   Select top 1 *                           
      From PRODUCTS prd                               
      Join STORE srg                             
      On  prd.Store_Range_Grp_Id = srg.Orig_Store_Range_Grp_ID                                
      And  srg.Match_Flag  = 'Y'                                
      And  prd.Range_Event_Id = srg.LAR_Range_Event_Id 
and           srg.Range_Event_Id ='45655'        



Where NOT EXISTS (Select top 1 *                                  
       From Last_Authorised_Range where Range_Event_Id=srg.Range_Event_Id)                             
 )  

Product 表有 432837 条记录,Store 表也有几乎相同数量的记录。我在存储过程本身中创建此表,然后将其放在存储过程的最后。

Create Table PRODUCTS                                 
(                                
     Range_Event_Id int,                                 
     Store_Range_Grp_Id int,                                
     Ranging_Prod_No nvarchar(14) collate database_default,
     Space_Break_Code nchar(1) collate database_default
)                     

Create Clustered Index Idx_tmpLAR_PRODUCTS 
   ON PRODUCTS (Range_Event_Id, Ranging_Prod_No, Store_Range_Grp_Id, Space_Break_Code)

我应该在这个表上使用非聚集索引还是我可以做些什么来减少执行时间?提前致谢

【问题讨论】:

  • PRIMARY KEY 中的PRODUCTS 在哪里?
  • Select distinct Range_Event_Id From Last_Authorised_Range 的结果放在一个表变量中,并在上面使用不存在。
  • 删除 top 1 和/或 distinct 子句 - exists()in() 没有这些会更好。您可以使用select * 而不是select 1 - 更好的可读性; SQL 优化器为这些生成相同的查询计划。在所有 ID 字段上创建索引。
  • 尝试将Where srg.Range_Event_Id Not IN (Select distinct Range_Event_Id From Last_Authorised_Range 重写为LEFT OUTER JOIN Last_Authorised_Range ON Range_Event_Id = srg.Range_Event_Id 并更改WHERE 子句WHERE Range_Event_Id IS NULL
  • 你有其他表的索引吗?

标签: sql sql-server sql-server-2005


【解决方案1】:

首先,在existsin 子查询中不需要top 1distinct。但这不应该影响性能。

这是查询,稍微重新排列,以便我更好地理解它:

Select 1                          
From PRODUCTS prd Join
     STORE srg                             
     On prd.Store_Range_Grp_Id = srg.Orig_Store_Range_Grp_ID and
        prd.Range_Event_Id = srg.LAR_Range_Event_Id                             
Where srg.Match_Flag  = 'Y'                                
      srg.Range_Event_Id = 45655 and   
Where NOT EXISTS (Select 1                                
                  From Last_Authorised_Range lar
                  where lar.Range_Event_Id = srg.Range_Event_Id)                             
                 )

请注意,我删除了 45655 周围的双引号。我想这个专栏实际上是一个数字。如果是这样,请不要通过使用字符串进行比较来混淆自己和优化器。

然后,尝试索引。我认为最好的索引是:

  • store(Range_Event_Id, Match_Flag, Orig_Store_Range_Grp_ID, LAR_Range_Event_Id)
  • products(Store_Range_Grp_Id, Range_Event_Id)(或任何以这两列开头的索引,无论是聚集的还是其他的,以任一顺序)
  • Last_Authorised_Range(Range_Event_Id)

根据您所描述的数据量,您的查询不应该花费数小时。我认为索引可以提供帮助。

【讨论】:

  • 我也使用了索引,并通过删除 Not In 子句实现了左外连接,但它仍然需要 2 小时才能运行。
  • 现在我在所有正在使用的表上使用聚集索引,我应该将聚集索引更改为非聚集索引吗?如果是,为什么???
  • @SumitDwivedi 。 . .您是否尝试过此答案中提到的索引?
猜你喜欢
  • 2019-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-22
  • 1970-01-01
  • 1970-01-01
  • 2020-04-16
  • 2018-04-07
相关资源
最近更新 更多