Search code examples
sql-serverindexingviewdatabase-performance

Speed up view performance


I have an old view that takes 4 mins to run, I have been asked to speed it up. The FROM looks like this:

FROM TableA
CROSS JOIN ViewA
INNER JOIN TableB on ViewA.Name = TableB.Name
   AND TableA.Code = TableB.Code
   AND TableA.Location = TableB.Location
WHERE (DATEDIFF(m, ViewA.SubmitDate, GETDATE()) = 1) -- Only pull last months rows

Table A has around 99k rows, ViewA has around 2000 rows and TableB has around 101K rows. I think the problem is at the INNER JOIN because it I remove it, the query takes 1 second.

My first thought was to see if I could down the number of rows in ViewA by breaking the whole thing into CTEs but this made zero impact. I am thinking I need to index TableB, because it is just a bunch of varchars being used in the joins. I am now changing it to temp tables so I can index it. I can not change the underlying tables and views. Is index temp tables a good way to go, or is there a better solution.

Edit to add info regarding existing indexes. Only thing with an index on it right now is TableA.Id which is the PK and a clustered Index. TableB has an Id field but it is not the PK. ViewA is not indexed.

Edit again to correct some structure. SubmitDate is in the View, not the table.

Here is a very basic structure:

    CREATE TABLE TableA
    (
        Id int NOT NULL PRIMARY KEY,
        Section varchar(20) NULL,
        Code varchar(20) NULL
    )


    CREATE TABLE TableB
    (
        Id int NOT NULL PRIMARY KEY,
        Name varchar(20) NULL,
        Code varchar(20) NULL,
        Section varchar(20) NULL
    )

    CREATE TABLE TableC
    (
        Id int NOT NULL PRIMARY KEY,
        Name varchar(20) NULL,
        SubmitDate DateTime NOT NULL
    )

    CREATE TABLE TableD
    (
        Id int NOT NULL PRIMARY KEY,
        Section varchar(20) NULL
    )

    CREATE VIEW ViewA
    AS
    SELECT c.Section, d.Name, c.SubmitDate
    FROM TableC c
    JOIN TableD d ON a.Id = b.Id

Solution

  • One improovement is to rewrite where clause into sargable clause. Add index to SubmitDate if there is no index and change query to:

    FROM TableA
    CROSS JOIN ViewA
    INNER JOIN TableB on ViewA.Name = TableB.Name
       AND TableA.Code = TableB.Code
       AND TableA.Location = TableB.Location
    WHERE 
    TableA.SubmitDate >=DATEADD(MONTH,DATEDIFF(MONTH,0,GETDATE())-1,0) 
    And TableA.SubmitDate < Dateadd(DAY, 1, DATEADD(MONTH, 
      DATEDIFF(MONTH, -1, GETDATE())-1, -1) )
    

    Also add nonclustered indexes on Name, Code and Location columns.