2

次のようにクエリを最適化しようとしています。

SELECT  id, type, parent_id
FROM    [dbo].[v5] with(nolock)
WHERE 
(
    USER_ID() = 1
    OR
        (
            v5.type IN (1,2,3)
            and 
            EXISTS
            (
                    SELECT obj_id FROM dbo.access with(nolock) 
                    where  access.obj_id = id 
                    AND obj_id.[u_name] in 
                    (
                        select SUSER_SNAME() union all 
                        select [name] COLLATE database_default from dbo.u_role
                    )
            )
        )
)

25秒で動作します。この行にコメントすると:

--USER_ID() = 1
 --     OR

それは5秒で動作します。このクエリを最適化するには? where句でUSER_ID()を使用しないようにするには?

4

1 に答える 1

1

これを試してみてください -

バリアント #1:

DECLARE @user INT
SELECT @user = USER_ID() --<--

SELECT 
      v.id
    , v.[type]
    , v.parent_id
FROM dbo.v5 v WITH (NOLOCK)
LEFT JOIN (
    SELECT DISTINCT a.obj_id 
    FROM dbo.access a WITH(NOLOCK) 
    WHERE a.[u_name] IN 
        (
            SELECT SUSER_SNAME() 
            UNION ALL 
            SELECT [name] COLLATE database_default 
            FROM dbo.u_role
        )
) a ON a.obj_id = v.id 
WHERE @user = 1
    OR (
            v5.[type] IN (1, 2, 3) 
        AND 
            a.obj_id IS NOT NULL
    )

バリアント #2:

IF USER_ID() = 1 BEGIN

    SELECT 
          v.id
        , v.[type]
        , v.parent_id
    FROM dbo.v5 v WITH (NOLOCK)

END
ELSE BEGIN

    SELECT 
          v.id
        , v.[type]
        , v.parent_id
    FROM dbo.v5 v WITH (NOLOCK)
    JOIN (
        SELECT DISTINCT a.obj_id 
        FROM dbo.access a WITH(NOLOCK) 
        WHERE a.[u_name] IN 
            (
                SELECT SUSER_SNAME() 
                UNION ALL 
                SELECT [name] COLLATE database_default 
                FROM dbo.u_role
            )
    ) a ON a.obj_id = v.id 
    WHERE v5.[type] IN (1, 2, 3) 

END

バリアント #3:

DECLARE @user INT
SELECT @user = USER_ID()

SELECT  id, [type], parent_id
FROM [dbo].[v5] WITH(NOLOCK)
WHERE @user = 1
    OR (
        v5.[type] IN (1,2,3)
        AND 
        EXISTS (
            SELECT 1 
            FROM dbo.access WITH(NOLOCK) 
            WHERE access.obj_id = id 
                AND access.[u_name] IN 
                    (
                        SELECT SUSER_SNAME() 
                        UNION ALL 
                        SELECT [name] COLLATE database_default 
                        FROM dbo.u_role
                    )
        )
    )
OPTION (RECOMPILE)
于 2013-06-13T07:44:59.607 に答える