内部查询的sql优化

时间:2013-11-21 12:40:54

标签: sql tsql sql-server-2012

我有一个包含网页的网站,每个网页可能属于几个类别。用户被分配到类别,如果为页面分配了用户所属的类别,则可以看到该页面。

最初每个页面属于一个类别,我可以加入此表并检查权限,如此

where Sec.[level] > 0

既然页面可以有多个类别我试图更改过滤掉结果的SP的where语句,虽然它有效但效率很低。我获得了所有类别的最大权限,如果至少有一个大于零,则授予访问权限

WHERE 
        (

            (TLA.RecipientTypeID = 2 and (SELECT MAX(CAST(dbo.PersonHasPermission_forSection(CS.SectionID, @pViewersID, 1) AS tinyint))
                                          FROM CONTENT_SECTION CS
                                          WHERE CS.ContentID = tla.RecipientID) > 0
            )
            OR
            (TLA.RecipientTypeID <> 2 AND Sec.[level] > 0)
        )

或者因为只有页面有多个猫,其他类型的内容仍然只有一个。

我不知道这里是否有足够的信息,但我们将非常感谢任何优化提示。

2 个答案:

答案 0 :(得分:3)

根据您的WHERE语句,执行缓慢的主要原因是为内部子查询中的每一行调用一个函数。我认为您不应该搜索MAX()并将其与0进行比较,在这种情况下您扫描所有表。而不是尝试使用这样的EXISTS只找到一个权限为&gt; 0的记录 - 它应该是:

and EXISTS(SELECT * FROM CONTENT_SECTION CS 
             WHERE CS.ContentID = tla.RecipientID
             AND 
            (CAST(dbo.PersonHasPermission_forSection(CS.SectionID, @pViewersID, 1) 
                       AS tinyint)>0)
           ) 

答案 1 :(得分:1)

如果您的效率低下,通常会重复调用函数。有时通过消除对函数的多次调用可以获得很大的效率提升。一种方法是使用临时表。所以,这可能是值得探讨的事情。

但是,我想从您的特定SQL退一步,因为我认为数据建模和方法可能存在潜在问题。按照你所描述的情况:

  

我有一个包含网页的网站,每个网页可能属于几个类别。   用户被分配到类别,并且如果页面已分配了   用户所属的类别,他们可以看到该页面。

这种情况的最佳数据模型是三个“实体”表(类别,用户和页面),它们之间具有多对多关系;多对多关系意味着要加入两个额外的表(UserCategory和PageCategory):

Example database structure with 5 tables

在这种情况下,要获取特定用户可以看到的所有页面的列表,您可以使用类似此示例的查询(这非常有效):

SELECT p.*
FROM UserCategory uc
  INNER JOIN PageCategory pc ON uc.CategoryID = pc.CategoryID
  INNER JOIN Page p ON pc.PageID = p.PageID
WHERE uc.UserID = @pViewersID

这是半笛卡尔式连接,但在这种情况下,这就是你想要的。另请注意,为了使给定的示例查询具有最佳的SELECT效率,您还需要UserCategory.UserID上的索引。

最后,我删除了[Level]列,因为它似乎只用于真/假检查(“大于0”),这已经由UserCategory中的row-exists-or-not处理。但是,如果您确实需要多个权限级别(超过0或1),请注意您还可以在UserCategory中包含[Level]列,并在示例查询中引用它以获得最低的额外成本。

相关问题