表连接选择性能:从嵌套组中获取成员(大量)

时间:2016-05-31 03:01:38

标签: sql sql-server performance sql-server-2012

我有三个表定义成员和表格的表格。组配置文件如下:

  

[tbMember] (1M记录):MemberID(PK)|会员名称|年龄|性

     

[tbGroup] (10K记录):GroupID(PK)| GroupName | ParentGroupID

     

[tbMemberGrouopRelation] (2M记录):MemberID |的GroupID

组按层次结构排序:

     /--- 2
1 --/---- 3    /--- 5
    \---- 4 --/---- 6
              \---- 7

当我从特定组(及其所有子组)中获取某些成员时,我编写了我的SQL(在SQL Server 2012中):

SELECT m.MemberID, m.MemberName, m.Age, m.Sex
FROM tbMember m
  LEFT JOIN tbMemberGroupRelation mg ON (mg.MemberID = m.MemberID)
WHERE mg.GroupID IN (
    SELECT GroupID FROM FN_GetAllSubgroups(1)
  )
ORDER BY m.MemberID DESC
OFFSET 1000 ROWS FETCH NEXT 40 ROWS ONLY

FN_GetAllSubgroups的实现方式如下:

CREATE FUNCTION [dbo].[GetAllSubgroups] (@parentID int)
RETURNS @t TABLE(GroupID int, ParentID int, GroupName nvarchar(128))
BEGIN
    WITH GroupList 
    AS
    (
        SELECT GroupID, ParentID, GroupName
        FROM dbo.tbGroup
        WHERE GroupID = @parentID UNION ALL
        SELECT a.GroupID, a.ParentID, a.GroupName 
        FROM tbGroup a
            INNER JOIN GroupList b on a.ParentID = b.GroupID
    )
    INSERT INTO @t
    SELECT a.GroupID, a.ParentID, a.GroupName FROM dbo.tbGroup a
        INNER JOIN GroupList b on a.GroupID = b.GroupID
    ORDER BY a.ParentID, a.DisplayOrder
    RETURN
END

GO

-- index on tbGroup is ParentID (INCLUDE[GroupID, GroupName, DisplayOrder])

函数本身处理速度非常快,即使从顶级节点组中选择(返回10k子组),处理时间也在200ms以内

但是,当我选择从特定子组集合中选择成员的表连接选择时,它变得非常慢(查看我的第一个SQL)。我检查了执行计划,它告诉我{t}的Clurster Index Seek占用了97%的时间,Estimate rows = 1actual rows usually >= 20K

是否有任何解决方案可以加快速度?

非常感谢您的帮助!

======================================

更新:执行结果粘贴在

下面
  

(40行受影响)

     

表'_tbMember'。扫描计数0,逻辑读取4679267,物理读取0,预读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。

     

表'_tbMemberGroupRelation'。扫描计数9516,逻辑读取32484,物理读取0,预读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。

     

表'#AC4BBD06'。扫描计数1,逻辑读取51,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。

     

(1行受影响)

     

SQL Server执行时间:

     

CPU时间= 2953 ms,经过时间= 9143 ms。

     

SQL Server解析和编译时间:

     

CPU时间= 0 ms,经过时间= 0 ms。

     

SQL Server执行时间:

     

CPU时间= 0 ms,经过时间= 0 ms。

enter image description here

1 个答案:

答案 0 :(得分:1)

您可以尝试将您的功能转换为iTVF

CREATE FUNCTION [dbo].[GetAllSubgroups] (
    @parentID int
)
RETURNS TABLE
AS
RETURN 

WITH GroupList AS (
    SELECT
        GroupID,
        ParentID,
        GroupName
    FROM dbo.tbGroup
    WHERE GroupID = @parentID
    UNION ALL
    SELECT
        a.GroupID,
        a.ParentID,
        a.GroupName
    FROM tbGroup a
    INNER JOIN GroupList b
        ON a.ParentID = b.GroupID
)
SELECT
    a.GroupID,
    a.ParentID,
    a.GroupName
FROM dbo.tbGroup a
INNER JOIN GroupList b
    ON a.GroupID = b.GroupID