Query running longer by adding unused WHERE conditions

后端 未结 3 1498
温柔的废话
温柔的废话 2021-01-03 15:20

I\'ve hit an interesting snag (interesting to me at least). Below is a general idea of what my query looks like. Assume @AuthorType is an input to the stored procedure and

3条回答
  •  醉话见心
    2021-01-03 15:37

    I should fight the urge to reduce duplication...but man, that really doesn't feel right to me.

    Would this "feel" better?

    SELECT ... lots of columns and complicated stuff ...
    FROM 
    (
        SELECT MyPK
        FROM TBooks
        WHERE 
        (--...SOME CONDITIONS) 
        AND @AuthorType = 1 AND --...DIFFERENT CONDITIONS) 
        union all 
        SELECT MyPK
        FROM TBooks
        WHERE 
        (--...SOME CONDITIONS) 
        AND @AuthorType = 2 AND --...DIFFERENT CONDITIONS) 
        union all 
        ... 
    ) AS B1
    JOIN TBooks AS B2
        ON B2.MyPK = B1.MyPK
    JOIN ... other tables ...
    

    The pseudo table B1 is just the WHERE clause to get the PKs. That is then joined back to the original table (and any others that are required) to get the "presentation". This avoids duplicating the Presentation columns in every UNION ALL

    You can take this a step further and insert PKs into a temporary table first, and then join that to the other tables for the presentation aspect.

    We do this for very large tables where the user has lots of choices on what to query on.

    DECLARE @MyTempTable TABLE
    (
        MyPK int NOT NULL,
        PRIMARY KEY
        (
            MyPK
        )
    )
    
    IF @LastName IS NOT NULL
    BEGIN
       INSERT INTO @MyTempTable
       (
            MyPK
       )
       SELECT MyPK
       FROM MyNamesTable
       WHERE LastName = @LastName -- Lets say we have an efficient index for this
    END
    ELSE
    IF @Country IS NOT NULL
    BEGIN
       INSERT INTO @MyTempTable
       (
            MyPK
       )
       SELECT MyPK
       FROM MyNamesTable
       WHERE Country = @Country -- Got an index on this one too
    END
    
    ... etc
    
    SELECT ... presentation columns
    FROM @MyTempTable AS T
        JOIN MyNamesTable AS N
            ON N.MyPK = T.MyPK -- a PK join, V. efficient
        JOIN ... other tables ...
            ON ....
    WHERE     (@LastName IS NULL OR Lastname @LastName)
          AND (@Country IS NULL OR Country @Country)
    

    Note that all tests are repeated [technically you don;t need the @Lastname one :) ], including obscure ones which were (lets say) not in the original filters to create @MyTempTable.

    The creation of @MyTempTable is designed to make the best of whatever parameters are available. Perhaps if both @LastName AND @Country are available that is far more efficient at filling the table than either one of them, so we create a case for that scenario.

    Scaling problems? Review what actual queries are being made and add cases for the ones that can be improved.

提交回复
热议问题