代码之家  ›  专栏  ›  技术社区  ›  Paria Molayem

哪个执行计划的性能更好?

  •  2
  • Paria Molayem  · 技术社区  · 10 年前

    (我的英语不够好,所以请容忍我)

    我正在优化此查询:

    Select Title from Groups Where GroupID = WWPMD.GroupID) as GroupName 
    FROM         dbo.Detail AS WWPMD INNER JOIN
                      dbo.News AS WWPMN ON WWPMD.DetailID = WWPMN.NewsID
    WHERE 
    WWPMD.IsDeleted = 0 AND WWPMD.IsEnabled= 1 AND WWPMD.GroupID IN (
    Select ModuleID FROM Page_Content_Item WHERE     ContentID='a6780e80-4ead4e62-9b22-1190bb88ed90')
    

    在这种情况下,表在GUID主键上具有聚集索引。在执行计划中,箭头有点粗,表“detail”的聚集索引查找成本为87%,并且没有键查找成本

    然后,我更改了表“detail”的索引。我在datetime列上放置了聚集索引,在PK和FK上放置了3个非聚集索引。现在在执行计划中,表详细信息的索引查找成本为4%,键查找成本为80%,带有细箭头。

    我想知道哪个执行计划更好,以及我可以做什么来改进这个查询。

    更新:

    感谢大家的指导。还有一个问题。我想知道是聚集索引查找的80%成本更好,还是非聚集索引查找和键查找的80%总成本更好。哪个更好?

    4 回复  |  直到 10 年前
        1
  •  1
  •   LittleDragon    10 年前

    IN语句适用于选择littele位数据,如果您选择的数据较多,则应使用INNER JOIN,对于大数据,其性能优于IN

    IN比DISTINCT上的JOIN更快

    EXISTS比IN更有效,因为“EXISTS只返回一行”

        2
  •  0
  •   Frederik Gheysels    10 年前

    当guid不连续时,guid列上的聚集索引不是一个好主意,因为这会导致插入时的性能损失。表中的记录是基于聚集索引进行物理排序的。聚集索引应放在具有连续值且不经常更改的列上。

    如果在groupid(表组)上有一个非聚集索引,那么可以将“title”作为该索引的包含列。有关包含的列,请参见msdn。

        3
  •  0
  •   mehdi lotfi    10 年前

    我建议使用以下查询:

    INNER JOIN (SELECT DISTINCT ModuleID FROM Page_Content_Item WHERE ContentID='a6780e80-4ead4e62-9b22-1190bb88ed90')z OR WWPMD.GroupID= z.ModuleID
    

    而不是:

    AND WWPMD.GroupID IN (
       Select ModuleID FROM Page_Content_Item WHERE ContentID='a6780e80-4ead4e62-9b22-1190bb88ed90')
    

    还必须是此查询的调查执行计划,似乎索引 Detail.DetailId 带过滤器( IsDeleted = 0 and IsEnable = 1 )非常有用。

        4
  •  0
  •   Dan Guzman    10 年前

    除非在JOIN和/或WHERE子句中指定了最左边的索引列,否则索引不会特别有用。我建议以下索引(尽可能唯一):dbo.Detail(GroupID)、dbo.News(DetailID)、dbo.Page_Content_Item(ContentID)

    您可以使用包含的列和/或筛选器来微调这些索引,但我怀疑如果没有这些度量,性能可能足够好。

    请注意,主键很重要。这不仅是一种设计最佳实践,还将在关键列上自动创建唯一索引,这可以提高相关列上的表连接性能。考虑检查您的模型,以确保您具有正确的主键和关系。