Sepehr Davarnia
Sepehr Davarnia

Reputation: 97

How to increase performance of this query?

I have an SQL query, it is running on MSSQL 2008 R2 View vMobileLastMobileHistory has about 1000 rows and select * from vMobileLastMobileHistory is taking 0.2 sec

but this query is taking 5 seconds, how can I optimize this code? (I think the problem is INTERSECT but I dont know how change this)

SELECT DISTINCT *
FROM
    (
        SELECT  vMobileLastMobileHistory.* 
        FROM    vMobileLastMobileHistory
            LEFT OUTER JOIN MobileType_DomainAction ON 
                MobileType_DomainAction.tiMobileType = vMobileLastMobileHistory.tiMobileType
        LEFT OUTER JOIN MobileType_User ON 
            MobileType_User.MobileID = MobileType_DomainAction.ID
        WHERE MobileType_User.UserID = @UserID OR @UserID = - 1 

        INTERSECT

        SELECT  vMobileLastMobileHistory.*  
        FROM    vMobileLastMobileHistory
            LEFT OUTER JOIN dbo.Region_User ON 
                dbo.vMobileLastMobileHistory.strRegion = dbo.Region_User.strRegion
        WHERE Region_User.iSystemUser = @UserID OR @UserID = - 1

        INTERSECT

        SELECT vMobileLastMobileHistory.* 
        FROM vMobileLastMobileHistory
        LEFT OUTER JOIN Contractor_User ON 
            vMobileLastMobileHistory.strContractor = Contractor_User.strContractor
        WHERE Contractor_User.iSystemUser = @UserID OR @UserID = - 1
    )

Upvotes: 1

Views: 68

Answers (2)

Ajay2707
Ajay2707

Reputation: 5808

Most of time Intersect and Inner Join will be same. You are not share your data, so based on my knowledge and this link, I just replace intersect query into Inner join query as :

--I think you don't need distinct upper query. If you have issue inform me.

        SELECT DISTINCT vml.* 
        FROM   vMobileLastMobileHistory vml
            LEFT OUTER JOIN MobileType_DomainAction mtda ON mtda.tiMobileType = vml.tiMobileType
            LEFT OUTER JOIN MobileType_User ON MobileType_User.MobileID = mtda.ID
            LEFT OUTER JOIN dbo.Region_User ON dbo.vml.strRegion = dbo.Region_User.strRegion
            LEFT OUTER JOIN Contractor_User ON vml.strContractor = Contractor_User.strContractor
        WHERE 
        (MobileType_User.UserID = @UserID 
        and Region_User.iSystemUser = @UserID or Contractor_User.iSystemUser = @UserID
        ) OR @UserID = - 1        

Upvotes: 0

GarethD
GarethD

Reputation: 69819

The problem is that if you have any indexes on your iSytemUser columns, the optimise is unable to use them because it has to account for a specific userID being passed, or returning all results, it would be better to logically separate your two cases. In addition, since you don't care about any columns in the auxiliary tables, you could use EXISTS in your case of specific users to take advantage of a semi join:

IF (@UserID = -1)
BEGIN
    SELECT  DISTINCT *
    FROM    vMobileLastMobileHistory;
END
ELSE
BEGIN
    SELECT  DISTINCT *
    FROM    vMobileLastMobileHistory AS mh
    WHERE   EXISTS 
            (   SELECT  1 
                FROM    Contractor_User AS cu 
                WHERE   cu.strContractor = mh.strContractor 
                AND     cu.iSystemUser = @UserID
            )
    AND     EXISTS 
            (   SELECT  1 
                FROM    Region_User AS ru 
                WHERE   ru.strRegion = mh.strRegion 
                AND     ru.iSystemUser = @UserID
            )
    AND     EXISTS 
            (   SELECT  1 
                FROM    MobileType_DomainAction AS da 
                        INNER JOIN MobileType_User AS mu
                            ON mu.MobileID = da.ID
                WHERE   da.tiMobileType = mh.tiMobileType 
                AND     mu.iSystemUser = @UserID
            );

END 

Now you can have two execution plans for each case (returning all results, or for a specific user), in each case you only need to read from vMobileLastMobileHistory once, and you also limit the sorts required by removing the INTERSECT and replacing with 3 EXISTS clauses.

If they don't already exist then you may also which to consider some indexes on your tables. A good way of finding out what indexes would help is to run the query in SQL Server Management Studio with the option "Show Actual Execution Plan" enabled, this will then show you any missing indexes.

Upvotes: 1

Related Questions